# Make some Alphabet Rain

streetster 10/10/2017. 30 answers, 3.488 views

# Alphabet Rain

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:

• 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"])

## Examples:

Input of aaaa gives:

aaaa

Input of abcda gives:

abcda
bcd
cd
d

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
uzz
uzz
zz
zz
zz
zz
zz

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

~|[abc<0>cba]|~
bc   cb
c   c

## Notes:

• 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
• 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 Lynn 10/10/2017
Is a single leading \n acceptable?
streetster 10/10/2017
@Lynn, no leading newlines, the first line should be the input string/character list - I'll update the post!
13 caird coinheringaahing 10/10/2017
FWIW, I think they look more like icicles than rain
1 WallyWest 10/10/2017
+1 for considering those that use the letter Thorn
Pureferret 10/11/2017
@cairdcoinheringaahing sounds almost festive

Emigna 10/10/2017.

# 05AB1E, 13 12 bytes

,εDlAsk×}ζ»,

Try it online!

Explanation

,             # print input
ε      }     # apply to each char in input
D           # duplicate
l          # convert to lower case
Ask       # get index of current char in the lower case alphabet
×      # repeat the char that many times
ζ    # transpose with space as filler
»,  # join on newlines and print
24 Uriel 10/10/2017
Need to get index of char in lowercase alphabet? just Ask for it

Felix Palmen 10/10/2017.

# 6502 machine code (C64), 113 bytes

00 C0 20 FD AE 20 9E AD 85 FB 20 A3 B6 A0 00 84 FC B1 22 99 6F C1 C9 41 90 14
C9 5B B0 04 E9 40 B0 0E C9 C1 90 08 C9 DB B0 04 E9 C0 B0 02 A9 00 99 6F C0 C5
FC 30 02 85 FC C8 C4 FB D0 D3 A9 00 99 6F C1 A0 C1 A9 6F 20 1E AB A9 0D 20 D2
FF A6 FC D0 01 60 C6 FC A0 00 B9 6F C1 F0 E6 BE 6F C0 D0 07 A9 20 99 6F C1 D0
05 CA 8A 99 6F C0 C8 D0 E7

Online demo

Usage: sys49152,"[string]", e.g. sys49152,"Programming Puzzles & Code Golf!".

Important: If the program was loaded from disk (like in the online demo), issue a new command first! This is necessary because loading a machine program trashes some C64 BASIC pointers.

Note: The C64 is by default in a mode without lowercase letters -- in order to be able to enter a mixed-case string, switch to lowercase mode first by pressing SHIFT+CBM.

### Explanation

Here's a commented disassembly listing:

         00 C0       .WORD $C000 ; load address .C:c000 20 FD AE JSR$AEFD          ; consume comma
.C:c003  20 9E AD    JSR $AD9E ; evaluate expression .C:c006 85 FB STA$FB            ; store string length
.C:c008  20 A3 B6    JSR $B6A3 ; free string .C:c00b A0 00 LDY #$00           ; initialize counter
.C:c00d  84 FC       STY $FC ; and number of "extra" lines .C:c00f .copyloop: .C:c00f B1 22 LDA ($22),Y        ; load next character
.C:c011  99 6F C1    STA .outbuf,Y      ; store to buffer
.C:c014  C9 41       CMP #$41 ; compare with 'a' .C:c016 90 14 BCC .zerocount ; smaller -> no repetition .C:c018 C9 5B CMP #$5B           ; compare with 'z'
.C:c01a  B0 04       BCS .checkupper    ; larger -> check for uppercase
.C:c01c  E9 40       SBC #$40 ; subtract 'a' ('a' - 1 and carry) .C:c01e B0 0E BCS .cl_storecount ; and jump to store in repeat count .C:c020 .checkupper: .C:c020 C9 C1 CMP #$C1           ; compare with 'A'
.C:c022  90 08       BCC .zerocount     ; smaller -> no repetition
.C:c024  C9 DB       CMP #$DB ; compare with 'Z' .C:c026 B0 04 BCS .zerocount ; larger -> no repetition .C:c028 E9 C0 SBC #$C0           ; subtract 'A' ('A' - 1 and carry)
.C:c02a  B0 02       BCS .cl_storecount ; and jump to store in repeat count
.C:c02c   .zerocount:
.C:c02c  A9 00       LDA #$00 ; store 0 ... .C:c02e .cl_storecount: .C:c02e 99 6F C0 STA .repcount,Y ; ... in repeat count .C:c031 C5 FC CMP$FC            ; compare with number of extra lines
.C:c033  30 02       BMI .cl_next       ; smaller -> go on with loop
.C:c035  85 FC       STA $FC ; repeat count to number of extra lines .C:c037 .cl_next: .C:c037 C8 INY ; next .C:c038 C4 FB CPY$FB            ; compare with string length
.C:c03a  D0 D3       BNE .copyloop      ; not yet reached? -> repeat
.C:c03c  A9 00       LDA #$00 ; terminate string in buffer .C:c03e 99 6F C1 STA .outbuf,Y ; with 0 byte .C:c041 .outloop: .C:c041 A0 C1 LDY #>.outbuf ; output ... .C:c043 A9 6F LDA #<.outbuf ; ... .C:c045 20 1E AB JSR$AB1E          ; ... string
.C:c048  A9 0D       LDA #$0D ; and output ... .C:c04a 20 D2 FF JSR$FFD2          ; ... newline
.C:c04d  A6 FC       LDX $FC ; load extra line count .C:c04f D0 01 BNE .ol_step ; not zero -> go on .C:c051 60 RTS ; WE ARE DONE HERE ;) .C:c052 .ol_step: .C:c052 C6 FC DEC$FC            ; decrease extra line count
.C:c054  A0 00       LDY #$00 ; initialize counter .C:c056 .eraseloop: .C:c056 B9 6F C1 LDA .outbuf,Y ; load next character from buffer .C:c059 F0 E6 BEQ .outloop ; 0 byte? -> end of string, output .C:c05b BE 6F C0 LDX .repcount,Y ; load repeat count for this characer .C:c05e D0 07 BNE .el_step ; not 0 yet? -> jump to decrement .C:c060 A9 20 LDA #$20           ; load code for space
.C:c062  99 6F C1    STA .outbuf,Y      ; store in current string position
.C:c065  D0 05       BNE .el_next       ; and jump to next loop iteration
.C:c067   .el_step:
.C:c067  CA          DEX                ; decrease repeat count ...
.C:c068  8A          TXA                ; ... and ...
.C:c069  99 6F C0    STA .repcount,Y    ; ... store back
.C:c06c   .el_next:
.C:c06c  C8          INY                ; increase counter ...
.C:c06d  D0 E7       BNE .eraseloop     ; and jump back to loop

.C:c06f   .repcount:
.C:c06f              .RES $100 ; 256 bytes for repeat count .C:c16f .outbuf: .C:c16f .RES$100          ; 256 bytes as buffer for output
Dschoni 10/11/2017
c64 machine code. I'm impressed.
Felix Palmen 10/11/2017
@Dschoni thanks, but it's still simple code (and it's fun, for me!) -- you should have a look at the demo scene for really impressive C64 works ;)
trlkly 10/12/2017
If we're gonna keep getting these, we might want to set up links to a JavaScript C64 emulator so people can see them run.

Jenny_mathy 10/11/2017.

# Mathematica, 115 89 bytes

It takes as input a list of characters [{"a", "b", "c", "d", "a"}] and outputs a list of lists of characters

Thread[PadRight[Table[#,Max@Position[Alphabet[]/."a"->#,#|ToLowerCase@#]]&/@#]/. 0->" "]&

Try it online!

-26 bytes from Misha Lavrov

-5 bytes from user202729

but if you want to see the output as it is in the test case, try this (128 bytes) code
Try it online!

user202729 10/10/2017
For future readers: The part "this answer only works on Mathematica..." is a bit misleading, the problem is Mathematica only support Unicode character in notebook (REPL) mode. In script mode, it only understand ASCII and special characters which have been converted to ASCII (e.g., ∞ (3 bytes) -> \[Infinity] (11 bytes)).
Jenny_mathy 10/10/2017
user202729 10/10/2017
Golf suggestion for Mathematica (script mode): \[Infinity] (11 bytes) can be replaced by Infinity (8 bytes) or \:221e (6 bytes). The last one is the default representation of special characters without names. (although it is not the main part)
Misha Lavrov 10/10/2017
We can avoid Infinity entirely. The problematic part is If[(d=Min@Position[Alphabet[],If[UpperCaseQ@#,ToLowerCase@#,‌​#]])==∞,1,d] and we can change this to Max@Position[Alphabet[]/."a"->#,#|ToLowerCase@#]. (Searching in the list {#,b,c,d,...,y,z}, we're guaranteed to find # at least once.)
Jenny_mathy 10/11/2017
@MishaLavrov very nice. fixed it!

Steven Hewitt 10/10/2017.

# Pyth, 1210 9 bytes

.tm+*xGr0

Test suite.

Explanation:

.tm+*xGr0dddQ   Expanded program with autofilled input variable
m      dddQ    For each character d in the input:
r0d     get its lowercase variant
xG        and return its 0-based index in the alphabet
(empty string for A/a and special characters)
*     d    that many of the corresponding character
+       d   and one more for good measure (because x is 0-indexed)
.t             Transpose it and fill blanks with spaces

12 bytes:

j.t*VmxGr0d

(with trailing newline)

Test suite.

Explanation:

j.t*VmxGr0d
QQ              Expanded program with autofilled input variable
Q               print the input verbatim
m    dQ    For each character d in the input:
r0      get its lowercase variant
xG        and return its 0-based index in the alphabet
*V       Q   multiply the corresponding characters in (the second autofilled input)
by their alphabet indices we just calculated
(empty string for A/a and special characters)
.t             Transpose it and fill blanks with spaces
j               Join the result on newlines
Mr. Xcoder 10/10/2017
output can be a list of lists of characters, so long as it looks like it's raining characters - Hence you don't need j
Steven Hewitt 10/10/2017
Ah, you're right! I was keeping it because the 12-byte version was printing one line verbatim and I couldn't mix the formats like that, and I forgot I could remove that now that everything is in the transpose. Thanks!

Lynn 10/10/2017.

# Python 3, 83 bytes

f=lambda s,k=65:[*{*s}-{' '}]and[s]+f([[' ',c][91>ord(c.upper())>k]for c in s],k+1)

Try it online! Takes a list of characters. Returns a list of lists of characters.

## Python 2, 90 bytes

f=lambda s,k=65:s.strip()and s+'\n'+f(''.join([' ',c][91>ord(c.upper())>k]for c in s),k+1)

Try it online! Takes a string. Returns a string.

Uriel 10/10/2017.

# Python, 105 103 bytes

2 bytes saved thanks to @TFeld

lambda s:'\n'.join(''.join((' '+l)[i<1or 91>ord(l.upper())>i+64]for l in s)for i in range(26)).rstrip()

Try it online!

TFeld 10/10/2017
Uriel 10/10/2017
@TFeld nice catch, thanks!

Erik the Outgolfer 10/10/2017.

# Charcoal, 12 bytes

θ↙↓Ｅ⮌θ×ι⌕α↥ι

Try it online!

-3 thanks to Neil.

TFeld 10/11/2017.

# Python 2, 11110699989787 93 bytes

s=input()
i=65
while s.strip():print s;s=''.join([' ',c][91>ord(c.upper())>i]for c in s);i+=1

Try it online!

Rod 10/10/2017
whilecan be replaced with exec to save few bytes, ican start with 65 to save more one to reach 87 bytes
TFeld 10/10/2017
@Rod Thanks :-)
Lynn 10/10/2017
The OP says extraneous trailing newlines are not allowed, but your code prints several of them when the input doesn’t contain z or Z.
TFeld 10/11/2017
@Lynn Fixed, I forgot to double-check the execchange...

Nahuel Fouilleul 10/11/2017.

# Bash, 78, 76 71 bytes

for c in {B..a};{ [[ -n ${1// } ]]&&echo "$1";set "${1//[!$c-Z${c,}-z]/ }";} Depending on collation (default LC_ALL) can save some more bytes for c in {b..z} _;{ [[ -n${1// } ]]&&echo "$1";set "${1//[!$c-Z]/ }";} Try It Online Uriel 10/10/2017. # Dyalog APL, 27 22 bytes 5 bytes saved thanks to @Adám ⍉∘↑⊢⍴¨⍨1⌈27|⎕A⍳819⌶⍨∘1 Try it online! How? ⍴¨⍨ - shape each char to length of 1⌈ - at least one or ⎕A⍳819⌶⍨∘1 - index of the char uppercased in alphabet 27| - modulo 27 ↑ - flatten to a matrix ⍉ - and transpose ##### 2 comments Uriel 10/10/2017 @Adám thanks! updated Dom Hastings 10/10/2017. # Perl 5, 43 bytes 41 bytes code + 2 for -nl. $c=A;print,s/$c|[^a-z]/ /gi,$c++while/\S/

Try it online!

1 Nahuel Fouilleul 10/10/2017
loop for [_0-9] characters, maybe s/["-$c]/ /gi and -l not needed Dom Hastings 10/10/2017 @NahuelFouilleul Ahh, yes, I was a little too quick on the test cases. They should be added to the OP! :) Thanks! +4 :( Nahuel Fouilleul 10/10/2017 my suggestion doesn't work for any characters between 32 and 126 (non alpha greater than Z) Dom Hastings 10/10/2017 @NahuelFouilleul Can't find a shorter way that meets all requirements... I'll keep playing... Luis Mendo 10/10/2017. # Octave / MATLAB, 74 bytes @(s)char(arrayfun(@(c){repmat(c,1,max(sum(find(upper(c)==65:90)),1))},s))' Try it online! Justin Mariner 10/11/2017. # JavaScript (ES6), 8778 76 bytes -9 bytes thanks to @RickHitchcock. -2 bytes thanks to @Neil. f=(s,i=10)=>s.trim()&&s+ +f(s.replace(/./g,c=>parseInt(c,36)>i?c:" "),i+1) Takes input as a string and returns with one trailing newline. ## Test Cases f=(s,i=10)=>s.trim()&&s+ +f(s.replace(/./g,c=>parseInt(c,36)>i?c:" "),i+1) ;["hello", "Programming Puzzles & Code Golf!", "~|[abc<0>cba]|~", "abcdefg0123456789"] .forEach(s=>console.log(f(s))); .as-console-wrapper{max-height:100%!important} ##### 5 comments Rick Hitchcock 10/10/2017 76 bytes (one trailing new line): f=(s,i=10)=>s.trim()&&s+'newline'+f(s.replace(/./g,c=>parseI‌​nt(c,36)-i?c:" "),i+1) Justin Mariner 10/10/2017 @RickHitchcock That seems to infinite loop for an input string containing numbers: Try it online!. The idea of step-by-step changes to s is really nice, though. Rick Hitchcock 10/10/2017 Ahh, good point. That can be fixed at the cost of 2 bytes: parseInt(c,36)-i>0 1 Neil 10/10/2017 @RickHitchcock Can you not use parseInt(c,36)>i instead to save 2 bytes? Rick Hitchcock 10/10/2017 @Neil, duh. Justin: What Neil said. : ) Titus 10/11/2017. # PHP, 69 78 77+1 bytes for($c=A;!$c[1];$s=preg_replace("#[^".++$c."-Z]#i"," ",$s))echo$s=&$argn,"
";

Run as pipe with -nR or try it online.

Shaggy 10/10/2017
If it only works with alphabetical strings then surely it's invalid? The challenge specifically requires the full range of printable ASCII to be supported.
Titus 10/10/2017
@Shaggy thanks for pointing out. It´s complete now.
Christoph 10/11/2017
+1 for $c=A;!$c[1];$c++. Nice one! Sadly extraneous trailing newlines are not allowed (single \n on final line is acceptable). So it fails for all strings not containing z. Shaggy 10/10/2017. # Japt, 151411 10 bytes First chance to play with Japt's new string padding methods so there might still be room for improvement. y_ùZInZu c Try it ## Explanation Implicit input of string U. y_ Pass each column of U through a function, where Z is the current element (or letter, in this case). InZu c Convert Z to uppercase (u), get its charcode (c) and subtract (u) 64 (I). ùZ Pad the start of Z with itself until it reaches that length. ## Alternative y_ùZ9aZn36 Try it ##### 2 comments ETHproductions 10/10/2017 But couldn't you change ùZ to p to save a b...never mind, that's really clever... Shaggy 10/10/2017 @ETHproductions: I made a few attempts with p (there might be 1 in the edit history) but ù won out in the end. Neil Slater 10/10/2017. ## Ruby, 7067 74 bytes f=->s{puts s;(?b..?z).each{|c|s.gsub! /[^#{c}-z]/i,' ';puts s if s=~/\S/}} Thanks to @TuukkaX for pointing out some parens could be dropped (-3 bytes) Unfortunately I then had to add 7 bytes because original version failed to handle "z". Calling it: f.call('The quick brown fox jumps over the lazy dog!') The quick brown fox jumps over the lazy dog! The quick brown fox jumps over the l zy dog The quick rown fox jumps over the l zy dog The qui k rown fox jumps over the l zy dog The qui k rown fox jumps over the l zy og Th qui k rown fox jumps ov r th l zy og Th qui k rown ox jumps ov r th l zy og Th qui k rown ox jumps ov r th l zy o T qui k rown ox jumps ov r t l zy o T qu k rown ox jumps ov r t l zy o T qu k rown ox umps ov r t l zy o T qu rown ox umps ov r t l zy o T qu rown ox umps ov r t zy o T qu rown ox u ps ov r t zy o T qu row ox u ps ov r t zy o T qu r w x u ps v r t zy T qu r w x u s v r t zy T u r w x u s v r t zy T u w x u s v t zy T u w x u v t zy u w x u v zy w x v zy w x zy x zy zy z ##### 1 comments TuukkaX 10/10/2017 The parentheses at the lambda definition can be removed. +1. plannapus 10/11/2017. # R, 118 114 bytes function(a)while(grepl("[^ ]",a)){F=F+1;cat(a,"\n");for(j in c("[^a-zA-Z]",letters[F],LETTERS[F]))a=gsub(j," ",a)} Thanks to @Giuseppe for those 4 bytes off Try it online! Short explanation: function(a) while(grepl("[^ ]",a)){ #As long as the string is not just spaces. F=F+1 #Increment letter counter (F is FALSE, hence 0 by default) cat(a,"\n") #Print string for(j in c("[^a-zA-Z]",letters[F],LETTERS[F])) #Get rid of non-letters, and the current letter in lower and upper case a=gsub(j," ",a) } ##### 4 comments Giuseppe 10/10/2017 114 bytes; nice work outgolfing me Giuseppe 10/10/2017 I forget, is there consensus on erroring to exit a program? You could use grep instead of grepl if it's OK that your program errors. plannapus 10/11/2017 Right! The "Using F as default for 0 trick"! nice. Concerning the second suggestion: I'm not sure either but instinctively I'll say that warnings are ok but not errors. Giuseppe 10/11/2017 ohhh, wait, potential issue: if a is all spaces, this won't print out anything...but you can change the while condition to grepl()|!F which is still a byte shorter than your original answer. Nejosan 10/11/2017. # C# (.NET Core), 162 bytes s=>{string A="abcdefghijklmnopqrstuvwxyz",r=s;for(int i=-1;++i<s.Max(A.IndexOf);)r+='\n'+string.Concat(s.Select(c=>A.IndexOf(char.ToLower(c))>i?c:' '));return r;} Try it online! ##### 3 comments Ian H. 10/10/2017 Welcome to PPCG and nice first answer. You can shorten your code by using a few tricks. Here is a more golfed version of your code: Try it online!. Nejosan 10/11/2017 Thanks for the comments, I assumed my code had to be executable by itself, so I built it upon that assumption! Thanks for the comment and the mentoring. Ian H. 10/11/2017 If you want to find some more tricks on how to golf in C#, take a look at this post, or take a look at existing C# answers. Happy golfing! Giuseppe 10/11/2017. # R, 125 123 bytes Outgolfed by plannapus for(i in 1:max(p<-pmax(1,match(tolower(S<-el(strsplit(scan(,""),''))),letters),na.rm=T)))cat(ifelse(p<i," ",S),'\n',sep='') Try it online! Prints to stdout with a single trailing newline and reads from stdin(). Let's break it down: S <- el(strsplit(scan,"")) # split the string to characters m <- match(tolower(S),letters) # 1-based index in letters (lowercase a-z) p <- pmax(1,m,na.rm=T) # parallel max, replaces NA (non-alphabet) or 0 with 1 for(i in 1:max(p)){ # iterate cat( # print ifelse(p<1,' ',S), # the corresponding letter in S if p>=1, space otherwise '\n',sep='') # newline, and no spaces between chars } ## Alternate answer, 106 bytes function(S)for(i in 1:max(p<-pmax(1,match(tolower(S),letters),na.rm=T)))cat(ifelse(p<i,' ',S),'\n',sep='') Try it online! Function; prints to stdout but it's basically my response above ported to accept a list of characters rather than splitting the string, so I feel like it's "cheating." Plus, plannapus' approach with regex is quite neat! MT0 10/11/2017. # Oracle SQL, 186 Bytes Assumes the string will be in a table t in column v: WITH a(s,l)AS(SELECT v,64 FROM t UNION ALL SELECT REGEXP_REPLACE(s,'[^'||CHR(l+1)||'-Z]',' ',1,0,'i'),l+1 FROM a WHERE l<90)SELECT LISTAGG(RTRIM(s),CHR(10))WITHIN GROUP(ORDER BY l)FROM a SQL Fiddle Oracle 11g R2 Schema Setup: CREATE TABLE t ( v ) AS SELECT '~|[abc<0>cba]|~' FROM DUAL / Query 1: WITH a(s,l)AS( SELECT v,64 FROM t UNION ALL SELECT REGEXP_REPLACE(s,'[^'||CHR(l+1)||'-Z]',' ',1,0,'i'),l+1 FROM a WHERE l<90 ) SELECT LISTAGG(RTRIM(s),CHR(10))WITHIN GROUP(ORDER BY l) FROM a | LISTAGG(RTRIM(S),CHR(10))WITHINGROUP(ORDERBYL) | |-----------------------------------------------------| | ~|[abc<0>cba]|~ | | abc cba | | bc cb | | c c | user1472751 10/11/2017. # Haskell, 137136127 119 bytes import Data.Char p c=last$0:[k|k<-[0..25],k+65==ord(toUpper c)]
f s=[[last$c:[' '|i>p c]|c<-s]|i<-[0..maximum$map p s]]

Try it online!

Pretty long but I can't think of any way to shorten it further. I feel like there must be some way shorter than the if-then syntax but I don't see it.

EDIT: Thanks @streetster for helping me shave off one byte! I didn't use toUpper at first because of the cost of importing Data.Char but I forgot that it also provides ord which is much shorter than fromEnum

EDIT 2: Thanks to @Laikoni for shaving off another 6 bytes and identifying a bug which I have now fixed. I used 26 instead of 25 because I forgot that Haskell arrays are inclusive. Then I noticed I could use last instead of head which would allow me to use 0: rather than ++[0].

EDIT 3: Thanks again Laikoni for those 8 bytes. I had actually forgotten about that space. For some reason Sublime Text flips out without it and I forgot to remove it. I wasn't aware that lists of lines were allowed, I should've read the rules more carefully.

1 streetster 10/10/2017
Can you lowercase the input to avoid having to check A-Z as well as a-z and then mod'ing?
user1472751 10/10/2017
@streetster In haskell the toLower and toUpper functions require importing Data.Char which costs more chars than it saves. TIO
1 Laikoni 10/11/2017

Try it online!

Try it online!

Short thanks to how PowerShell can dynamically cast between [char] and [int], but long because of removing extraneous whitespace. There's gotta be a better way to run the comparison ($_-ge65+$i-and$_-le90)-or$_-ge97+$i, but I can't come up with one. steenbergh 10/11/2017. # 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...

## Explanation

_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

Conor O'Brien 10/12/2017.

# 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     

Digital Trauma 10/12/2017.

# Bash + sed, 49

sed -nep\;s/\\W/\ /g -e"/^ *\$/q;p;s/"{a..z}/\ /gi`