55
\$\begingroup\$

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:

  • 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
  • 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
caird coinheringaahing
50.9k11 gold badges133 silver badges364 bronze badges
asked Oct 10, 2017 at 9:24
\$\endgroup\$
6
  • 2
    \$\begingroup\$ Is a single leading \n acceptable? \$\endgroup\$ 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\$ 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\$ Commented Oct 12, 2017 at 3:10

41 Answers 41

1
2
22
\$\begingroup\$

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

screenshot

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 #5ドルB ; 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 #0ドルD ; 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
answered Oct 10, 2017 at 21:07
\$\endgroup\$
4
  • 3
    \$\begingroup\$ c64 machine code. I'm impressed. \$\endgroup\$ Commented Oct 11, 2017 at 12:16
  • \$\begingroup\$ @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 ;) \$\endgroup\$ Commented Oct 11, 2017 at 12:57
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Oct 12, 2017 at 3:50
  • 1
    \$\begingroup\$ @trlkly I have such a link in my submission, click on "Online demo" ;) \$\endgroup\$ Commented Oct 12, 2017 at 5:10
15
\$\begingroup\$

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
answered Oct 10, 2017 at 9:31
\$\endgroup\$
1
  • 34
    \$\begingroup\$ Need to get index of char in lowercase alphabet? just Ask for it \$\endgroup\$ Commented Oct 10, 2017 at 10:53
8
\$\begingroup\$

Pyth, (削除) 12 (削除ここまで) (削除) 10 (削除ここまで) 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 
 (-1 if not found, for special chars)
 (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 
 (-1 if not found, for special chars)
 *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
answered Oct 10, 2017 at 10:33
\$\endgroup\$
2
  • \$\begingroup\$ 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 \$\endgroup\$ Commented Oct 10, 2017 at 11:25
  • \$\begingroup\$ 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! \$\endgroup\$ Commented Oct 10, 2017 at 11:27
8
\$\begingroup\$

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.

answered Oct 10, 2017 at 10:54
\$\endgroup\$
7
\$\begingroup\$

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!

answered Oct 10, 2017 at 9:31
\$\endgroup\$
5
  • \$\begingroup\$ 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)). \$\endgroup\$ Commented Oct 10, 2017 at 16:17
  • \$\begingroup\$ @user202729 ok,I'll edit and address people to read your comment.thanks \$\endgroup\$ Commented Oct 10, 2017 at 16:20
  • \$\begingroup\$ 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) \$\endgroup\$ Commented Oct 10, 2017 at 16:21
  • \$\begingroup\$ 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.) \$\endgroup\$ Commented Oct 10, 2017 at 23:53
  • \$\begingroup\$ @MishaLavrov very nice. fixed it! \$\endgroup\$ Commented Oct 11, 2017 at 0:36
6
\$\begingroup\$

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

answered Oct 10, 2017 at 9:57
\$\endgroup\$
2
  • \$\begingroup\$ 22 bytes: ⍉∘↑⊢⍴¨⍨1⌈27|⎕A⍳819⌶⍨∘1 \$\endgroup\$ Commented Oct 10, 2017 at 10:40
  • \$\begingroup\$ @Adám thanks! updated \$\endgroup\$ Commented Oct 10, 2017 at 10:44
6
\$\begingroup\$

Charcoal, 12 bytes

×ばつι⌕α↥ι

Try it online!

-3 thanks to Neil.

answered Oct 10, 2017 at 12:04
\$\endgroup\$
5
\$\begingroup\$

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!

answered Oct 10, 2017 at 10:28
\$\endgroup\$
2
  • \$\begingroup\$ 103 bytes \$\endgroup\$ Commented Oct 10, 2017 at 10:47
  • \$\begingroup\$ @TFeld nice catch, thanks! \$\endgroup\$ Commented Oct 10, 2017 at 10:50
5
\$\begingroup\$

Python 2, (削除) 111 (削除ここまで) (削除) 106 (削除ここまで) (削除) 99 (削除ここまで) (削除) 98 (削除ここまで) (削除) 97 (削除ここまで) (削除) 87 (削除ここまで) 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!

answered Oct 10, 2017 at 10:25
\$\endgroup\$
3
  • \$\begingroup\$ whilecan be replaced with exec to save few bytes, ican start with 65 to save more one to reach 87 bytes \$\endgroup\$ Commented Oct 10, 2017 at 14:46
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Oct 10, 2017 at 23:03
  • \$\begingroup\$ @Lynn Fixed, I forgot to double-check the execchange... \$\endgroup\$ Commented Oct 11, 2017 at 7:48
5
\$\begingroup\$

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!

answered Oct 10, 2017 at 14:29
\$\endgroup\$
5
  • 2
    \$\begingroup\$ 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!. \$\endgroup\$ Commented Oct 10, 2017 at 17:01
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Oct 11, 2017 at 7:29
  • 2
    \$\begingroup\$ 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! \$\endgroup\$ Commented Oct 11, 2017 at 7:31
  • \$\begingroup\$ Nice answer. Keep going :) \$\endgroup\$ Commented Oct 12, 2017 at 13:24
  • 1
    \$\begingroup\$ Hi, welcome to PPCG! Great first answer, especially now that it's golfed. +1 from me. Btw, it's currently 180 bytes, not 162. The required import using System.Linq; is unfortunately mandatory to add to the byte-count (or you should change Max to System.Linq.Max and Select to System.Linq.Max, which would be higher than simply using System.Linq; once.) Again welcome, and enjoy your stay. Oh, and I see @IanH. already mentioned Tips for Golfing in C#. Tips for golfing in <all languages> might also be interesting to read through. \$\endgroup\$ Commented Oct 17, 2017 at 13:43
5
\$\begingroup\$

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

answered Oct 11, 2017 at 10:50
\$\endgroup\$
4
\$\begingroup\$

Perl 5, 43 bytes

41 bytes code + 2 for -nl.

$c=A;print,s/$c|[^a-z]/ /gi,$c++while/\S/

Try it online!

answered Oct 10, 2017 at 10:26
\$\endgroup\$
4
  • 1
    \$\begingroup\$ loop for [_0-9] characters, maybe s/["-$c]/ /gi and -l not needed \$\endgroup\$ Commented Oct 10, 2017 at 10:37
  • \$\begingroup\$ @NahuelFouilleul Ahh, yes, I was a little too quick on the test cases. They should be added to the OP! :) Thanks! +4 :( \$\endgroup\$ Commented Oct 10, 2017 at 10:39
  • \$\begingroup\$ my suggestion doesn't work for any characters between 32 and 126 (non alpha greater than Z) \$\endgroup\$ Commented Oct 10, 2017 at 10:42
  • \$\begingroup\$ @NahuelFouilleul Can't find a shorter way that meets all requirements... I'll keep playing... \$\endgroup\$ Commented Oct 10, 2017 at 11:50
4
\$\begingroup\$

JavaScript (ES6), (削除) 87 (削除ここまで) (削除) 78 (削除ここまで) 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}

answered Oct 10, 2017 at 13:01
\$\endgroup\$
6
  • \$\begingroup\$ 76 bytes (one trailing new line): f=(s,i=10)=>s.trim()&&s+'newline'+f(s.replace(/./g,c=>parseInt(c,36)-i?c:" "),i+1) \$\endgroup\$ Commented Oct 10, 2017 at 14:26
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Oct 10, 2017 at 15:14
  • \$\begingroup\$ Ahh, good point. That can be fixed at the cost of 2 bytes: parseInt(c,36)-i>0 \$\endgroup\$ Commented Oct 10, 2017 at 15:16
  • 1
    \$\begingroup\$ @RickHitchcock Can you not use parseInt(c,36)>i instead to save 2 bytes? \$\endgroup\$ Commented Oct 10, 2017 at 21:24
  • \$\begingroup\$ @Neil, duh. Justin: What Neil said. : ) \$\endgroup\$ Commented Oct 10, 2017 at 21:28
4
\$\begingroup\$

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)
 }
answered Oct 10, 2017 at 15:41
\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Oct 11, 2017 at 13:43
4
\$\begingroup\$

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!

answered Oct 10, 2017 at 13:47
\$\endgroup\$
4
\$\begingroup\$

Octave / MATLAB, (削除) 74 (削除ここまで) 66 bytes

@(s)char(arrayfun(@(c){repmat(c,1,prod(find(upper(c)==65:90)))},s))'

Try it online!

answered Oct 10, 2017 at 14:03
\$\endgroup\$
3
\$\begingroup\$

Japt, (削除) 15 (削除ここまで) (削除) 14 (削除ここまで) (削除) 11 (削除ここまで) 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

answered Oct 10, 2017 at 14:25
\$\endgroup\$
2
  • \$\begingroup\$ But couldn't you change ùZ to p to save a b...never mind, that's really clever... \$\endgroup\$ Commented Oct 10, 2017 at 18:32
  • \$\begingroup\$ @ETHproductions: I made a few attempts with p (there might be 1 in the edit history) but ù won out in the end. \$\endgroup\$ Commented Oct 10, 2017 at 18:56
3
\$\begingroup\$

Haskell, (削除) 137 (削除ここまで) (削除) 136 (削除ここまで) (削除) 127 (削除ここまで) 119 bytes

import Data.Char
p c=last0ドル:[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.

answered Oct 10, 2017 at 16:38
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Can you lowercase the input to avoid having to check A-Z as well as a-z and then mod'ing? \$\endgroup\$ Commented Oct 10, 2017 at 16:58
  • \$\begingroup\$ @streetster In haskell the toLower and toUpper functions require importing Data.Char which costs more chars than it saves. TIO \$\endgroup\$ Commented Oct 10, 2017 at 17:06
  • 1
    \$\begingroup\$ You may want to have a look at the tips for golfing in Haskell. E.g. if i>p c then ' ' else c can be shortened to last$c:[' '|i>p c]. \$\endgroup\$ Commented Oct 11, 2017 at 10:30
  • \$\begingroup\$ Two more things: There is an unnecessary space in [k | and returning a list of lines is allowed, so you don't need the unlines. Finally, you might be interested in our Haskell chat room. \$\endgroup\$ Commented Oct 11, 2017 at 13:58
3
\$\begingroup\$

Excel VBA, 110 Bytes

Anonymous VBE Immediate Window Function that takes input as expected type Variant\String from range [A1] and uses it to make it rain the alphabet in the VBE immediate window.

?[A1]:For i=1To 26:For j=1To[Len(A1)]:c=Mid([A1],j,1):d=Asc(UCase(c)):?IIf((d>64+i)*(d<91),c," ");:Next:?:Next

Sample I/O

[A1]="qwertyuiop[]ASDFGHJKL:'zxcvbnm,./"
?[A1]:For i=1To 26:For j=1To[Len(A1)]:c=Mid([A1],j,1):d=Asc(UCase(c)):?IIf((d>64+i)*(d<91),c," ");:Next:?:Next
qwertyuiop[]ASDFGHJKL:'zxcvbnm,./
qwertyuiop SDFGHJKL zxcvbnm 
qwertyuiop SDFGHJKL zxcv nm 
qwertyuiop SDFGHJKL zx v nm 
qwertyuiop S FGHJKL zx v nm 
qw rtyuiop S FGHJKL zx v nm 
qw rtyuiop S GHJKL zx v nm 
qw rtyuiop S HJKL zx v nm 
qw rtyuiop S JKL zx v nm 
qw rtyu op S JKL zx v nm 
qw rtyu op S KL zx v nm 
qw rtyu op S L zx v nm 
qw rtyu op S zx v nm 
qw rtyu op S zx v n 
qw rtyu op S zx v 
qw rtyu p S zx v 
qw rtyu S zx v 
 w rtyu S zx v 
 w tyu S zx v 
 w tyu zx v 
 w yu zx v 
 w y zx v 
 w y zx 
 y zx 
 y z 
 z 
answered Oct 10, 2017 at 20:55
\$\endgroup\$
3
  • \$\begingroup\$ Brutal!!! It seams you can also make ?A1:... \$\endgroup\$ Commented Oct 17, 2017 at 14:12
  • \$\begingroup\$ @LS_ᴅᴇᴠ, unfortunately, as the [] indicates that the contained string should be evaluated to an object in/on/as a workbook, the [A1] call may not reduced to A1 - as this will not take and print the initial input from the range [A1]; rather this will just leave an empty line and all subsequent lines will be printed \$\endgroup\$ Commented Oct 17, 2017 at 19:55
  • \$\begingroup\$ Ups, you're right... Didn't notice this! \$\endgroup\$ Commented Oct 18, 2017 at 12:53
3
\$\begingroup\$

PHP, (削除) 69 78 77 (削除ここまで) 85+1 bytes

for($c=A;!$c[1]&&~trim($s=&$argn);$s=eregi_replace("[^".++$c."-Z]"," ",$s))echo"$s
";

requires PHP<7. Run as pipe with -nR or try it online.

answered Oct 10, 2017 at 13:59
\$\endgroup\$
3
  • \$\begingroup\$ @Shaggy thanks for pointing out. It´s complete now. \$\endgroup\$ Commented Oct 10, 2017 at 21:48
  • \$\begingroup\$ +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. \$\endgroup\$ Commented Oct 11, 2017 at 12:33
  • 1
    \$\begingroup\$ @Christoph fixed \$\endgroup\$ Commented Oct 12, 2017 at 7:50
3
\$\begingroup\$

Bash + sed, 37

sed -rne"/^ *$/q;p;s/\W|"{a..z}/\ /gi

Try it online.

answered Oct 12, 2017 at 3:13
\$\endgroup\$
2
  • \$\begingroup\$ it looks like it's repeating characters in the alphabet 1-too-many times \$\endgroup\$ Commented Oct 12, 2017 at 10:50
  • \$\begingroup\$ @streetster I think its fixed now. \$\endgroup\$ Commented Oct 12, 2017 at 16:21
2
\$\begingroup\$

C (gcc), 189 bytes

#define F for(q=c,p=s;*p;++p,++q)
char*p,*q,s[99],c[99];main(h){gets(s);F{*q=*p>64&&*p<91?*p-65:*p>96&&*p<123?*p-97:0;h=h>*q?h:*q;}for(puts(s);h--;){F{putchar(*q?--*q,*p:32);}putchar(10);}}

Try it online!

answered Oct 10, 2017 at 19:25
\$\endgroup\$
2
  • \$\begingroup\$ Try puts(""); instead of putchar(10) \$\endgroup\$ Commented Oct 12, 2017 at 3:13
  • \$\begingroup\$ 178 bytes \$\endgroup\$ Commented Aug 21, 2018 at 0:33
2
\$\begingroup\$

Ruby, (削除) 70 (削除ここまで) (削除) 67 (削除ここまで) 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
answered Oct 10, 2017 at 18:07
\$\endgroup\$
1
  • \$\begingroup\$ The parentheses at the lambda definition can be removed. +1. \$\endgroup\$ Commented Oct 10, 2017 at 19:13
2
\$\begingroup\$

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

Results :

| LISTAGG(RTRIM(S),CHR(10))WITHINGROUP(ORDERBYL) |
|-----------------------------------------------------|
| ~|[abc<0>cba]|~ |
| abc cba |
| bc cb |
| c c |
answered Oct 11, 2017 at 14:08
\$\endgroup\$
2
\$\begingroup\$

Jelly, 15 bytes

ØaḊiЀŒl‘8ẋ"z6Y

Try it online!

answered Oct 12, 2017 at 3:00
\$\endgroup\$
2
\$\begingroup\$

Haskell, 98 bytes

p c=sum[length[a..c]|a:e<-["B[","b{"],[c]<e]
f s=[[last$c:[' '|i>p c]|c<-s]|i<-[0..maximum$p<$>s]]

Try it online!

Example usage: f "[Abc]" yields a list of lines: ["[Abc]"," bc "," c "]. Use putStr.unlines.f $ "[Abc]" for pretty-printed output:

[Abc]
 bc
 c

(削除) Partly inspired by (削除ここまで) Now directly based on user1472751's Haskell answer.


Previous approach ((削除) 100 (削除ここまで) 99 bytes)

f s=[h|i<-[0..26],h<-[[(c:concat[c<$[a..c]|[a,e]<-["B[","b{"],c<e]++cycle" ")!!i|c<-s]],any(>' ')h]

Try it online!

answered Oct 11, 2017 at 13:12
\$\endgroup\$
2
\$\begingroup\$

PowerShell, (削除) 122 (削除ここまで) 127 bytes

param($a)$a;(1..25|%{$i=$_;(-join([char[]]$a|%{(' ',$_)[$_-match'[a-z]'-and[math]::Max(0,($_-bor32)-96-$i)]})).TrimEnd()})-ne''

Try it online!

Short thanks to how PowerShell can dynamically cast between [char] and [int], but long because of removing extraneous whitespace and the calculation of whether to output a space or the character.

Bugfix thanks to beatcracker.

answered Oct 11, 2017 at 15:04
\$\endgroup\$
2
  • \$\begingroup\$ Unfortunately, this fails on ~|[abc<0>cba]|~ test case. Try this: param($a)$a;(1..25|%{$i=$_;(-join([char[]]$a|%{(' ',$_)[$_-match'[a-z]'-and[math]::Max(0,($_-bor32)-96-$i)]})).TrimEnd()})-ne'' \$\endgroup\$ Commented Oct 16, 2017 at 5:12
  • \$\begingroup\$ @beatcracker Good catch. That's a clever way of handling the comparison. Thanks! \$\endgroup\$ Commented Oct 16, 2017 at 13:02
2
\$\begingroup\$

Java 8, (削除) 151 (削除ここまで) (削除) 147 (削除ここまで) (削除) 144 (削除ここまで) (削除) 143 (削除ここまで) 139 bytes

s->{String x="\n"+s;for(int i=64,t;++i<91;)for(char c:x.toCharArray())s+=(t=c&~32)>64&t<91&t>i|c<11?c:" ";return s.replaceAll("\\s+$","");}

Explanation:

Try it here.

s->{ // Method with String as both parameter and return-type
 String x="\n"+s; // Temp-String (equal to leading new-line + input)
 for(int i=64, // Index-integer `i` (starting at 64)
 t; // Temp-integer
 ++i<91;) // Loop (1) from 'A' (65) to 'Z' (90) (inclusive)
 for(char c:x.toCharArray())
 // Inner loop (2) over the character of the array
 s+=(t=c&~32)>64 // If the current character as uppercase is larger than 'A'
 &t<91 // and smaller or equal to 'Z'
 &t>i // and larger than the current index
 |c<11? // or the current character is a new-line
 c // Append the current character to `s`
 : // Else:
 " "; // Append a space to `s` instead
 // End of inner loop (2) (implicit / single-line body)
 // End of loop (1) (implicit / single-line body)
 return s // Return the result,
 .replaceAll("\\s+$",""); 
 // after we've removed all trailing spaces and new-lines
} // End of method
answered Oct 17, 2017 at 13:16
\$\endgroup\$
2
\$\begingroup\$

q, (削除) 42 (削除ここまで) 37 bytes

{(+)max[m]$(m:1+mod[.Q.a?(_)x]26)#'x}

-5 thanks to streetster!


old solution+explanation:

{(+)max[m]$'(m:1+mod[.Q.a?lower x;26])#'x}
{ } / lambda func
 .Q.a?lower x / get lowercase of input (ignores non-alpha values) and find (?) their index in "a...z" (.Q.a). non-alpha values return `26`
 mod[.Q.a?lower x;26] / get mod 26 of each index, this returns 0 where index is 26
 (m:1+mod[.Q.a?lower x;26]) / add 1 and assign to m
 (m:1+mod[.Q.a?lower x;26])#'x / m and x conform, so we can take (#) m copies of each (') x at corresponding indices
 max[m]$'(m:1+mod[.Q.a?lower x;26])#'x / get max of m, and pad each ($') of right-side list to that length
 (+) / transpose the char matrix
answered Sep 4, 2019 at 12:49
\$\endgroup\$
2
  • 1
    \$\begingroup\$ {(+)max[m]$(m:1+mod[.Q.a?(_)x]26)#'x} for 37, cant remember how I solved it when creating the question, probably very similar though! \$\endgroup\$ Commented Sep 4, 2019 at 13:37
  • \$\begingroup\$ @streetster, thanks! updated. didn't know about k's _ , i typed lower in the q interpreter and got k){$[~t&77h>t:abs@@x;.z.s'x;19<t;.z.s@. x;~t in 10 11h;'`type;_x]}. hence giving my answer in q haha \$\endgroup\$ Commented Sep 4, 2019 at 13:58
1
\$\begingroup\$

SOGL V0.12, (削除) 12 (削除ここまで) 11 bytes

ā,{Z4UW1Χ∙┼

Try it Here!

Explanation:

ā push an empty array
 ,{ for each character in the input, pushing it
 Z push the uppercase alphabet
 4 push a duplicate of the character
 U uppercase it
 W find its index in that alphabet
 1Χ get the maximum of that and 1
 ∙ repeat the character that many times
 ┼ append horizontally to that array
answered Oct 10, 2017 at 12:22
\$\endgroup\$
1
2

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.