40
\$\begingroup\$

Disclaimer: This challenge inspired by me spending the morning debugging recursive functions, which have been frying my brain a little.

Here's an example of recursion, from a letter, we keep going to the previous letter of the alphabet, printing out each one as we go, until we hit the letter a, then we print that and stop. We do this for each letter in a string and there's a pretty pattern at the end of it.

The task

  • Start with a string of characters
    • The input string may only contain the lower-case letters a-z and the space character.
  • For each letter, produce a line of text (terminal output or variable or whatever)
    • Print out the letter
    • Print out the previous letter (on the same line)
    • Print out the previous letter (on the same line)
    • Print out the previous letter (on the same line)
    • ...
    • If the letter is 'a', print it out and move to the next line.
    • If it's a space, print out an empty line (or one just containing the space character.

The rules

  • It's golf, try and make your code short.
  • Any language you like.
  • Please include a link to an online interpreter.
  • The output should be human-readable (e.g. I can't work it out from a list of bytes.
  • Follow the rules of the standard loopholes ¯\_(ツ)_/¯
  • Recursion is not mandated by the rules, but it's probably necessary.

Test Cases

Input: 'abcdefghijklmnopqrstuvwxyz' Output:

a
ba
cba
dcba
edcba
fedcba
gfedcba
hgfedcba
ihgfedcba
jihgfedcba
kjihgfedcba
lkjihgfedcba
mlkjihgfedcba
nmlkjihgfedcba
onmlkjihgfedcba
ponmlkjihgfedcba
qponmlkjihgfedcba
rqponmlkjihgfedcba
srqponmlkjihgfedcba
tsrqponmlkjihgfedcba
utsrqponmlkjihgfedcba
vutsrqponmlkjihgfedcba
wvutsrqponmlkjihgfedcba
xwvutsrqponmlkjihgfedcba
yxwvutsrqponmlkjihgfedcba
zyxwvutsrqponmlkjihgfedcba

Input: 'zyxwvutsrqponmlkjihgfedcba'

zyxwvutsrqponmlkjihgfedcba
yxwvutsrqponmlkjihgfedcba
xwvutsrqponmlkjihgfedcba
wvutsrqponmlkjihgfedcba
vutsrqponmlkjihgfedcba
utsrqponmlkjihgfedcba
tsrqponmlkjihgfedcba
srqponmlkjihgfedcba
rqponmlkjihgfedcba
qponmlkjihgfedcba
ponmlkjihgfedcba
onmlkjihgfedcba
nmlkjihgfedcba
mlkjihgfedcba
lkjihgfedcba
kjihgfedcba
jihgfedcba
ihgfedcba
hgfedcba
gfedcba
fedcba
edcba
dcba
cba
ba
a

Input: 'hello world' Output:

hgfedcba
edcba
lkjihgfedcba
lkjihgfedcba
onmlkjihgfedcba

wvutsrqponmlkjihgfedcba
onmlkjihgfedcba
rqponmlkjihgfedcba
lkjihgfedcba
dcba
\$\endgroup\$
  • 2
    \$\begingroup\$ May we output a list of strings instead of a single string with linefeeds? \$\endgroup\$ – Arnauld Nov 21 '19 at 13:10
  • 12
    \$\begingroup\$ I don't think a single answer uses recursion \$\endgroup\$ – Jo King Nov 22 '19 at 1:39
  • 3
    \$\begingroup\$ “Human readable” prohibits most of the languages popular here! \$\endgroup\$ – WGroleau Nov 22 '19 at 2:50
  • 2
    \$\begingroup\$ @WGroleau Ah, I think I've spotted what's gone wrong here. I didn't require that the code should be human-readable, only the result. \$\endgroup\$ – AJFaraday Nov 22 '19 at 9:13
  • 3
    \$\begingroup\$ Recursion is never necessary. At the very worst, you can just use stack data structure to have your own "recursion" in a flat loop, ending when the stack is empty. \$\endgroup\$ – Tomáš Zato - Reinstate Monica Nov 22 '19 at 11:41

64 Answers 64

3
\$\begingroup\$

Retina, 38 bytes

L$`.
27*$&
+T` l`_al`(?<=(.))\1+
aa+
a

Try it online! Explanation:

L$`.
27*$&

List each character 27 times each on its own line.

+T` l`_al`(?<=(.))\1+

Count all the characters back down to a, except the first of each run, and also delete trailing spaces.

aa+
a

Remove trailing as.

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

J, 22 bytes

(u:97+i._26)&(i.}.[)"0

Try it online!

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Keg, 33 bytes

@f1|: =[,|:a=[,|:,;@fƒ]]ƒ?(@fƒ
,)

Try it online!

Unlike most people here, this answer actually uses recursion!

Keg, -ir -lp, 22 bytes

(: >[:&aɧ(&\`-;|,)],
,

Try it online!

Iterative approach as suggested by @A

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Lua, 99 bytes

function r(l)return l:find"[` ]"and"\n"or l..r(string.char(l:byte()-1))end
print((...):gsub(".",r))

Try it online!

Only works if we can have redundant output, else +1 byte.

Explanation

Creates a recursive function r that returns what each letter should turn into. When the input letter of this function is a space or the character before a (which is `) then this should not be printed, but a new line instead.

Replace each character in the input string (the first command-line argument) with the output of the function r called with this character.

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Common Lisp, 127 bytes

Also the first truly recursive answer:

(labels((p(x)(princ(code-char x))(if(< 97 x)(p(1- x))(terpri)))(s(s n)(p(char s n))(if(>(length s)n)(s(1+ n))))(x(s)(s 0)))#'x)

Test:

(funcall (labels((p(x)(princ(code-char x))(if(< 97 x)(p(1- x))(terpri))t)
                 (s(n s)(and(>(length s)n)(p(char-code(char s n)))(s(1+ n)s)))
                 (x(s)(s 0 s)))#'x)
         "hello world")

Try it online!

The recursive p function prints from an ascii code down to 97, then a newline (terpri) (this also covers the space case since its code is 32).

The recursive s function iterates over string s by increasing index n, calling p at each step for the character at position n.

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Matlab / Octave, 25 bytes

for i=s['' i-0:-1:97]
end

Assumes the input string s, prints out to console.

  • Iterate over the contents of the string with for i=s
  • i-0 implicitly converts char to number
  • num:-1:97 outputs the range descending from the number down to 97 (ascii a)
  • space results in empty output as it already is less than 97
  • ['' int] concatenates an empty char with a number, resulting in a char (saves one byte compared to char(num).
  • each loop iteration output is printed as a line to console, which is what Matlab does when there is no semicolon terminating the line.

Try it online!

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

PHP, 68 63 55 bytes

Simple approach, similar to my previous answer.

for(;$c=$argn[$i++];)echo$c<a?"":join(range($c,a)),"\n";

The \n was counted as 1 character, not 2 characters.

This is meant to be used with php -R.


Thanks to @manatwork for saving 5 bytes, and providing the link to try the code: https://tio.run/##BcHRCYAgEADQ/6YQEVSoBSpohxaI6zKvEE9OofHtvRMq9UJFTbuy/WYJgORqk6OW9DRnQGL2UA36gMQGV9i0nl9@shPIMTiDI3g/6kEv3XYKKbH6WNL1Aw

Thanks to @Shaggy for saving another 8 bytes, and providing an updated link: https://tio.run/##BcFBCoAgEADAe68QWVDRPpBFf@gaHTYzNcQVO/R8mznxjb3GysaNiX5TkxbcAthC2SFpfVjlXSRwM66cTw@lIhuW4CU4g0oZPnDbRY8@Z2IftXz9

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ The only input character below “a” will be “ ”, so you can just use $c<a instead of $c==' '. And the $glue parameter of join() is optional and “Defaults to an empty string.” Try it online! \$\endgroup\$ – manatwork Nov 22 '19 at 18:02
  • \$\begingroup\$ @manatwork Thanks for the tips. I was mostly just banging out a solution. \$\endgroup\$ – Ismael Miguel Nov 22 '19 at 18:06
  • \$\begingroup\$ 55 bytes \$\endgroup\$ – Shaggy Nov 23 '19 at 0:32
  • \$\begingroup\$ @Shaggy Thank you! I didn't though about trying that. \$\endgroup\$ – Ismael Miguel Nov 25 '19 at 9:42
3
\$\begingroup\$

GolfScript, 27 18 17 bytes

{),97>-1%10}/]''+

Try it online!

Explanation:

 {           }/       Iterate over (implicit) input
  ),                  Create array [0 1 2 ... n]
    97>               Remove items less than 97
        -1%           Reverse order
           10         Push 10
               ]      Place in array
                ''+   Convert ascii values to string
| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

brainf**k 123 bytes

,[>>[-]<----[---->+<]>+<++++[->>++++++++<<]++++++++++>>[-<<<->>>>+<]<<<[->>->[-]+>+<<<<]>>>[-<[+>>.-<<]>]<<.[-]>>>[-]<<<<,]

Try it online!

Not better than the other brainfuck solutions posted in the comments, but still too much work not to post it ;-) In contrast to the bf solutions above, this does not need a circular cell ring.

How it works

p0 
,
[  {input}
p1 >  
p2 > [-] < ----[---->+<]>+< #64
p3 ++++[->>++++++++<<]  #32
p1 ++++++++++ # 10
p2 >
p3 >
   [
     -
p2   <
p1   <
p0   < -
p1   >
p2   >
p3   >
p4   > +
p3   <
   ]
p2 <
p1 <
p0 <
   [
     -
p1   >
p2   > -
p3   >[-]+ # indicates that output is required
p4   > +
p3   <
p2   <
p1   <
p0   <
   ]
p1 > 
p2 >
p3 >  # if output required
   [
     -
p2   <
     [
       +
p3     >
p4     > . -
p3     <
p2     <
     ]
p3   >
   ]
p2 <
p1 < . [-]   
p2 >
p3 >
p4 > [-]
p3 <
p2 <
p1 <
p0 < ,
]
| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

naz, 104 bytes

2a2x1v2m8m2x2v3m1a2x3v1x1f3x1v4e3x2v3e1o2f0x1x2f3x3v3e1s1o2f0x1x3f1r3x1v4e2x4v0m9a1a1o4v1f0x1x4f0a0x1r1f

Works for any input string terminated with the control character STX (U+0002).

If an extra trailing newline is allowed, we can save another 14 bytes:

2a2x1v2m8m2x2v3m1a2x3v1x1f1r3x1v4e3x2v3e1o2f0x1x2f3x3v3e1s1o2f0x1x3f0m9a1a1o1f0x1x4f0a0x1f

Explanation of the 104-byte version (with 0x commands removed)

2a2x1v                       # Set variable 1 equal to 2
2m8m2x2v                     # Set variable 2 equal to 32 (space)
3m1a2x3v                     # Set variable 3 equal to 97 ("a")
1x1f3x1v4e3x2v3e1o2f         # Function 1
                             # Jump to function 4 if the register equals variable 1
                             # Jump to function 3 if the register equals variable 2
                             # Otherwise, output and jump to function 2
1x2f3x3v3e1s1o2f             # Function 2
                             # Jump to function 3 if the register equals variable 3
                             # Otherwise, subtract 1, output,
                             # and jump back to the start of the function
1x3f1r3x1v4e                 # Function 3
                             # Read a byte
                             # Jump to function 4 if it equals variable 1
            2x4v             # Otherwise, store it in variable 4,
                0m9a1a1o     # output a newline,
                        4v1f # read variable 4 into the register, and jump to function 1
1x4f0a                       # Function 4
                             # Add 0 to the register
1r1f                         # Read the first byte of input and jump to function 1
| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

GolfScript, 12 bytes

{),97>-1%n}%

Try it online!

Explanation

{         }% # Map over the implicit input
 ),          # Generate range to 0x00
   97>       # Remove all that is less than 97
      -1%    # Reverse the string
         n   # Add a newline
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Lua, 107 103 bytes

s=string
for n in io.read():gmatch"."do t=''for j=s.byte(n)-96,1,-1 do t=t..s.char(j+96)end print(t)end

Try it online!

Again, still a newbie to this.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ For the string.byte you can also do n:byte(). As for the loop, can't you also loop from byte to 97? That would remove 5 bytes as well. I tried this with actual recursion, but yours can definitely be shorter than mine is now. See this where I tried to golf yours even more \$\endgroup\$ – Anderium Nov 23 '19 at 10:14
  • \$\begingroup\$ I tried n:byte() and it didn't seem to work. Started complaining about function calls. \$\endgroup\$ – Corsaka Nov 26 '19 at 8:57
2
\$\begingroup\$

Perl 5 (-nF//), 31, 28 bytes

-3 bytes thanks to @nwellnhof

say/\w/&&reverse a..$_ for@F

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ indeed, reading again the post, the input may only contain the lower-case letters a-z and the space character \$\endgroup\$ – Nahuel Fouilleul Nov 21 '19 at 13:25
2
\$\begingroup\$

Charcoal, 9 bytes

ES⮌…β⊕⌕βι

Try it online! Link is to verbose version of code. Explanation:

 S          Input string
E           Map over characters
    β       Lowercase alphabet
   …        Truncated to length
      ⌕     Position of
        ι   Current charcter in
       β    Lowercase alphabet
     ⊕      Incremented
  ⮌         Reversed
             Each prefix implicitly printed on its own line
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Kotlin, 56 bytes

{it.map{println(('a'..it).joinToString("").reversed())}}

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

jq, 39 characters

explode|map([range(.;96;-1)]|implode)[]

Or remove the trailing [] to get the output as array of strings.

Sample run:

bash-5.0$ jq -Rr 'explode|map([range(.;96;-1)]|implode)[]' <<< 'cgcc'
cba
gfedcba
cba
cba

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Pyth, 7 bytes

m_<GhxG

Try it online!

Lowercase alphabet autos feel like cheating but oh well. Might add a recursive solution if I come up with anything good. Returns list of strings.

How it works

m_<GhxG
m         - Map on implicit input
 _        - The reverse of
  <G      - The lowercase alphabet at and below
     xG   - The index of the implicit element of input in the lowercase alphabet
    h     - above + 1
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Red, 56 bytes

func[s][foreach c s[until[prin c#"a"> c: c - 1]print""]]

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Icon, 66 bytes

procedure f(s)
c:=ord(!s)&write()&writes(char(c to 97by-1))&\z
end

Try it online!

Longer alternative:

Icon, 72 bytes

procedure f(s)
c:=ord(!s)-95&write((0>c&"")|reverse(&lcase[1:c]))&\z
end

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Python 2, 68 bytes

for x in input():
 o="";c=ord(x)
 while c>96:o+=chr(c);c-=1
 print o

Try it online!

Nothing very clever here.

Python 2, 64 53 bytes

lambda i:[map(chr,range(x,96,-1))for x in map(ord,i)]

Try it online!

Here's one for 64 53 but it outputs a list of lists which is not only ugly but probably stretches "flexible input/output" to near breaking point.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

SimpleTemplate, 46 66 bytes

This was a simple challenge, but quite fun!

{@eachargv.0}{@echol}{@if_ matches"@\w@"}{@forfrom _to"a"}{@echo_}

Loops over all the chars (that match with \d) in the string, and then outputs all the characters from that char to "a".


Ungolfed:

{@each argv.0 as char}
    {@echo "\n"}
    {@if char matches "@^[a-z0-9_]$@"}
        {@for letter from char to "a"}
            {@echo letter}
        {@/}
    {@/}
{@/}

The argv variable contains all the arguments passed to the render() method, or to the function, when converted.

The {@echo "\n"} ({@echol} in the golfed version) is needed because all whitespace will be automatically trimmed.

You can try the golfed version on https://ideone.com/Ru8shP

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Glad you enjoyed it! I find simple challenges seem to capture folks' imaginations and are more likely to take off than something overcomplicated. \$\endgroup\$ – AJFaraday Nov 22 '19 at 10:26
2
\$\begingroup\$

Rust, 63 bytes

|s:&str|s.bytes().map(|c|(b'a'..=c).rev()).collect::<Vec<_>>();

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

C# (Visual C# Interactive Compiler), 80 77 bytes

a=>{var b="";foreach(var c in a){for(var j=c;j>96;)b+=j--;b+="\n";}return b;}

Try it online!

-3 bytes thanks to @my pronoun is monicareinstate for pointing out some unnecessary stuff

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ >=97 -> >96; the innermost curly braces are unnecessary. Unfortunately, (_=>{code})(0) doesn't execute code as an expression :( (related fun fact: the C++ code [](){}() executes an empty lambda expression, so I include it or something like <:](){%>() with digraphs everywhere) \$\endgroup\$ – my pronoun is monicareinstate Nov 24 '19 at 4:15
  • \$\begingroup\$ Of course! How did I miss such obvious stuff. Thanks for pointing it out \$\endgroup\$ – Malivil Nov 24 '19 at 16:19
2
\$\begingroup\$

Standard ML (MLton), 84 79 bytes

fun t#"a"="a"|t#" "=" "|t x=(str x)^t(chr((ord x)-1));fun q p=map t(explode p);

Try it online!

Done by coworker, I insisted it should recursive at least partially.

Thanks for -5 to Galen Ivanov!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Several spaces can be removed for 79 bytes \$\endgroup\$ – Galen Ivanov Nov 22 '19 at 19:06
2
\$\begingroup\$

Forth (gforth), 66 bytes

: f bounds do i c@ dup 96 - 0 max 0 ?do dup emit 1- loop cr loop ;

Try it online!

Code Explanation

: f            \ start a new word definition
  bounds       \ get starting and ending address of string
  do           \ loop from starting address to ending address
    i c@       \ get ascii value at current address
    dup 96 -   \ get numerical position in alphabet
    0 max      \ if negative (char is space), set to 0
    0 ?do      \ loop from 0 to position in alphabet
      dup emit \ output character
      1-       \ subtract 1 from current character (move backwards in alphabet)
    loop       \ end inner loop definition
    cr         \ output a newline
  loop         \ end outer loop definition
;              \ end word definition
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Perl 5 + -a -M5.010, 23 bytes

say reverse a..$_ for@F

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ @JoKing goddammit. I thought it was too easy... Thanks! \$\endgroup\$ – Dom Hastings Nov 28 '19 at 19:42
2
\$\begingroup\$

Pip -l, 11 bytes

CRV97\,A_Ma

Try it online!

Explanation

          a  Input as a command-line argument
         M   Map this function to each of its characters:
       A_     Get ASCII code
   97\,       Range from 97 up to and including the above
 RV           Reverse the range
C             Convert to (a list of) characters
             With -l, output each list of chars concatenated on separate lines
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

W, 7 5 bytes

Lowercase alphabet auto feels like cheating. This one does not use any alphabet built-in with the same bytecount. DISCLAIMER: insert literal spaces as \x20 in your input strings.

^'a.E

Explanation

   E Map over every item in the input
^    Trim out all literal whitespace in this item
 'a. Generate a range to the character 'a'
     An error-proof mechanism returns the null string
     if any of those operands are the null string
     Implicit print on each iteration
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Burlesque, 13 bytes

XX{'ajr\<-}m[

Try it online!

XX  # Explode a string into characters
{
'a  # Literal "a"
jr\ # Create range from "a" -> char and join as string
<-  # Reverse string
}m[ # Apply to each char
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

x86-16 machine code, IBM PC DOS, 27 23 bytes

Binary:

00000000: b408 cd21 b40e cd10 483c 617d f9b0 0acd  ...!....H<a}....
00000010: 10b0 0dcd 10eb e9                        .......

Test and build using xxd -r from above.

Unassembled:

        IN_LOOP: 
B4 08       MOV  AH, 08H        ; DOS read char without echo function
CD 21       INT  21H            ; load next char from STDIN
B4 0E       MOV  AH, 0EH        ; BIOS write char teletype output function
        CHR_LOOP: 
CD 10       INT  10H            ; write to console 
48          DEC  AX             ; move to next char 
3C 61       CMP  AL, 'a'        ; end with an 'a' 
7D F9       JGE  CHR_LOOP       ; keep looping descending chars 
B0 0A       MOV  AL, 0AH        ; CR char 
CD 10       INT  10H            ; write to console 
B0 0D       MOV  AL, 0DH        ; LF char 
CD 10       INT  10H            ; write to console 
EB E9       JMP  IN_LOOP        ; keep looping until ^C/^Break

I/O:

Input via STDIN or interactive input, output to console. Will run until EOF or ^C/^Break.

enter image description here

Iterative approach. Of course, it's 8 bytes just to write a newline character...

| improve this answer | |
\$\endgroup\$

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.