Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Your task is to take an input string of ascii characters and output the string as a series of vertical words separated by spaces. An example is shown below:

Given the string:

Hello, World! My name is Foo.

the output should be:

H W M n i F
e o y a s o
l r   m   o
l l   e   .
o d
, !

10 bonus points will be awarded if your program correctly handles strings which need to wrap-around the terminal, which we'll set at 80 characters.

50 points if your program can also do the reverse!

share|improve this question
    
Quite similar to Transpose a page of text. –  manatwork Feb 21 at 12:29
3  
@manatwork: I suppose it is. It's not identical though - and I might argue my problem is a little easier. –  Foo Barrigno Feb 21 at 12:31
    
It's not 100% identical, but it's close enough to count as a duplicate: the reduction to make it identical is just replacing each space with two newlines. –  Peter Taylor Feb 21 at 14:04
1  
@PeterTaylor: Not quite. My problem has no requirement to respect newlines in the original string. That problem requires that new lines be converted into spaces, and spaces converted into two newlines. It's not quite a trivial reduction. –  Foo Barrigno Feb 21 at 14:09
add comment

23 Answers 23

up vote 8 down vote accepted

J, 15

|:>'\S+| 'rxall

Usage:

   |:>'\S+| 'rxall 'Hello, World! My name is Foo.'
H W M n i F
e o y a s o
l r   m   o
l l   e   .
o d        
, !        
share|improve this answer
    
Very nicely done. Accepting your answer. –  Foo Barrigno Mar 20 at 10:45
add comment

Javascript - 228 172 145 126

A=prompt().split(" "),B="",N=A;for(y=0;y<N.length;y++){for(i=0;i<N.length;i++){if(A[i][y]){B+=A[i][y];}else{B+=" ";}}B+="\n";}

My first code golf :)

share|improve this answer
    
Its great for your first attempt! –  Foo Barrigno Feb 21 at 12:54
    
Thank you very much –  Wolle Vanillebär Lutz Feb 21 at 12:54
    
You should attempt to make your code as short as possible, for instance, remove spaces, also "Input ?" doesn't really affect the program's behaviour, remove it too. –  mniip Feb 21 at 12:54
    
Fixed Bugs. Should work as expected :) –  Wolle Vanillebär Lutz Feb 21 at 13:11
1  
Works correctly now. But some minor things: no need for variable N, store the array's length instead of asking it twice, some pointless braces, some unnecessary semicolons. A=prompt().split(" "),B="";for(y=0;y<(l=A.length);y++){for(i=0;i<l;i++)if(A[i][y])B+=A[i][y];else B+="_";B+="\n"}alert(B). (In the JavaScript Standards for IO meta question the mostly agreed opinion was that relying on REPL's implicit output should not be considered correct.) –  manatwork Feb 21 at 13:28
show 3 more comments

Ruby, 91 87

s=gets.split
puts s.map{|x|x.ljust(s.map(&:size).max,' ').split''}.transpose.map &:join

Hooray, I beat Perl! :D

Ruby, 150 - 50 bonus = 100

s=$<.read
n=s.index"
"
s=s.split n ?'
':' '
o=s.map{|x|x.ljust(s.map(&:size).max,' ').split''}.transpose.map &:join
puts n ?o.map(&:strip).join(' '):o

It just detects for newlines, and applies special handling if they are detected.

Run it like

ruby transposegolf.rb < transposegolfinput.txt
share|improve this answer
add comment

Javascript 184 149 123

var a=s.split(" "),b="",c;for(c in a)b+="<div style='float:left'>"+a[c].split("").join("<br>")+"</div>";document.write(b);

With the example string defined:

var s = "Hello, World! My name is Foo.";
var a=s.split(" "),b="",c;for(c in a)b+="<div style='float:left'>"+a[c].split("").join("<br>")+"</div>";document.write(b);

You can copy the second statement to you browsers console.

Unminified:

var res = "Hello, World! My name is Foo.";
var t=res.split(" ");
var s ="";
for (var word in t){
    s+="<div style='float:left'>" + t[word].split("").join("<br />") + "</div>";
}
document.write(s);

JsFiddle Link: http://jsfiddle.net/FzMvK/

My first code golf post :P

share|improve this answer
    
Very nicely done –  Foo Barrigno Feb 21 at 13:16
    
@FooBarrigno updated answer to support reverse –  RononDex Feb 21 at 13:28
    
@FooBarrigno Updated answer, removed reverse support and changed logic completely to reduce byte count –  RononDex Feb 21 at 15:15
    
Clever, I like it. Can't you just change to float:right for reverse? –  Danny Feb 21 at 16:26
2  
Depends what "reverse" means. If the first letter should be at the bottom then it wont work. If it is simply reversing the words, then it should work yes –  RononDex Feb 21 at 16:57
show 2 more comments

APL, 22

{⍉⊃⍵⊂⍨1+0,+\2≠/⍵=' '}

Explanation

{              ⍵=' '}   A. check which chars are spaces           
            2≠/         B. of that vector, which consecutive pairs are different  
          +\            C. compute the partial sums                           
      1+0,              D. insert 0 at the front and add 1 to every item
   ⍵⊂⍨                     use this vector to split the original string
 ⍉⊃                        disclose into a matrix and transpose

    'W o w   S u c h   D o g e'
A.   0 0 0 1 0 0 0 0 1 0 0 0 0
B.    0 0 1 1 0 0 0 1 1 0 0 0
C.    0 0 1 2 2 2 2 3 4 4 4 4
D.  1 1 1 2 3 3 3 3 4 5 5 5 5

Example

      {⍉⊃⍵⊂⍨1+0,+\2≠/⍵=' '} 'Hello, World! My name is Foo.'
H W M n i F
e o y a s o
l r   m   o
l l   e   .
o d        
, !        
share|improve this answer
add comment

Perl - 92 97

$_=<>;chop;@x=split$";do{print((substr$_,$q,1or$").$")for@x;$q++,print$/}while/@{['\S'x$q]}/

Does the job in a pretty straightforward way.

share|improve this answer
    
No need for parenthesis around statement modifiers' expressions. –  manatwork Feb 21 at 12:45
    
Note that while as used here is also statement modifier. –  manatwork Feb 21 at 12:51
    
Is it? Is it not a do{}while() loop? –  mniip Feb 21 at 12:55
    
Nope. do itself has nothing else, just a block. The while is a separate thing. –  manatwork Feb 21 at 13:00
add comment

K, 33

{" "/:',:''x@'/:!max@#:'x:" "\:x}

Example input and output:

k){" "/:',:''x@'/:!max@#:'x:" "\:x}"Hello, World! My name is Foo."
"H W M n i F"
"e o y a s o"
"l r   m   o"
"l l   e   ."
"o d        "
", !        "
share|improve this answer
    
Are the " supposed to be there? –  belisarius Feb 21 at 13:34
    
@belisarius It's how strings are represented in k. If you specifically want to write to stdout then you can with {-1@" "/:',:''x@'/:!max@#:'x:" "\:x;} (37 chars), which would produce the output without " –  tmartin Feb 21 at 14:00
4  
Well, I think the output should be the required one, notwithstanding the language –  belisarius Feb 21 at 14:02
add comment

Python:

One line of code to process the sting:

import sys
m = "Hello, World! My name is Foo."

map(lambda y: sys.stdout.write(' '.join(y)+'\n'), zip(*map(lambda x: x.ljust(max(map(len,m.split()))), m.split())))
share|improve this answer
add comment

Python 2.7, 108 103

I'm sure this can be golfed more, but here's an initial solution in python.

w=raw_input().split();m=max(map(len,w));i=0
while i<m:print" ".join(map(lambda x:x.ljust(m)[i],w));i+=1

Improvements:

  • split(" ") => split()
  • removed some extra spaces
share|improve this answer
    
Nice job! If you start with i=m and loop down to 0, you can shave another 3 characters for an even 100. –  DLosc Jun 9 at 0:30
add comment

F#, 187

let o=Console.ReadLine()
let s=o.Split(' ')
let m=s|>Seq.map String.length|>Seq.max
for l=0 to m-1 do
 for w in s|>Seq.map(fun x->x.PadRight(m,' ').[l])do printf"%c "w
 printfn"%s"""
share|improve this answer
add comment

Ruby, 63

$F.map(&:size).max.times{|i|puts$F.map{|s|s[i]||' '}.join' '}

The algorithm is very straightforward; only golfed. Code is 61 bytes long, plus 2 bytes for the -na options that it needs to work. From ruby -h:

-n   assume 'while gets(); ... end' loop around your script
-a   autosplit mode with -n or -p (splits $_ into $F)

Sample run:

$ echo 'This sentence is false' | ruby -na cols.rb
T s i f
h e s a
i n   l
s t   s
  e   e
  n    
  c    
  e
share|improve this answer
add comment

Python 2.7 - 137 112 bytes

s=raw_input().split()
for c in range(max(map(len,s))):
 for w in s:
    try:print w[c],
    except:print' ',
 print''

Someone else has already done it better, but I might as well throw this up. Adds spaces to each word in the input until it's the same length as the longest one (to avoid index errors for the next part), then prints the cth letter of every word while c goes from 0 to the length of each string.

I came up with a much better way of doing this and cut out 25 bytes. Rather than padding strings with spaces to avoid the index error, I handle the error directly! Whenever there's nothing to print, I print a single space in its place with try:print w[c],, except:print' ',. I also remembered that I don't need a space between a print statement and a string literal, which saved one byte.

Note that Python 2 allows you to mix tabs and spaces and considers them separate levels of indentation. SE's Markdown interpreter replaces a tab character with four spaces, but every line of this program except the first has exactly one byte of indentation.

Formatting was pretty easy, since print 'something', prints 'something ' rather than 'something\n'. I did that for each character, and used an empty print statement to get the newline where I needed it.

share|improve this answer
add comment

C, 111 110 95 90 bytes

This solution uses VT-100 control codes to move the cursor on the terminal

main(int _,char**v){char*s=*++v;printf("^[7");while(*s)' '==*s?(s++,printf("^[8^[[2C^[7")):printf("%c^[[B^H",*s++);}

the ^[ sequence is a placeholder for the single ASCII ESC character, that can't be displayed here.

  • ^[7 saves the current pointer position
  • ^[8 restores the cursor position to the saved position
  • ^[[2C moves 2 steps right
  • ^[[B moves 1 step down

edit 1: the ^[[D (1 step left) VT-100 code has been replaced by a backspace (shown as ^H here, but is only one ASCII char) ; also forgot the "separated by spaces" instruction, now fixed

edit 2:

7 chars saved by using a for loop instead of while, and 32 instead of ' ':

main(int _,char**v){printf("^[7");for(char*s=*++v;*s;s++)32==*s?printf("^[8^[[2C^[7"):printf("%c^[[B^H",*s);}

8 more chars saved by calling one less printf: the ternary ?: operator is now used in the printf parameters

main(int _,char**v){printf("^[7");for(char*s=*++v;*s;s++)printf(32==*s?"^[8^[[2C^[7":"%c^[[B^H",*s);}

edit 3:

Got rid of the local variable s, working directly with argv aka v. This is totally hideous. But saved 4 chars. Also replaced == with ^ and therefore switched the ?: operands, to save 1 more char.

main(int c,char**v){printf("^[7");for(v++;**v;)printf(32^*(*v)++?"%c^[[B^H":"^[8^[[2C^[7",**v);}

Usage

$ gcc transpose.c -o transpose --std=c99
$ ./transpose 'Hello, World! My name is Foo.'
H W M n i F
e o y a s o
l r   m   o
l l   e   .
o d
, !

Un-golfed version (first version)

main (int _,char**v) {
    char*s=*++v; // init s with the address of the first letter
    printf("^[7"); // save the current cursor position
    while(*s) 
        ' '==*s ? ( /* if current char is a space */
            s++,printf("^[8^[[2C^[7") /* return to the saved location, move right, save position */
        ) : /* kind of else */
            printf("%c^[[B^H",*s++); /* print the current char, move down, move left */
}

Un-golfed version (last version)

main(int c,char**v) {
    printf("^[7");
    for(v++;**v;) /* v++: make v point to argv[1] */
        printf(     
            32^*(*v)++? /* test if **v is different from ' ', and make *v point to
                           the next char */
                "%c^[[B^H":         
                "^[8^[[2C^[7",      
            **v); /* this undefined behaviour (using *v and (*v)++ in the same expression)
                     works as "expected" with gcc 4.7.2 */
} 
share|improve this answer
    
That un-golfed version looks suspiciously like Befunge. :) –  DLosc Jun 9 at 0:20
add comment

I answered this question 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.

share|improve this answer
    
I have no idea why this is CW. I might have hit the button by accident. Oh well. –  undergroundmonorail Jun 10 at 18:03
add comment

Mathematica 49

Clearly Mathematica isn't the best for this one:

Grid[PadRight@Characters@StringSplit@s^T]/. 0->" "

Mathematica graphics

Note ^T (transpose) is only one char (I can't find the right char code now)

share|improve this answer
add comment

Javascript, 141

a=prompt().split(' '),c=0,d=a.map(function(a){b=a.length;c=c<b?b:c});for(j=0;j<c;j++){b='';for(i in a)b+=a[i][j]?a[i][j]:' ';console.log(b);}

Sample

hello, world! this is code golf

hwticg
eohsoo
lri dl
lls ef
od    
,! 
share|improve this answer
add comment

GolfScript [41 bytes]

' '%:x{.,x{,}%$-1=-abs' '*+}%zip{' '*}%n*

How it works:

' '%:x          split text into words and store array in 'x'
{               for each word in the array:
    .,              from word's length
    x{,}%$-1=-      substract the length of the longest word in 'x'
    abs             get absolute value (maybe there is a shorter way?)
    ' '*+           add corresponding number of spaces
}%
zip{' '*}%      transpose array of words and add spaces between letters
n*              join words with a new line character

You may see the online demo here.

P.S.: This is my first GolfScript code ever, so don't judge me strictly ;)

share|improve this answer
add comment

R, 116

z=t(plyr::rbind.fill.matrix(lapply(strsplit(scan(,""),""),t)));z[is.na(z)]=" ";invisible(apply(cbind(z,"\n"),1,cat))
share|improve this answer
add comment

Bash + coreutils, 54

eval paste `printf " <(fold -w1<<<%s)" $@`|expand -t2

Output:

$ ./transpose.sh Hello, World! My name is Foo.
H W M n i F
e o y a s o
l r   m   o
l l   e   .
o d       
, !       
$ 
share|improve this answer
add comment

Python 2.7 - 119 106

Take 1 - 166. The reversing of lists was needed to make pop work in the order I wanted, but this seemed wasteful. And when I tried to combine into a single comprehension for fun, the pop screwed things up.

w=raw_input().split(' ');l=max([len(l) for l in w]);
q=[list(p)[::-1]for p in w]+[['\n']*l]
t=[' '+(v.pop() if v else' ')for i in range(l)for v in q]
print ''.join(t)

Take 2 - 119. So I changed to simple list indexing. Still seems clunky though, especially the padding of spaces and new lines.

w=raw_input().split(' ');l=max([len(l)for l in w]);print''.join([' '+(v+' '*l)[i]for i in range(l)for v in w+['\n'*l]])

Take 3 - thanks to @grc

w=raw_input().split();l=max(map(len,w));print''.join(' '+(v+' '*l)[i]for i in range(l)for v in w+['\n'*l])
share|improve this answer
2  
[len(l)for l in w] can be shortened to map(len,w), .split(' ') to .split(), and .join([...]) to .join(...). –  grc Feb 21 at 13:57
    
I haven't gone over your code in too much detail so this might not work, but: "The reversing of lists was needed to make pop work in the order I wanted" Couldn't you use v.pop(0) to pop the first element instead of the last one? –  undergroundmonorail Feb 21 at 14:12
add comment

Python 3, 124

a=input().split()
l=max(map(len,a))
print("\n".join(" ".join(c[i] for c in [i+" "*(l-len(i)) for i in a]) for i in range(l)))
share|improve this answer
add comment

Haskell, 112

Golfed:

import Data.List
r s=unlines$transpose$p$words s
p w=m(\s->s++replicate(maximum(m l w)-l s)' ')w
m=map
l=length

Explained:

import Data.List

-- Break on spaces, then pad, then transpose, then join with newlines
r s=unlines$transpose$p$words s

-- Pads each String in a list of String to have the same length as the longest String
p w=m(\s->s++replicate(maximum(m l w)-l s)' ')w

-- Aliases to save space
m=map
l=length

Example:

*Main Data.List> putStrLn $ r "Hello Doge"
HD
eo
lg
le
o
share|improve this answer
add comment

JavaScript, 139 (156 with console.log output)

s=" ",b="",a=prompt().split(s),l=0;for(var i in a){m=a[i].length;l=(l<m)?m:l;}for(i=0;i<l;i++){for(var j in a)b+=((x=a[j][i])?x:s)+s;b+="\n"}console.log(b);

I think this is as golfed as I can get it. I just split, find the largest word and transpose accordingly, adding spaces if the char doesn't exist in the shorter words. More than the previous submitted JavaScript answer, but that answer doesn't seem to work?

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.