Related: Rather similar (but much easier) challenge horizontally: There I fixed it (with tape)


Given a string only containing upper- and/or lowercase letters (whichever you prefer) and new-lines, put rope vertically to fix it. We do this by checking the difference of two adjacent letters in the alphabet (ignoring wrap-around and only going downward), and filling the space with as much ROPE/rope as we would need.
NOTE: One other key difference between this challenge and the There I fixed it (with tape) challenge is that we're not wasting rope this time like we did with the tape (suggested by @JonathanAllan in part one of the challenge).







  • Between b and d in column 1 should be c (length 1), so we fill this with R;
  • Between e and g in column 1 should be f (length 1), so we fill this with O;
  • Between f and k in column 2 should be ghij (length 4), so we fill this with PERO;
  • Between k and m in column 2 should be l (length 1), so we fill this with P;
  • Between d and c in column 3 should be efghijklmnopqrstuvw (length 19), so we fill this with EROPEROPEROPEROPERO;
  • Between x and z in column 3 should be y (length 1), so we fill this with P;
  • Between a and h in column 3 should be bcdefg (length 6), so we fill this with EROPER.

Challenge rules:

  • The difference only applies downwards, so no rope between za (column 3 in the example above).
  • It is possible to have multiple of the same adjacent letters like dd (column 3 in the example above).
  • You will continue using the ROPE one column at a time to not waste parts (suggested by @JonathanAllan in part 1 of the challenge).
  • You are allowed to take the input in any reasonable format. Can be a single string, string-array/list, character-matrix, etc. Output has the same flexibility.
  • You are allowed to use lowercase and/or uppercase any way you'd like. This applies both to the input, output, and ROPE.
  • Trailing spaces are optional (note that the correct amount of leading spaces are mandatory so the columns are correct).
    Any amount of trailing and/or leading new-lines are also optional.
  • You can assume that all test cases will have the same length across all rows, so a\naa/[[a][a,a]] wouldn't be a valid input.
  • It is possible no ROPE is necessary, in which case the input remains unchanged.

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.

Test cases:

As string:
 Input:  "abc\nbcd\nddd\neex\ngfz\nhka\nimh"
 Output: "abc\nbcd\nRdd\ndeE\nefR\nOPO\ngEP\nhRE\niOR\n kO\n PP\n mE\n  R\n  O\n  P\n  E\n  R\n  O\n  P\n  E\n  R\n  O\n  x\n  P\n  z\n  a\n  E\n  R\n  O\n  P\n  E\n  R\n  h"
As array-matrix:
 Input:  [[a,b,c],[b,c,d],[d,d,d],[e,e,x],[g,f,z],[h,k,a],[i,m,h]]
 Output: [[a,b,c],[b,c,d],[R,d,d],[d,e,E],[e,f,R],[O,P,O],[g,E,P],[h,R,E],[i,O,R],[ ,k,O],[ ,P,P],[ ,m,E],[ , ,R],[ , ,O],[ , ,P],[ , ,E],[ , ,R],[ , ,O],[ , ,P],[ , ,E],[ , ,R],[ , ,O],[ , ,x],[ , ,P],[ , ,z],[ , ,a],[ , ,E],[ , ,R],[ , ,O],[ , ,P],[ , ,E],[ , ,R],[ , ,h]]

As string:
 Input:  "a\nz\na"
 Output: "a\nR\nO\nP\nE\nR\nO\nP\nE\nR\nO\nP\nE\nR\nO\nP\nE\nR\nO\nP\nE\nR\nO\nP\nE\nz\na"
As array-matrix:
 Input:  [[a],[z],[a]]
 Output: [[a],[R],[O],[P],[E],[R],[O],[P],[E],[R],[O],[P],[E],[R],[O],[P],[E],[R],[O],[P],[E],[R],[O],[P],[E],[z],[a]]

As string:
 Input:  "zz\nyy\nxx\nxx\ncc\ncc\nbb\nad"
 Output: "zz\nyy\nxx\nxx\ncc\ncc\nbb\naR\n d"
As array-matrix:
 Input:  [[z,z],[y,y],[x,x],[x,x],[c,c],[c,c],[b,b],[a,d]]
 Output: [[z,z],[y,y],[x,x],[x,x],[c,c],[c,c],[b,b],[a,R],[ ,d]]

As string:
 Input:  "a\nb\nc\nc\nx\nx\ny\nz"
 Output: "a\nb\nc\nc\nR\nO\nP\nE\nR\nO\nP\nE\nR\nO\nP\nE\nR\nO\nP\nE\nR\nO\nP\nE\nx\nx\ny\nz"
 As array-matrix:
  Input:  [[a],[b],[c],[c],[x],[x],[y],[z]]
  Output: [[a],[b],[c],[c],[R],[O],[P],[E],[R],[O],[P],[E],[R],[O],[P],[E],[R],[O],[P],[E],[R],[O],[P],[E],[x],[x],[y],[z]]

As string:
 Input:  "zai\nybj\nxcq\nxcu\ncxw\ncxw\nbyr\nazw"
 Output: "zai\nybj\nxcR\nxcO\ncRP\ncOE\nbPR\naEO\n Rq\n OP\n PE\n ER\n Ru\n OO\n Pw\n Ew\n Rr\n OP\n PE\n ER\n RO\n Ow\n P \n E \n x \n x \n y \n z "
As array-matrix:
  Input:  [[z,a,i],[y,b,j],[x,c,q],[x,c,u],[c,x,w],[c,x,w],[b,y,r],[a,z,w]]
  Output: [[z,a,i],[y,b,j],[x,c,R],[x,c,O],[c,R,P],[c,O,E],[b,P,R],[a,E,O],[ ,R,q],[ ,O,P],[ ,P,E],[ ,E,R],[ ,R,u],[ ,O,O],[ ,P,w],[ ,E,w],[ ,R,r],[ ,O,P],[ ,P,E],[ ,E,R],[ ,R,O],[ ,O,w],[ ,P, ],[ ,E, ],[ ,x, ],[ ,x, ],[ ,y, ],[ ,z, ]]

As string:
 Input:  "asdljasdjk"
 Output: "asdljasdjk"
As array-matrix:
 Input:  [[a,s,d,l,j,a,s,d,j,k]]
 Output: [[a,s,d,l,j,a,s,d,j,k]]

As string:
 Input:  "asdljasdjk\nlkawdasuhq\nasjdhajksd"
 Output: "asdljasdjk\nRkaOdasPhR\nOPOPEajEPO\nPEPER  REP\nERERO  ORE\nROROh  POR\nOPOP   EPq\nPEPE   ROd\nERER   OR \nRsRO   PO \nO jP   EP \nl  w   RE \na  d   Os \n       P  \n       E  \n       R  \n       O  \n       u  \n       k  "
As array-matrix:
 Input:  [[a,s,d,l,j,a,s,d,j,k],[l,k,a,w,d,a,s,u,h,q],[a,s,j,d,h,a,j,k,s,d]]
 Output: [[a,s,d,l,j,a,s,d,j,k],[R,k,a,O,d,a,s,P,h,R],[O,P,O,P,E,a,j,E,P,O],[P,E,P,E,R, , ,R,E,P],[E,R,E,R,O, , ,O,R,E],[R,O,R,O,h, , ,P,O,R],[O,P,O,P, , , ,E,P,q],[P,E,P,E, , , ,R,O,d],[E,R,E,R, , , ,O,R, ],[R,s,R,O, , , ,P,O, ],[O, ,j,P, , , ,E,P, ],[l, , ,w, , , ,R,E, ],[a, , ,d, , , ,O,s, ],[ , , , , , , ,P, , ],[ , , , , , , ,E, , ],[ , , , , , , ,R, , ],[ , , , , , , ,O, , ],[ , , , , , , ,u, , ],[ , , , , , , ,k, , ]]

As string:
 Input:  "re\nop\npo\ner"
 Output: "re\noR\npO\neP\n E\n R\n O\n P\n E\n R\n O\n p\n o\n P\n E\n r"
As array-matrix:
 Input:  [[r,e],[o,p],[p,o],[e,r]]
 Output: [[r,e],[o,R],[p,O],[e,P],[ ,E],[ ,R],[ ,O],[ ,P],[ ,E],[ ,R],[ ,O],[ ,p],[ ,o],[ ,P],[ ,E],[ ,r]]
  • 9
    \$\begingroup\$ Can I fix it with hope instead? Hope is stronger than rope. (This is a poor attempt at humor, not a real question) \$\endgroup\$ Mar 8, 2018 at 14:47
  • \$\begingroup\$ @KevinCruijssen did you mean this is easier of the TAPE is easier?? \$\endgroup\$
    – Dat
    Mar 8, 2018 at 15:24
  • 3
    \$\begingroup\$ @MagicOctopusUrn Nope, rope is our only hope. \$\endgroup\$
    – Steadybox
    Mar 8, 2018 at 15:53
  • \$\begingroup\$ Can I ouput and array of columns?? \$\endgroup\$
    – Dat
    Mar 8, 2018 at 15:56
  • \$\begingroup\$ @Dat The tape challenge is a lot easier (imho). And yes, you can output an array of column. \$\endgroup\$ Mar 8, 2018 at 15:59

7 Answers 7


05AB1E, 38 37 25 bytes

Saved 10 bytes with suggestions from Magic Octopus Urn and another byte changing output format.

Outputs a list of strings.
Footer pretty prints.


Try it online!


'ÙºU                       # store the string "rope" in variable X
    ζ                      # transpose input
     ε                ]    # for each transposed row
      D   )ζ               # zip the row with
       ǥ<                 # the decremented deltas of its character codes  
            ε              # for each pair of [letter, delta-1]
             `F     }      # delta-1 times do:
               X¬          # get the first letter of X (originally "rope")
                 sÀU       # rotate the letters left by 1 and store in X 
                     J     # join the rope-letter to the current row-letter
                       J   # join to list of strings (the new columns)
                        ζ  # transpose
  • \$\begingroup\$ @MagicOctopusUrn: The main difference is that with Tape we started over each time we should insert it, aTAdTAg. Now with rope we continue where we left off on the rope, so aROdPEg. \$\endgroup\$
    – Emigna
    Mar 8, 2018 at 12:28
  • 1
    \$\begingroup\$ missed that tidbit, what about "extend string to length X" and inserting spaces inbetween each character representing places where the "rope" is supposed to go, then inserting the extended string into the spaces? \$\endgroup\$ Mar 8, 2018 at 14:12
  • \$\begingroup\$ @MagicOctopusUrn: I think I have 32 using your suggestion above. Could still be golfable as well. \$\endgroup\$
    – Emigna
    Mar 8, 2018 at 14:28
  • \$\begingroup\$ Does 05AB1E have a: pop a,b,c | push c[b..a] type dealio? \$\endgroup\$ Mar 8, 2018 at 14:44
  • \$\begingroup\$ @MagicOctopusUrn: Nope. I have been thinking it needs one though. \$\endgroup\$
    – Emigna
    Mar 8, 2018 at 14:52

Jelly, 21 bytes


Try it online!


ZµOI’R“¡nⱮ»ṁż@"µF€z⁶Y  Main Link
Z                      Transpose the input so the columns are now rows
 µ                     New monadic chain
  O                    [Vectorizing] Convert each letter to its character code
   I                   [Vectorizing] Get the differences (gap size)
    ’                  [Vectorizing] Add one
     R                 [Vectorizing] Range from 1 .. x
           ṁ           Mold the string        into the ranges
      “¡nⱮ»                            "rope"
            ż@"        Vectorizing zip the rope strings with the original string (place ropes in gaps)
               µ       New monadic chain
                F€     Flatten Each
                  z⁶   Zip and fill with spaces
                    Y  Join on newlines for output

-1 byte thanks to Mr. Xcoder
-2 bytes thanks to Erik the Outgolfer

  • \$\begingroup\$ 21 bytes using rope \$\endgroup\$
    – Mr. Xcoder
    Mar 8, 2018 at 12:15
  • \$\begingroup\$ @KevinCruijssen fixed \$\endgroup\$
    – hyper-neutrino
    Mar 8, 2018 at 13:24
  • \$\begingroup\$ 21 bytes \$\endgroup\$ Mar 8, 2018 at 13:42
  • \$\begingroup\$ @EriktheOutgolfer oh yeah thanks idk why I was each-ing auto-each things :P \$\endgroup\$
    – hyper-neutrino
    Mar 8, 2018 at 14:11
  • \$\begingroup\$ @KevinCruijssen done \$\endgroup\$
    – hyper-neutrino
    Mar 23, 2018 at 16:05

Python 2, 197 194 bytes

def f(s):
 for i in zip(*s):
	for c,C in zip(i,i[1:]+(' ',)):l=(C>c)*(ord(C)+~ord(c));x[-1]+=c+r[:l];r=r[l:]
 print zip(*['%*s'%(-max(map(len,x)),s)for s in x])

Try it online!

  • -3 bytes thanks to ovs

Ruby, 119 bytes

->a{l=0;a.map!{|r|r.reduce{|x,y|x+("ROPE"*7)[l%4,-l+l+=[0,y.ord+~x[-1].ord].max]+y}}.map{|s|s.ljust a.map(&:size).max}}

Try it online!

Yes, this is much more difficult than the "TAPE" challenge. I tried to build up on my solution to that task, but this has a few extra twists.

Takes input as a columnwise array of characters, returns an array of strings, also in columnwise format. The code in the footer of the TIO link performs pre- and post-processing of I/O data so that we could supply a more manageable string and then print the result nicely.


The code makes two passes through the input array.

In the first pass we apply the reduce operation that fills up the space between the characters with the required amount of ROPE (y.ord-x[-1].ord-1 characters, if positive). We also need to keep track of the used ROPE length (l).

Unlike in the TAPE case we cannot simply use rjust for filling, as it would always start from the R character. Instead, taking a proper slice of a long "ROPEROPE..." string seems lighter on byte count, especially since we also need to update l on the fly.

In the second pass we left-justify the resulting strings with spaces to match the length of the longest of them. Since we need the full results of the previous iteration here, the first pass modifies the array in place (hence map!, not map).

  • \$\begingroup\$ To my mind your columnwise I/O format already solves so much of the problem that it becomes a loophole \$\endgroup\$
    – Ton Hospel
    Mar 11, 2018 at 23:17
  • \$\begingroup\$ @TonHospel I also hesitated at first, but OP specifically confirmed this is OK in comments to the challenge \$\endgroup\$
    – Kirill L.
    Mar 12, 2018 at 8:06
  • \$\begingroup\$ Ah, not what I would have decided, but that's OK then. \$\endgroup\$
    – Ton Hospel
    Mar 12, 2018 at 8:41

-1 bytes thanks to Kevin Cruijssen

-70 bytes thanks to Jonathan Frech, wow.......

Python 3, 203 bytes

def f(s,c=0,x=()):
	for i in range(len(s[0])):
		p,o=" ",""
		for j in s:t=j[i];y=p>' 'and~ord(p)+ord(t);o+=('ROPE'*y)[c:y+c]+t;c,p=c%4+y*(y>=0)%4,t
	for i in x:yield i.ljust(len(max(x,key=len)))

Try it online!

  • \$\begingroup\$ ord(t)-ord(p)-1 can be ord(t)+~ord(p) to save a byte again. ;) Here is the relevant tip. \$\endgroup\$ Mar 8, 2018 at 17:39
  • \$\begingroup\$ +=[o] -> +=o,. \$\endgroup\$ Mar 8, 2018 at 17:49
  • \$\begingroup\$ @Dat Are you sure? \$\endgroup\$ Mar 8, 2018 at 18:03
  • \$\begingroup\$ Since you only deal with printable characters, p!=' ' is also equivalent to p>' '. \$\endgroup\$ Mar 8, 2018 at 18:06
  • 1
    \$\begingroup\$ 203 bytes, using a generator. \$\endgroup\$ Mar 8, 2018 at 18:22

Python 3, 182 bytes

from itertools import*
def f(l):r=cycle('ROPE');return zip_longest(*(''.join(c+''.join(islice(r,max(ord(n)+~ord(c),0)))for c,n in zip(z,z[1:]+(' ',)))for z in zip(*l)),fillvalue=' ')

Try it online!

The function takes its input as a list (or an iterable) of strings and also returns a generator for a sequences of strings, which is almost as good as a list.


…for better readability of the nested generators.

def f(l):
    r = cycle('ROPE')
    return zip_longest(
                c + ''.join(islice(r, max(ord(n) - ord(c) - 1, 0)))
                for c, n in zip(z, z[1:] + (' ',)))
            for z in zip(*l)),
        fillvalue=' ')


  1. The function uses zip to transpose the incoming list of lines into a generator of columns.

  2. The innermost generator looks at pairs of adjacent characters and…

  3. …slices the required amount of continuous ROPE out of an (infinite) cycle generator.

  4. After copious amounts of string joining from generators the function re-transposes the list of columns back to a generator or lines and fills missing entries with zip_longest.


Stax, 25 bytes


Run and debug online!

Input and output are given as space separated lists. Input is the list of rows as required, output is the list of columns as permitted.


Uses the unpacked version to explain.

M                                 Transpose
 "ROPE"                           The string "ROPE"
       s{                   mJ    Map each column (in the original input) with block, and output with space as the separator
         2B                       All contiguous pairs of current column
           {            m         Map each pair with block
            Ev|r%                     Pair [j,k] to length of range [j..k-2]
                 b:m                  Repeat current repeating string to given length
                    ~                 Last line gives the result the pair should map to, now store it on the input stack
                     |(               Rotate current repeating string `p` times, where `p` is the length of the range [j..k-1]
                       ,              Fetch back the result
                         _s\      Zip with current column, filling missing element with empty string

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.