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
    Commented Oct 10, 2017 at 12:01
  • \$\begingroup\$ @Lynn, no leading newlines, the first line should be the input string/character list - I'll update the post! \$\endgroup\$
    – mkst
    Commented Oct 10, 2017 at 14:25
  • 20
    \$\begingroup\$ FWIW, I think they look more like icicles than rain \$\endgroup\$ Commented Oct 10, 2017 at 18:39
  • \$\begingroup\$ @cairdcoinheringaahing sounds almost festive \$\endgroup\$ Commented Oct 11, 2017 at 17:02
  • \$\begingroup\$ :( Just Nordic? \$\endgroup\$
    – ASCII-only
    Commented Oct 12, 2017 at 3:10

41 Answers 41


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
  • \$\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
    Commented Nov 25, 2017 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
    Commented Nov 25, 2017 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     

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!


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

Stax, 12 bytes


Run and debug it


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!

  • \$\begingroup\$ This only prints one b, 2 c etc, think you need a +1 or something somewhere :) \$\endgroup\$
    – mkst
    Commented Aug 7, 2019 at 5:52
  • \$\begingroup\$ Change the A to an @ tio.run/… \$\endgroup\$
    – mkst
    Commented Aug 7, 2019 at 5:57
  • \$\begingroup\$ Should be fixed now \$\endgroup\$ Commented Aug 7, 2019 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.

  • \$\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\$ Commented Sep 5, 2019 at 15:08
  • \$\begingroup\$ Nice! No requirement to trim the strings so all good on that front :) \$\endgroup\$
    – mkst
    Commented Sep 5, 2019 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);
  • 2
    \$\begingroup\$ nice answer. Do host it on tio.run so people can verify your answer. \$\endgroup\$
    – Razetime
    Commented Oct 18, 2020 at 12:16
  • \$\begingroup\$ @Razetime; Thanks foir the feedback. Done. @Titus: Thanks for showing a simpler alternative to tio.run. :) \$\endgroup\$ Commented Oct 18, 2020 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

Husk, 15 bytes

T' m?SRȯ-64ca;√

Try it online!

repeat each character, then transpose-pad.


Thunno 2 N, 7 bytes


Try it online!


Ä1|Ḟ×ðƬ  # Implicit input
Ä        # Get the 1-based index in the alphabet
         # for each character in the input string
 1|      # Replace 0s (non-alphabets) with 1s
   Ḟ×    # Multiply elementwise with the input
     ðƬ  # Transpose with filler space
         # Implicit output, joined on newlines

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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