# There, I fixed it (with rope)

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

## Challenge:

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).

### Example:

Input:

abc
bcd
ddd
eex
gfz
hka
imh


Output:

abc
bcd
Rdd
deE
efR
OPO
gEP
hRE
iOR
kO
PP
mE
R
O
P
E
R
O
P
E
R
O
x
P
z
a
E
R
O
P
E
R
h


Why?

• 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.

## 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:
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]]

• Can I fix it with hope instead? Hope is stronger than rope. (This is a poor attempt at humor, not a real question) – Magic Octopus Urn Mar 8 '18 at 14:47
• @KevinCruijssen did you mean this is easier of the TAPE is easier?? – Dat Mar 8 '18 at 15:24
• @MagicOctopusUrn Nope, rope is our only hope. – Steadybox Mar 8 '18 at 15:53
• Can I ouput and array of columns?? – Dat Mar 8 '18 at 15:56
• @Dat The tape challenge is a lot easier (imho). And yes, you can output an array of column. – Kevin Cruijssen Mar 8 '18 at 15:59

# Jelly, 21 bytes

ZµOI’R“¡nⱮ»ṁż@"µF€z⁶Y


Try it online!

# Explanation

ZµOI’R“¡nⱮ»ṁż@"µF€z⁶Y  Main Link
Z                      Transpose the input so the columns are now rows
O                    [Vectorizing] Convert each letter to its character code
I                   [Vectorizing] Get the differences (gap size)
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)
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

# 05AB1E, 3837 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.

'ÙºUζεDÇ¥<)ζεFX¬sÀU}J]Jζ


Try it online!

Explanation

'Ùº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

• @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. – Emigna Mar 8 '18 at 12:28
• 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? – Magic Octopus Urn Mar 8 '18 at 14:12
• @MagicOctopusUrn: I think I have 32 using your suggestion above. Could still be golfable as well. – Emigna Mar 8 '18 at 14:28
• Does 05AB1E have a: pop a,b,c | push c[b..a] type dealio? – Magic Octopus Urn Mar 8 '18 at 14:44
• @MagicOctopusUrn: Nope. I have been thinking it needs one though. – Emigna Mar 8 '18 at 14:52

# Python 2, 197 194 bytes

def f(s):
r='ROPE'*len(s)*9;x=[]
for i in zip(*s):
x+='',
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.

## Explanation

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).

• To my mind your columnwise I/O format already solves so much of the problem that it becomes a loophole – Ton Hospel Mar 11 '18 at 23:17
• @TonHospel I also hesitated at first, but OP specifically confirmed this is OK in comments to the challenge – Kirill L. Mar 12 '18 at 8:06
• Ah, not what I would have decided, but that's OK then. – Ton Hospel Mar 12 '18 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
x+=o,
for i in x:yield i.ljust(len(max(x,key=len)))


Try it online!

• ord(t)-ord(p)-1 can be ord(t)+~ord(p) to save a byte again. ;) Here is the relevant tip. – Kevin Cruijssen Mar 8 '18 at 17:39
• +=[o] -> +=o,. – Jonathan Frech Mar 8 '18 at 17:49
• @Dat Are you sure? – Jonathan Frech Mar 8 '18 at 18:03
• Since you only deal with printable characters, p!=' ' is also equivalent to p>' '. – Jonathan Frech Mar 8 '18 at 18:06
• 203 bytes, using a generator. – Jonathan Frech Mar 8 '18 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.

## Ungolfed

…for better readability of the nested generators.

def f(l):
r = cycle('ROPE')
return zip_longest(
*(
''.join(
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=' ')


## Explanation

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

ÅiV╘ε╢+gA┘♦W[≈{Co?-φvM«'


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.

## Explanation

Uses the unpacked version to explain.

M"ROPE"s{2B{Ev|r%b:m~|(,m_s\mJ
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
`