47
\$\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\$
14
  • 2
    \$\begingroup\$ May we output a list of strings instead of a single string with linefeeds? \$\endgroup\$
    – Arnauld
    Nov 21, 2019 at 13:10
  • 16
    \$\begingroup\$ I don't think a single answer uses recursion \$\endgroup\$
    – Jo King
    Nov 22, 2019 at 1:39
  • 3
    \$\begingroup\$ “Human readable” prohibits most of the languages popular here! \$\endgroup\$
    – WGroleau
    Nov 22, 2019 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, 2019 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\$ Nov 22, 2019 at 11:41

76 Answers 76

3
\$\begingroup\$

IBM/Lotus Notes Formula, 116 bytes

a:="zyxwvutsrqponmlkjihgfedcba";p:="";@For(x:=1;x<=@Length(i);x:=x+1;c:=@Right(@Left(i;x);1);p:=p:(c+@Right(a;c)));p

I have never found a practical use for @For except when golfing.

enter image description here

\$\endgroup\$
3
\$\begingroup\$

Bash, 73 63 57 bytes

while read -n1 a;do [ - $a]&&echo||eval echo {$a..a};done

Try it online!

-6 bytes thanks to Kritixi Lithos

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can skip out on fold with read -n1 a. Also apparently [ = $a] can replace [ -z $a] \$\endgroup\$
    – user41805
    Nov 22, 2019 at 10:26
  • \$\begingroup\$ Beautiful. Tyvm. \$\endgroup\$
    – Jonah
    Nov 22, 2019 at 12:28
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.

\$\endgroup\$
3
\$\begingroup\$

J, 22 bytes

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

Try it online!

\$\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

\$\endgroup\$
0
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.

\$\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!

\$\endgroup\$
3
\$\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!

\$\endgroup\$
2
  • \$\begingroup\$ Several spaces can be removed for 79 bytes \$\endgroup\$ Nov 22, 2019 at 19:06
  • \$\begingroup\$ You actually don't need the semicolons and some of the parenthesis: Try it online! \$\endgroup\$
    – Laikoni
    Feb 15, 2021 at 13:56
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

\$\endgroup\$
4
  • \$\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, 2019 at 18:02
  • \$\begingroup\$ @manatwork Thanks for the tips. I was mostly just banging out a solution. \$\endgroup\$ Nov 22, 2019 at 18:06
  • \$\begingroup\$ 55 bytes \$\endgroup\$
    – Shaggy
    Nov 23, 2019 at 0:32
  • \$\begingroup\$ @Shaggy Thank you! I didn't though about trying that. \$\endgroup\$ Nov 25, 2019 at 9:42
3
\$\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
\$\endgroup\$
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
\$\endgroup\$
0
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 < ,
]
\$\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
\$\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.

\$\endgroup\$
2
  • \$\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, 2019 at 10:14
  • \$\begingroup\$ I tried n:byte() and it didn't seem to work. Started complaining about function calls. \$\endgroup\$
    – Corsaka
    Nov 26, 2019 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!

\$\endgroup\$
1
  • \$\begingroup\$ indeed, reading again the post, the input may only contain the lower-case letters a-z and the space character \$\endgroup\$ Nov 21, 2019 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
\$\endgroup\$
2
\$\begingroup\$

Kotlin, 56 bytes

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

Try it online!

\$\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!

\$\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
\$\endgroup\$
2
\$\begingroup\$

Red, 56 bytes

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

Try it online!

\$\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!

\$\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.

\$\endgroup\$
1
  • \$\begingroup\$ -4 : lambda i:[map(chr,range(ord(x),96,-1))for x in i] \$\endgroup\$
    – Jakque
    May 22, 2021 at 10:20
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

\$\endgroup\$
1
  • 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, 2019 at 10:26
2
\$\begingroup\$

Rust, 63 bytes

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

Try it online!

\$\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

\$\endgroup\$
2
  • 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\$ Nov 24, 2019 at 4:15
  • \$\begingroup\$ Of course! How did I miss such obvious stuff. Thanks for pointing it out \$\endgroup\$
    – Malivil
    Nov 24, 2019 at 16:19
2
\$\begingroup\$

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

say reverse a..$_ for@F

Try it online!

\$\endgroup\$
0
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
\$\endgroup\$
2
\$\begingroup\$

TCL, 179 bytes

rename string d;proc a s {set b zyxwvutsrqponmlkjihgfedcba;if {$s=={}} return;if {[set c [d first [d index $s 0] $b]]<0} {puts {}} {puts [d range $b $c end]};a [d replace $s 0 0]}

Try it online!

ungolfed version

proc a {s} {
    set b zyxwvutsrqponmlkjihgfedcba
    if {$s=={}} return


    if {[set c [string first [string index $s 0] $b]]<0} then {
            puts {} # if it's a space print a newline
    } else {
        puts [string range $b $c end] # print the substring of $b starting at the character
    }

    #recurse on the string minus the front character
    a [string replace $s 0 0]
}

a [concat $argv]
\$\endgroup\$
1
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
\$\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
\$\endgroup\$

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.