I [answered this question](http://codegolf.stackexchange.com/a/21659/14509) a long time ago. It was one of my first contributions to the site, actually. I recently came across it again and was kind of embarrassed. 112 bytes?! Unacceptable. So I gave it another shot:
#Python 3 - 92 bytes
s=input().split()
print('\n'.join(map(' '.join,zip(*[a.ljust(max(map(len,s)))for a in s]))))
In the 109 days since I posted that first answer, I like to think I've come a long way. Even something like using Python 3 over 2.71 wouldn't have occurred to me. With this code golfed down to under 100 bytes, my soul can finally rest and I can proceed to the afterlife.
Explanation
s=input().split()
This gets a line from stdin
and creates a list by splitting it at whitespace characters. The only whitespace likely to be in the input is spaces, so this line gets a list of words.
Let's take the second line from the inside out:
max(map(len,s))
map
takes a function and an iterable as arguments. It applies the function to each element of the iterable, and returns a new iterable of the results. Here, I create an iterable with the lengths of each input word. max
gets the maximum value from an iterable. This gets us the longest word in the input.
[a.ljust( )for a in s]
A list comprehension is similar to map
. It does something to every element of an iterable, and returns a list the results. For every word in the input, I do that_word.ljust(
some code)
. ljust
is short for "left justify". It takes an integer as an argument and adds spaces to the string until it's that long.
zip(* )
This is a neat trick. In this context, *
means "unzip this iterable as multiple arguments". This way, zip
can be used to transpose a matrix (e.g. zip(*[(1,2),(3,4)])
-> [(1,3),(2,4)]
). The only restriction is that all the rows in the matrix have to be the same length, or elements from all rows but the shortest are cut off to match.
map(' '.join, )
We already know what map
does. The only new thing here is join
, which takes an iterable of strings and makes it a single string using the delimiter it's attached to. For example, 'a'.join(['I', 'can', 'play', 'the', 'saxophone'])
2 becomes Iacanaplayatheasaxophone
.
print('\n'.join( ))
This join
takes a bunch of strings and seperates them by newlines. All that's left is to print
to stdout
and we're done!
All together now:
print('\n'.join(map(' '.join,zip(*[a.ljust(max(map(len,s)))for a in s]))))
Find the length of the longest word from the input, append spaces to every word until they're the same length, transpose with the zip(*
3 trick, use join
to seperate each character in a row with spaces, join
again to seperate each row with a newline, and print! Not bad for the only non-input-handling line in a 92 byte program.
1. The extra characters spent on print()
's parentheses are outweighed by the 4 characters I drop from raw_input()
->input()
.
2. I can't actually play the saxophone.
3. )
. You're welcome.