J, 35 33 bytes
3 :'[;.0>(,|:)&:,.&.>/_98{.;:|.y'
This is a verb that takes the input as a single string with the words separated by spaces. For example, you could call it like this:
3 :'[;.0>(,|:)&:,.&.>/_98{.;:|.y' 'programming puzzles and code golf'
The output is a matrix of letters and spaces, which the interpreter outputs with newlines as required. Each line will be padded with spaces so they have the exact same length.
There's one slight problem with the code: it won't work if the input has more than 98 words. If you want to allow a longer input, replace the _98
in the code by _998
to allow up to 998 words, etc.
Let me explain how this works through some examples.
Suppose we have a matrix of letters and spaces that we imagine is a partial output for some words, starting with a horizontal word.
[m=: 3 3$'vwx y z'
vwx
y
z
How could we prepend a new word before this, vertically? It's not hard: just turn the new word to a single-column matrix of letters with the verb ,.
, then append the output to that single-column matrix. (The verb ,.
is convenient because it behaves as an identity function if you apply it to a matrix, which we use for golfing.)
(,.'cat') , m
c
a
t
vwx
y
z
Now we can't just iterate this way of prepending a word as is, because then we'd only get vertical words. But if we transpose the output matrix between each step, then every other word will be horizontal.
(,.'dog') , |: (,.'cat') , m
d
o
g
catv
w
xyz
So our first attempt for a solution is to put each word into a single-column matrix, then fold these by appending and transposing between them.
> (,|:)&.>/ ,.&.>;: 'car house dog children'
c
a
r
housed
o
g
children
But there's a big problem with this. This puts the first letter of the next word before turning a right angle, but the specification requires turning before putting the first letter, so the output should be something like this instead:
c
a
rhouse
d
o
gchildren
The way we achieve this is to reverse the entire input string, as in
nerdlihc god esuoh rac
then use the above procedure to build the zig-zag but turning only after the first letter of each word:
n
e
r
d
l
i
h
c
gode
s
u
o
h
rac
Then flip the output:
[;.0> (,|:)&.>/ ,.&.>;:|. 'car house dog children'
car
h
o
u
s
edog
c
h
i
l
d
r
e
n
But now we have yet another problem. If the input has an odd number of words, then the output will have the first word vertical, whereas the specification says that the first word must be horizontal. To fix this, my solution pads the list of words to exactly 98 words, appending empty words, since that doesn't change the output.