Staircase writing

Retina, 50 44 34 (+10) 32 30 bytes

Thanks to Dennis for saving 14 bytes by using actual control characters.

i`[aeiouy]
<VT>$0#
+`#(\S*)
$1<ESC>[A

Based on this answer, I'm using ANSI escape codes to move the terminal cursor vertically. The <ESC> should be replaced with the control character 0x1B, and <VT> with the vertical tab 0x0B. For simpler testing, you can also replace <ESC> with \e, <VT> with \v and feed the output through printf.

For counting purposes, each line goes in a separate file. However, for convenience it's simpler to just paste the code into a single file and invoke Retina with the -s option.

The first replacement surrounds each vowel in \v...#, where the \v shifts the cursor downward and the # is a marker for the second step. The i` is Retina's notation for case-insensitive matching.

The second step then repeatedly (+`) removes a # from a word and puts a e\[A at the end of the word which shifts the cursor upward. This stops once the string stops changing, i.e. when there are no more # markers in the string.


CJam, 39 36 bytes

0000000: 6c 7b 5f 65 6c 22 61 65 69 6f 75 79 22  l{_el"aeiouy"
000000d: 26 7b 22 1b 5b 41 22 27 0b 6f 5c 7d 26  &{".[A"'.o\}&
000001a: 5f 53 26 7b 5d 7d 26 6f 7d 2f           _S&{]}&o}/

The above is a reversible xxd dump, since the source code contains the unprintable character VT (code point 0x0b) and ESC (code point 0x1b).

Like this answer, it uses vertical tabs and ANSI escape sequences.

This requires a supporting video text terminal, which includes most non-Windows terminal emulators.

Test run

Before executing the actual code, we'll disable the prompt and clear the screen.

$ PS1save="$PS1"
$ unset PS1
$ clear

This makes sure the output is shown properly.

echo -n Programming Puzzles and Code Golf | cjam <(xxd -ps -r <<< 6c7b5f656c226165696f757922267b221b5b4122270b6f5c7d265f53267b5d7d266f7d2f)
Pr          P           C    G
  ogr        uzzl   and  od   olf
     amm         es        e
        ing

To restore the prompt, execute this:

PS1="$PS1save"

How it works

We insert a vertical tab before each vowel to move the cursor down and sufficient copies of the byte sequence 1b 5b 41 ("\e[A") after each space to move the cursor back to the first row.

l           e# Read a line from STDIN.
{           e# For each character C:
  _el       e#   Push lowercase(C).
  "aeiouy"& e#   Intersect with "aeiouy".
  {         e#   If the intersection is non-empty:
    ".[A"   e#     Push "\e[A" (will be printed later).
    '.o     e#     Print "\v".
    \       e#     Swap "\e[A" with C.
  }&        e#
  _S&       e#   Intersect C with " ".
  {         e#   If the intersection is non-empty:
    ]       e#     Wrap the entire stack in an array.
  }&
  o         e#   Print C or the entire stack.
}/          e#

Java, 428 bytes

void s(String s){int l=s.length(),m=0;char[][]c=new char[l][];for(int i=0;i<c.length;java.util.Arrays.fill(c[i++],' '))c[i]=new char[l];String v="aeiouyAEIOUY";String[]a=s.split(" ");for(int r=0,p=0;r<a.length;r++){String u=a[r]+" ";int o=v.indexOf(u.charAt(0))>=0?1:0,x=p;for(;x<u.length()-1+p;o+=v.indexOf(u.charAt(x++-~-p))>=0?1:0)c[o][x]=u.charAt(x-p);p+=u.length();m=m<o?o:m;}for(int i=0;i<=m;i++)System.out.println(c[i]);}

I know, it's horrible. There's probably some chars that can be shaved of, but I'm too lazy to do that.