Sandbox post here.

Create a function or program that "Springifies" a string.

  • Input will be a String in Stdin, or closest alternative
  • Input will only contain printable ASCII and/or spaces
  • Output will be to Stdout, or closest alternative
  • A trailing newlines and spaces are acceptable

How to springify a String

  1. Format the String into as many ASCII spring coils as needed
  2. Pad the coils with spaces, up to the nearest coil
  3. Read off the characters, following the spring around the coils

This is an ASCII spring coil:

# ####
 #    #
# ####

Where the #s are the characters of the String

Here is an example:



b cdef
 g    h
i jklm
p qrst
 u    v
w xyz.

Where the .s replace spaces for visibility.

Then, the string is read back, following the ASCII spring downwards, around the loops, hitting the g and u twice:

1| a  <-3
 V b cdef
    g    h
4| i jklm
 V n  2->


abgjklmhfedcginopuxyz vtsrquw (with a trailing space)

Test Cases

(quotations added to highlight trailing spaces - please ignore in terms of IO)

I: "abcdefghijklmnopqrstuvwxyz"
O: "abgjklmhfedcginopuxyz vtsrquw "

I: "!@#"
O: "!@         #   "

I: ""
O: ""

I: "12345 67890"
O: "12690  7 54368 "

I: " "
O: "               "

Note that the output length is always a multiple of 15, the length of a spring coil

This is , so the shortest answer in bytes wins.

  • \$\begingroup\$ I feel like it would've been much more of a challenge to follow the pattern along the coil. \$\endgroup\$ Commented Jan 20, 2017 at 14:52
  • \$\begingroup\$ @carusocomputing you mean the inverse? \$\endgroup\$ Commented Jan 20, 2017 at 16:47
  • \$\begingroup\$ codegolf.stackexchange.com/a/107531/59376 turns out I didn't understand the challenge as written, that's exactly the challenge ahaha. \$\endgroup\$ Commented Jan 20, 2017 at 17:00

11 Answers 11


Python 2, 104 102 98 Bytes

f=lambda t:''.join((t+' '*13)[ord(x)-97+y*14]for y in range(len(t)/14+1)for x in'abgjklmhfedcgin')

Thanks for the comment help!



t=raw_input()+' '*13
print''.join(t[ord(x)-97+y*14]for y in range(len(t)/14)for x in'abgjklmhfedcgin')
  • \$\begingroup\$ You can just use input() and take input in the format "<stuff>". \$\endgroup\$
    – hyper-neutrino
    Commented Jan 20, 2017 at 3:24
  • \$\begingroup\$ Great first golf! As Alex L. points out, we allow input to be taken in quotes. You can also use a lambda to give an anonymous function rather than a program -- this is often shorter. \$\endgroup\$
    – xnor
    Commented Jan 20, 2017 at 3:28
  • \$\begingroup\$ Fails for the empty string test case with an IndexError. I think you may need to change 13 to 14 and pop off the final value (much like my Jelly answer). \$\endgroup\$ Commented Jan 20, 2017 at 7:30
  • \$\begingroup\$ ...changing the +13 to +14 and the +1 to +(len(t)%14>0) would do it, but there must be a shorter way. \$\endgroup\$ Commented Jan 20, 2017 at 7:41

JavaScript (ES6), 79 bytes

s=>s.replace(/.{1,14}/g,s=>'0169abc7543268d'.replace(/./g,c=>s['0x'+c-0]||' '))
<input oninput=o.textContent=f(this.value)><pre id=o>

Hexadecimal string shamelessly stolen from @ETHproductions.

  • \$\begingroup\$ @ETHproductions Thanks, fixed. \$\endgroup\$
    – Neil
    Commented Jan 20, 2017 at 17:04
  • \$\begingroup\$ That's brilliant! \$\endgroup\$
    – dodov
    Commented Jan 20, 2017 at 22:11
  • \$\begingroup\$ It's nice how the snippet lets you see the result as you type it \$\endgroup\$ Commented Jan 22, 2017 at 19:26

Jelly, 26 bytes




“4ṘƝ;þ¦Ɱ’b®¤ị - Link 1, output for a single coil: char array
           ¤  - nilad followed by link(s) as a nilad
“4ṘƝ;þ¦Ɱ’     - base 250 number, 13140239220751650
          ®   - retrieve from register (14 from main link)
         b    - convert to base, [1,2,7,10,11,12,13,8,6,5,4,3,7,9,0]
            ị - index into the char array

;⁶x14©¤s®ṖÇ€ - Main link: theString
      ¤      - nilad followed by link(s) as a nilad
 ⁶           - a space character
  x          - repeated
   14©       - place 14 into the register and yield 14
;            - concatenate theString with the 14 spaces
       s     - split into chunks of length
        ®    -     retrieve from register (14)
         Ṗ   - pop last entry from the result (removes the space only last entry of 14 chars or less)
          Ç€ - call the last link (1) as a monad for €ach
             - implicit print

Retina, 71 bytes


Try it online!

Permuting strings isn't exactly concise in Retina...


JavaScript (ES7), 144 143 141 114 104 103 bytes

Thanks to ETHProductions for a 10B save!

a=>[...b=a+' '.repeat(15-a.length%15)].map((_,c)=>b['0x'+'0169abc7543268d'[c%15]-0+(c/15|0)*14]).join``


f=a=>[...b=a+' '.repeat(15-a.length%15)].map((_,c)=>b['0x'+'0169abc7543268d'[c%15]-0+(c/15|0)*14]).join``


abgjklmhfedcginopuxyz vtsrquw 
  • \$\begingroup\$ Very nice. You can save some bytes by converting the array to a hexadecimal string, and using +('0x'+whatever) to convert it to a number: (_,c)=>b[(c/15|0)*14+ +('0x'+'0169abc7543268d'[c%15])] \$\endgroup\$ Commented Jan 20, 2017 at 12:45
  • \$\begingroup\$ Clever trick. I was already thinking of other ways to write the array, but I couldn't come up with any. I can still shorten that, by placing the hexadecimal number first and then the multiplication, making the space needless. \$\endgroup\$
    – Luke
    Commented Jan 20, 2017 at 14:22
  • \$\begingroup\$ You could even do '0x'+'...'[c%15]-0+(c/15|0)*14 to save yourself a pair of parentheses :-) \$\endgroup\$ Commented Jan 20, 2017 at 14:32
  • \$\begingroup\$ You're right. Added. \$\endgroup\$
    – Luke
    Commented Jan 20, 2017 at 14:40

Perl 6, 61 bytes

{S:g/(.)**1..14/{[~] $0["abgjklmhfedcgin".ords X-97]X//" "}/}

How it works

The basic structure is this:

{                                  }  # A lambda.
 S:g/(.)**1..14/{                }/   # Regex-replace segments of 1-14 characters, with:
                     $0               #   The single-char submatches captured by the parens.
                       [  ]           #   Index them using certain indices (see below).
                           X//" "}    #   Replace each undefined element with a space.
                 [~]                  #   Concatenate the characters.

The expression used to index into each 14-characters segment is "abgjklmhfedcgin".ords X- 97, which works as follows:

  1. Take the hard-coded string abgjklmhfedcgin.
  2. Get its codepoints: 97 98 103 106 107 108 109 104 102 101 100 99 103 105 110.
  3. Subtract 97 from each number: 0 1 6 9 10 11 12 7 5 4 3 2 6 8 13.

Perl 6, 64 bytes

{[~] .comb(14)».comb»[0,1,6,9..12,7,5...2,6,8,13].flat X//" "}

Try it online!

How it works

The basic structure is this:

{                                    }  # A lambda.
     .comb(14)                          # Split the argument into substrings of <= 14 chars.
              ».comb                    # Split each substring into a list of characters.
                    »[  ]               # Index each list using the same indices (see below).
                         .flat          # Flatten the resulting nested list.
                               X//" "   # Replace each undefined element with a space.
 [~]                                    # Concatenate the list to get a string again.

Same indices as above, but since we're calling .flat anyway, we can use a nested (but 1 byte shorter) expression for them: 0,1,6,9..12,7,5...2,6,8,13.

(Looks trivial, but actually relies on a parsing peculiarity of Rakudo Perl 6 that is probably a bug. To write it without exploiting that bug, one would have to add parens around the 5...2.)


Befunge-93, 97 bytes

==    =  ====

Try it online!

This is a breakdown of the source code with the various component parts highlighted.

Source code with execution paths highlighted

* The main loop starts off executing right to left, wrapping around to the right hand side of the playfield. This is where we read the first character from stdin, and terminate if it's an EOF.
* The next section makes sure any EOF characters are converted to spaces using the formula c = c + 31*!(c+1). Although this won't apply on the first iteration, it can occur on subsequent passes.
* A copy of the character is saved to temporary memory, and then a lookup of the current index is performed on the table on line four (*) to determine whether the character should be output or not.
* If the character needs to be output, we take the left branch. A swap is performed here to cancel out the swap that's going to occur next, and then a zero is pushed to force the branch right.
* If the character wasn't output, we swap it down the stack beneath the index counter (this is the swap that gets cancelled in the left branch). And in both cases we save the character to memory at the current index offset, increment the index, and check if it's greater than 13.
* If not, we read the next character from stdin and repeat the inner loop.
* If it is, we'll have finished a set of 14 characters, 7 having been output (abgjklm), and 7 remaining on the stack (cdefhin). We drop the last two, output the remaining 5 (hfedc), and then retrieve and output the special cases g, i and n from memory.
* And that brings us back to the start of the main loop, where we repeat the process again for the next 14 characters.

  • \$\begingroup\$ Nice explanation, well done \$\endgroup\$ Commented Jan 22, 2017 at 19:26

Mathematica, 77 72 bytes

Thanks to JungHwan Min for saving 5 bytes!

Join@@Partition[#,14,14,{1,1}," "][[;;,LetterNumber@"abgjklmhfedcgin"]]&

Unnamed function taking a list of characters as input and returning a list of characters. Partition[#,14,14,{1,1}," "] splits the input into sublists of length 14, padding with spaces if necessary. LetterNumber@"abgjklmhfedcgin" evaluates to {1,2,7,10,11,12,13,8,6,5,4,3,7,9,14}, which indicates the order to take each length-14 sublist in (repeating the 7th element appropriately). Then [[;;,...]] takes the elements of all the length-14 sublists in that order, and Join@@ joins the answers together.

Previous submission:

Join@@Partition[#,14,14,{1,1}," "][[All,83224017339955102~IntegerDigits~16]]&
  • 1
    \$\begingroup\$ LetterNumber@"abgjklmhfedcgin" is a shorter way to compress the list. Also ;; instead of All saves a byte. \$\endgroup\$ Commented Jan 20, 2017 at 4:33
  • \$\begingroup\$ Great suggestions! \$\endgroup\$ Commented Jan 20, 2017 at 4:41

Python 3, 86 bytes

lambda s:''.join(t[i%14]for t in zip(*[iter(s+' '*13)]*14)for i in b'Tq>]zQ|1/X;:L$o')

Try it online!

As a bonus, the string Tq>]zQ|1/X;:L$o is a valid CJam program that prints the unique characters on standard input, sorted. Try it online! (+ explanation)


PHP, 94 bytes

foreach(str_split($argv[1],14)as$s)for($i=0;$c=abgjklmhfedcgin[$i++];)echo$s[ord($c)-97]??" ";

splits command line argument to 14-byte chunks and loops through the translation string as index for the sub-string. Run with php -nr '<code>' <string>.

I was glad to find out that ?? also accepts the empty string (for an "invalid" index) as null.


Ruby, 83 bytes

->s{v="";(s+" "*13).scan(/.{14}/){|y|"0169:;<7543268=".chars{|o|v+=y[o.ord-48]}};v}

First idea was using hex numbers, but ord-48 saves another byte (stolen from throx's answer).


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.