Golf a string twister
Pyth, 11
jC.>R~hZC.z
Try it here
jC.>R~hZC.z ## implicit: .z = list of input split by lines
C.z ## transpose .z to get columns
.>R~hZ ## shift each column by it's index
## equivalent to .e.>bk
jC ## transpose back and join by newlines
APL (Dyalog), 7 bytes
⊖⊖⊖⍨⍬⍋⍉
Requires ⎕io←0
Try it online!
⍬⍋⍉
gets the range from 0 to the number of columns
⊖
reverses vertically
⊖⊖⍨⍬⍋⍉
rotate (vertically) the (vertically) reversed input by 0,1..
⊖
reverse that, and return it.
Retina, 111 101 92 87 bytes
Byte count assumes ISO 8859-1 encoding.
(?<=((.))*)(?=(?<1>.*¶)*.*(?<=(?=(?<-2>.)*(.))(?<-1>.+¶)*.*(.(?<=^(?<-1>¶?.+)*))*)).
$3
Woo, solved it in a single regex substitution. :) (Chances are, there's a shorter solution by using several, but where's the fun in that...)
Try it online!
Explanation
This requires some basic knowledge of balancing groups. In short, .NET's regex flavour allows you to capture multiple times with a single group, pushing all captures onto a stack. That stack can also be popped from, which allows us to use it for counting things inside the regex.
(?<=((.))*)
This pushes one capture onto both groups 1
and 2
for each character in front of the match (in the current line). That is, it counts the horizontal position of the match.
The rest is in a lookahead:
(?=(?<1>.*¶)*.* [...] )
We match each line and also push it onto group 1
, such that group 1
is now the sum of the horizontal and vertical position (where the latter is counted from the bottom). This essentially labels the diagonals of the grid with increasing values starting from the bottom left corner. That .*
then just moves the engine's cursor to the end of the string.
We now switch into a lookbehind, which is matched from right to left in .NET:
(?<= [...] (.(?<=^(?<-1>¶?.+)*))*)
This will repeatedly pop exactly H
captures from group 1
(where H
is the height of the input). The purpose of that is to take the group modulo H
. Afterwards, group 1
contains the row (counted from the bottom) from which to pick the new character in the current column.
(?=(?<-2>.)*(.))(?<-1>.+¶)*.*
Another lookbehind, again starting from the right. (?<-1>.+¶)*.+
now uses group 1
to find the row from which to pick the new character and then the lookahead finds the correct column using group 2
.
The desired character is captured into group 3
and written back by the substitution.