Alphabet Rain

The Task:

The basic premise is to print out the input string and then repeat each character vertically, based on it's (0-indexed) position in the (case-insensitive) alphabet A-Z. A is at location 0 so is not repeated, e is at position 4 so is repeated 4 times, P is at position 15 so is repeated 15 times, ! is not in A-Z so is repeated 0 times, etc.

For clarity, anything that falls outside of the range B-Zb-z, for example digits or special characters, will not be repeated, and thus will only appear on the first line.

This is , so shortest solution in each language is the winner.


  • Input will be in the standard printable ASCII character set, from 32 up to 126 ~.
  • The input string will be 1 character long or longer.
  • There will not be any leading or trailing whitespace.
  • You can take take input as a string ("hello") or list of characters ( ["h", "e", "l", "l", "o"])


Input of aaaa gives:


Input of abcda gives:


Input of Programming Puzzles & Code Golf!, gives:

Programming Puzzles & Code Golf!
Progr mming Puzzles   Code Golf
Progr mming Puzzles   Code Golf
Progr mming Puzzles    ode Golf
Progr mming Puzzles    o e Golf
Progr mming Puzzl s    o   Golf
Progr mming Puzzl s    o   Gol
Pro r mmin  Puzzl s    o    ol
Pro r mmin  Puzzl s    o    ol
Pro r mm n  Puzzl s    o    ol
Pro r mm n  Puzzl s    o    ol
Pro r mm n  Puzzl s    o    ol
Pro r mm n  Puzz  s    o    o
Pro r    n  Puzz  s    o    o
Pro r       Puzz  s    o    o
Pr  r       Puzz  s
 r  r        uzz  s
 r  r        uzz  s
             uzz  s

Input of ~|[abc<0>cba]|~, gives:

    bc   cb
     c   c


  • standard loopholes apply
  • output can be a list of strings, but:
  • extraneous trailing newlines are not allowed (single \n on final line is acceptable)
  • output can be a list of lists of characters, so long as it looks like it's raining characters
  • no leading newline
  • to our Nordic users who have a few extra letters in their "A-Z" alphabet, feel free to support them, but it's not part of the challenge
  • 2
    \$\begingroup\$ Is a single leading \n acceptable? \$\endgroup\$ – Lynn Oct 10 '17 at 12:01
  • \$\begingroup\$ @Lynn, no leading newlines, the first line should be the input string/character list - I'll update the post! \$\endgroup\$ – streetster Oct 10 '17 at 14:25
  • 19
    \$\begingroup\$ FWIW, I think they look more like icicles than rain \$\endgroup\$ – caird coinheringaahing Oct 10 '17 at 18:39
  • \$\begingroup\$ @cairdcoinheringaahing sounds almost festive \$\endgroup\$ – Pureferret Oct 11 '17 at 17:02
  • \$\begingroup\$ :( Just Nordic? \$\endgroup\$ – ASCII-only Oct 12 '17 at 3:10

40 Answers 40


QBIC, 141 bytes

_L;|dim g(a)┘dim H(a)[a|_SA,b,1|┘H(b)=B┘o=asc(ucase$(B))-65~o<1or o>25|o=0]g(b)=o~g(b)>p|p=g(b)}?A[p|[a|~g(d)|g(d)=g(d)-1\H(d)=@ `]?H(d)';`]?

Wow, this has to be the longest entry I've made using QBIC...


_L |                        Assign to num var 'a' the length of
  ;                         A$, which is read off the CMD line
dim g(a)                    Define 'g' as an array of 'a' slots. The lower-
                            case letter denotes it will store numbers.
                            g() will store if we still need to rain down the char at pos ()
                            of the input string.
┘                           Inject a linebreak in the compiled QBasic
dim H(a)                    Define H$ to be an array, also of length 'a', for strings
                            H$(x) will store what to rain down if g(x) > 0
[a|                         Run along the length of the input string
                            (QBasic: FOR b = 1 TO a STEP 1)
  _SA,b,1|┘                 Take a substring at index b on string A$, length 1 and 
                            store as B$; lift out each character one at a time
  H(b)=B┘                   Save the character in H$(x)
  o=asc(ucase$(B))-65       Take the ASCII codepoint of that substring, as uppercase 
                            minus 65. [A-Z] maps to 0-25. Save that number as 'o'
  ~o<1or o>25               IF o is not in range
  |o=0]                     THEN set o to zero (the same value as 'A/a')
  g(b)=o                    SET the number of rain-down copies to 'o'
  ~g(b)>p                   IF the number of raindowns exceeds the prvious max,
  |p=g(b)                   THEN store the new max into 'p'. This defines the rain-down depth
}                           END IF, NEXT
?A                          PRINT the original, \n
[p|                         FOR c = 1 TO max-depth 
  [a|                       FOR d = 1 to LEN(A$)
    ~g(d)                   IF the rain-down counter is positive
    |g(d)=g(d)-1            THEN decrement it by 1
    \H(d)=@ `               ELSE replace the char by a literal space in the char map
    ]                       END IF
    ?H(d)                   PRINT the character at the current pos int he char map
      ';`                   and suppress newlines
  ]                         NEXT character
?                           PRINT \n at the end of the line
| improve this answer | |
  • \$\begingroup\$ I was going to write a QBasic answer until I realized that 26 lines of output wouldn't fit on the screen without scrolling. Does QBIC have the same limitation? If so, what are your thoughts on how that affects the validity of this solution? \$\endgroup\$ – DLosc Nov 25 '17 at 1:50
  • \$\begingroup\$ @DLosc Same restriction applies to QBIC; it runs QBasic code after all. However, I feel the answer is valid - within the technical possibilities of the QBasic platform. Inputs that don't require displaying 26 lines (like ~|[abc<0>cba]|~) show that the functionality of this is according to spec. \$\endgroup\$ – steenbergh Nov 25 '17 at 9:34

Stacked, 47 bytes

[[:upcase ALPHA\index 0 max#+*]"!LF#`togrid tr]

Try it online! Takes input as list of characters, and returns a list of list of characters.

[[:upcase ALPHA\index 0 max#+*]"!LF#`togrid tr]          input: str
 [                            ]"!                        for(char of str)
   upcase ALPHA\index                                        get index of uppercase char
                                                             in uppercase alphabet
                      0 max                                  max(0, index)
  :                        #+*                               repeat char ^ times
                                 LF#`togrid                  convert to aligned char array
                                            tr               transpose     
| improve this answer | |

Jq 1.5, 106 bytes

foreach("\n","^B-Zb-z",(range(24)|[.+66,.+98]|implode))as$x(.;gsub("[\($x)]";" ");.)|select(.!=length*" ")


   foreach ("\n",                            # first pattern won't match anything
            "^B-Zb-z",                       # next a, A and punctuation
            (range(24)|[.+66,.+98]|implode)  # then Bb, Cc, ...
   ) as $x (
   ; gsub("[\($x)]";" ")                     # apply each pattern to input
   ; .
 | select(.!=length*" ")                     # eliminate blank lines

Try it online!

| improve this answer | |

SNOBOL4 (CSNOBOL4), 181 bytes

Z	S NOTANY(U L ' ') =' '	:S(Z)
N	U LEN(1) . X REM . U
	L LEN(1) . Y REM . L
R	S (X | Y) =' '	:S(R)
	S NOTANY(' ')	:F(END)

Try it online!

	S =OUTPUT =INPUT		;* read input and print it
	U =&UCASE			;* alias for uppercase letters
	L =&LCASE			;* alias for lowercase letters
Z	S NOTANY(U L ' ') =' '	:S(Z)	;* replace non-alphabet, non-space characters with space
N	U LEN(1) . X REM . U		;* get the Next uppercase letter
	L LEN(1) . Y REM . L		;* get the Next lowercase letter
R	S (X | Y) =' '	:S(R)		;* replace all those with spaces
	S NOTANY(' ')	:F(END)		;* if S is all spaces, terminate the program
	OUTPUT =S	:(N)		;* else print S and goto N
| improve this answer | |

Stax, 12 bytes


Run and debug it

| improve this answer | |

Julia 1.0, 97 bytes

f(s,h=c->isletter(c)&&(c-'A')%32)=println.([s;[map(c->h(c)>i ? c : ' ',s) for i=0:maximum(h,s)]])

Try it online!

| improve this answer | |
  • \$\begingroup\$ This only prints one b, 2 c etc, think you need a +1 or something somewhere :) \$\endgroup\$ – streetster Aug 7 '19 at 5:52
  • \$\begingroup\$ Change the A to an @ tio.run/… \$\endgroup\$ – streetster Aug 7 '19 at 5:57
  • \$\begingroup\$ Should be fixed now \$\endgroup\$ – Simeon Schaub Aug 7 '19 at 10:06

Assembly (MIPS, SPIM), 319 bytes

.globl main
lw $4 4($5)
li $2 4
li $9 65
li $11 91
li $14 122
move $12 $4
li $2 11
li $4 10
addi $9 1
bge $9 $11 n
addi $8 $12 -1
addi $8 1
lb $4 ($8)
beqz $4 g
blt $4 $9 e
blt $4 $11 f
addi $13 $9 32
blt $4 $13 e
bgt $4 $14 e
j l
li $4 32
j f
li $2 10

Try it online!

almost positive this can be golfed further, (might be able to use mod instead of a bunch of branches, idk) but i'm not complaining. Takes the string as a command line argument. most of the registers are used for magic ascii numbers, though $9 and $8 update - $9 is the current iteration, starting at 65 (a). $8 starts at the beginning of the string, then iterates over the string until reaching a null terminator. characters that are no longer valid are replaced with '32' or space. Prints a single trailing newline, on the last line.

The output is padded - that is, if the input string is 5 characters long, each printed row will also be 5 characters long, even if this means the last few bytes in a row are space characters. or more practically: "Faa"=>
"Faa" "F " "F " "F " "F " "F "
The instructions did not specify if we had to trim each row to the shortest possible or if this behavior was allowed. If the trimmed variant is desired I can mark this non-competing.

| improve this answer | |
  • \$\begingroup\$ one cool aside: flipping the contents of e and f in the code will result in [stalagmites](tio.run/… " - the code will print the line at the top, then grow from the bottom up, as if the text dripped down to the ground and built up over time. Did that by accident first and wondered what I did wrong. \$\endgroup\$ – Andrew Baumher Sep 5 '19 at 15:08
  • \$\begingroup\$ Nice! No requirement to trim the strings so all good on that front :) \$\endgroup\$ – streetster Sep 5 '19 at 17:27

PHP 7, 110 Bytes

";for($i=66;$i<90&&trim($t);){echo$t;$t=preg_replace('~[^\n'.chr($i).'-Z'.chr(32+$i++).'-z]~', ' ',$t);}

Try it online


Input given in $t


    $t=preg_replace('~[^\n'.chr($i).'-Z'.chr(32+$i++).'-z]~', ' ',$t);
| improve this answer | |
  • 2
    \$\begingroup\$ nice answer. Do host it on tio.run so people can verify your answer. \$\endgroup\$ – Razetime Oct 18 at 12:16
  • \$\begingroup\$ @Razetime; Thanks foir the feedback. Done. @Titus: Thanks for showing a simpler alternative to tio.run. :) \$\endgroup\$ – Zsolt Szilagy Oct 18 at 12:19

Pip, 23 bytes


Try it online!


Pa                      Print the original string
  Fi,26                 loop with variable i across range 0-26 
                     Ma Map the input to the following function
        {z@?LCa>i?as}   Replace any symbols with index lesser than i with a space
       P                Print the mapped string
| improve this answer | |

Husk, 15 bytes

T' m?SRȯ-64ca;√

Try it online!

repeat each character, then transpose-pad.

| improve this answer | |

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.