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!

  • \$\begingroup\$ Quite similar to Transpose a page of text. \$\endgroup\$ – manatwork Feb 21 '14 at 12:29
  • 3
    \$\begingroup\$ @manatwork: I suppose it is. It's not identical though - and I might argue my problem is a little easier. \$\endgroup\$ – Foo Barrigno Feb 21 '14 at 12:31
  • \$\begingroup\$ 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. \$\endgroup\$ – Peter Taylor Feb 21 '14 at 14:04
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ – Foo Barrigno Feb 21 '14 at 14:09

31 Answers 31


J, 15

|:>'\S+| 'rxall


   |:>'\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        
, !        

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 :)

  • \$\begingroup\$ Its great for your first attempt! \$\endgroup\$ – Foo Barrigno Feb 21 '14 at 12:54
  • \$\begingroup\$ 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. \$\endgroup\$ – mniip Feb 21 '14 at 12:54
  • \$\begingroup\$ Fixed Bugs. Should work as expected :) \$\endgroup\$ – Wolle Vanillebär Lutz Feb 21 '14 at 13:11
  • 1
    \$\begingroup\$ 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.) \$\endgroup\$ – manatwork Feb 21 '14 at 13:28
  • 1
    \$\begingroup\$ (untested) if(A[i][y]){B+=A[i][y];}else{B+=" ";} => B+=(x=A[i][y])?x:" " \$\endgroup\$ – daniero Feb 25 '14 at 16:04

APL, 22

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


{              ⍵=' '}   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


      {⍉⊃⍵⊂⍨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        
, !        

Ruby, 91 87

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=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

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.


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>";

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

My first code golf post :P

  • \$\begingroup\$ Very nicely done \$\endgroup\$ – Foo Barrigno Feb 21 '14 at 13:16
  • \$\begingroup\$ @FooBarrigno updated answer to support reverse \$\endgroup\$ – RononDex Feb 21 '14 at 13:28
  • \$\begingroup\$ @FooBarrigno Updated answer, removed reverse support and changed logic completely to reduce byte count \$\endgroup\$ – RononDex Feb 21 '14 at 15:15
  • \$\begingroup\$ Clever, I like it. Can't you just change to float:right for reverse? \$\endgroup\$ – Danny Feb 21 '14 at 16:26
  • 2
    \$\begingroup\$ 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 \$\endgroup\$ – RononDex Feb 21 '14 at 16:57

Perl - 92 97


Does the job in a pretty straightforward way.

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

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        "
", !        "
  • \$\begingroup\$ Are the " supposed to be there? \$\endgroup\$ – Dr. belisarius Feb 21 '14 at 13:34
  • \$\begingroup\$ @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 " \$\endgroup\$ – tmartin Feb 21 '14 at 14:00
  • 4
    \$\begingroup\$ Well, I think the output should be the required one, notwithstanding the language \$\endgroup\$ – Dr. belisarius Feb 21 '14 at 14:02


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())))

Python 2.7, 108 103

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

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


  • split(" ") => split()
  • removed some extra spaces
  • \$\begingroup\$ Nice job! If you start with i=m and loop down to 0, you can shave another 3 characters for an even 100. \$\endgroup\$ – DLosc Jun 9 '14 at 0:30

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

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

Python 2.7 - 137 112 bytes

for c in range(max(map(len,s))):
 for w in s:
    try:print w[c],
    except: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.


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);}


$ 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
        ' '==*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) {
    for(v++;**v;) /* v++: make v point to argv[1] */
            32^*(*v)++? /* test if **v is different from ' ', and make *v point to
                           the next char */
            **v); /* this undefined behaviour (using *v and (*v)++ in the same expression)
                     works as "expected" with gcc 4.7.2 */
  • 1
    \$\begingroup\$ That un-golfed version looks suspiciously like Befunge. :) \$\endgroup\$ – DLosc Jun 9 '14 at 0:20

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

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.



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:


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.

  • 2
    \$\begingroup\$ I have no idea why this is CW. I might have hit the button by accident. Oh well. \$\endgroup\$ – undergroundmonorail Jun 10 '14 at 18:03
  • \$\begingroup\$ You can change print("\n".join(...)) to *map(print,...),. Try it online! \$\endgroup\$ – Jo King Oct 6 '18 at 10:05

05AB1E, score 8 -20 -21 (30 29 bytes - 50 bonus):


Try it online (regular single-line input).
Try it online (multi-line reversed input).


|                     # Take the input split on newlines:
                      #  i.e. 'This is a test' → ['This is a test']
                      #  i.e. 'T i a t\nh s   e\ni     s\ns     t'
                      #    → ['T i a t','h s   e','i     s','s     t']
 Dg                   #  Duplicate this list, and take the length
                      #   i.e. ['This is a test'] → 1
                      #   i.e. ['T i a t','h s   e','i     s','s     t'] → 4
   i         }        # If the length is exactly 1:
    ¹                 #  Take the input again 
     #                #  Split the input-string by spaces
                      #   i.e. 'This is a test' → ['This','is','a','test']
      ζ               #  Zip with space-filler: Swap all rows and columns
                      #   i.e. ['This','is','a','test'] → ['Tiat','hs e','i  s','s  t']
       ε   }          #  For each item:
        S             #   Convert the item to a list of characters
                      #    i.e. 'Tiat' → ['T','i','a','t']
         ðý           #   Join them by a single space
                      #    i.e. ['T','i','a','t'] → 'T i a t'
            »         #  Join the result by newlines (and output implicitly)
    ë                 # Else:
     ε    }           #  For each item:
      2ô              #   Split it into chunks of two characters
                      #    i.e. 'h s   e' → ['h ','s ','  ','e']
        €¬            #   Take the head (first character) of each:
                      #    i.e. ['h ','s ','  ','e'] → ['h','s',' ','e']
           ζ          #  Zip with space-filler: Swap all rows and columns
                      #   i.e. [['T','i','a','t'],['h','s',' ','e'],['i',' ',' ','s'],['s',' ',' ','t']]
                      #     → [['T','h','i','s'],['i','s',' ',' '],['a',' ',' ',' '],['t','e','s','t']]
            J         #  Join each inner list to a single string
                      #   i.e. [['T','h','i','s'],['i','s',' ',' '],['a',' ',' ',' '],['t','e','s','t']]
                      #     → ['This','is  ','a   ','test']
             ε  }     #  For each item:
              ðÜ      #   Remove any trailing spaces
                      #    i.e. 'is  ' → 'is'
                 ðý   #  Join the items by a single space (and output implicitly)

Original 8-byte answer:


Try it online.


#           # Split the input-string by spaces
            #  i.e. 'This is a test' → ['This','is','a','test']
 ζ          # Zip with space-filler: Swap all rows and columns
            #  i.e. ['This','is','a','test'] → ['Tiat','hs e','i  s','s  t']
  ε   }     # For each item:
   S        #  Convert the item to a list of characters
            #   i.e. 'Tiat' → ['T','i','a','t']
    ðý      #  Join them by a single space
            #   i.e. ['T','i','a','t'] → 'T i a t'
       »    # Join the result by newlines (and output implicitly)

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)


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);}


hello, world! this is code golf

lri dl
lls ef

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 ;)


R, 116

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

Bash + coreutils, 54

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


$ ./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       
, !       
  • \$\begingroup\$ Suggestion for an update: backticks for command substitution is depreciated. Using the $() construct is now the common method for command substitution. \$\endgroup\$ – Yokai Jul 31 '18 at 9:23
  • \$\begingroup\$ @Yokai - This is code-golf - here we are optimizing for code length and not for standards/best-practices compliance. codegolf.stackexchange.com/a/25572/11259 \$\endgroup\$ – Digital Trauma Jul 31 '18 at 16:34
  • \$\begingroup\$ I figured since the norm had changed for command substitution, I would suggest an update. You don't have to. It was just a suggestion. It would only add a single new character to the count anyways. \$\endgroup\$ – Yokai Aug 1 '18 at 8:27

APL: 18

⍉↑1↓¨a⊂⍨' '=a←' ',


a←' ', put a space in front of the string and assign to a

' '= find spaces, produces a boolean

1↓¨a⊂⍨ make substrings starting where the boolean has 1's and drop first element of each (so the space)

⍉↑ Make matrix out of the resulting substrings, and reverse it along the diagonal


R, 81 bytes

Save a byte by storing a newline as e, which can be used in both scan calls, the compare call and cat.

"));while(any((s=substr(w,F<-F+1,F))>e))cat(pmax(" ",s),e)

Try it online!


K (oK), 26 bytes


`0:{" "/'+(|/#:'x)$x}@" "\

Try it online!


`0:{" "/'+(|/#:'x)$x}@" "\ / the solution
                      " "\ / split input on whitespace
   {                }@     / apply (@) lambda
                  $x       / pad ($) input (x)
          (      )         / do this together
             #:'x          / count (#:) each (')
           |/              / max
         +                 / transpose / flip
    " "/'                  / join each with whitespace
`0:                        / print to stdout

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])
  • 2
    \$\begingroup\$ [len(l)for l in w] can be shortened to map(len,w), .split(' ') to .split(), and .join([...]) to .join(...). \$\endgroup\$ – grc Feb 21 '14 at 13:57
  • \$\begingroup\$ 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? \$\endgroup\$ – undergroundmonorail Feb 21 '14 at 14:12

Python 3, 124

print("\n".join(" ".join(c[i] for c in [i+" "*(l-len(i)) for i in a]) for i in range(l)))

Haskell, 112


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


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


*Main Data.List> putStrLn $ r "Hello Doge"

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?


Japt -R, 5 bytes


Try it


¸         :Split on spaces
 y        :Transpose
  ¬       :Split columns
   m      :Map rows
    ¸     :  Join with spaces
          :Implicitly join with newlines and output

Pyth, 8 bytes

jbjL\ Cc

Try it online!

Pretty straightforward. Takes input enclosed in quotes, i.e. "Hello World"

jbjL\ CcQ
       cQ    Chop the input Q on spaces
      C      Matrix transpose
  jL\        Join each element by spaces,
             i.e. interleave spaces between the characters of each element
jb           Join by newlines
  • 1
    \$\begingroup\$ C truncates to the length of the shortest entry, so this doesn't work. Here's a quick fix which is also 8 bytes. \$\endgroup\$ – hakr14 Aug 1 '18 at 4:49

APL(NARS), 79 chars, 158 bytes

{m←⌈/↑∘⍴¨z←(' '≠⍵)⊂,⍵⋄v←∊m{⍵\⍨∊(k⍴1)(0⍴⍨⍺-k←↑⍴⍵)}¨z⋄((2×↑⍴z)⍴1 0)\[2]⍉(↑⍴z)m⍴v}


  f←{m←⌈/↑∘⍴¨z←(' '≠⍵)⊂,⍵⋄v←∊m{⍵\⍨∊(k⍴1)(0⍴⍨⍺-k←↑⍴⍵)}¨z⋄((2×↑⍴z)⍴1 0)\[2]⍉(↑⍴z)m⍴v}
  f '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         
, !         

The old function have output not perfect:

  {⍪¨(' '≠⍵)⊂,⍵}'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             
 ,  !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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