Given a square string, produce all the output for the string at every stage of unfurling.
The string must unfurl in a clockwise direction one quarter turn at a time.
Examples
Input:
A
Output:
A
Note: I'll also accept the input duplicated for this particular test case only if this helps reduce your byte count.
Input:
DC
AB
Output:
DC
AB
D
ABC
ABCD
Input:
GFE
HID
ABC
Output:
GFE
HID
ABC
HG
IF
ABCDE
IH
ABCDEFG
I
ABCDEFGH
ABCDEFGHI
Input:
JIHG
KPOF
LMNE
ABCD
Output:
JIHG
KPOF
LMNE
ABCD
LKJ
MPI
NOH
ABCDEFG
NML
OPK
ABCDEFGHIJ
ON
PM
ABCDEFGHIJKL
PO
ABCDEFGHIJKLMN
P
ABCDEFGHIJKLMNO
ABCDEFGHIJKLMNOP
Rules
This is code-golf so the shortest code in bytes wins.
- Any reasonable format can be used for I/O assuming it is consistent.
- Spaces must be used to pad the top lines of the output.
- Must be able to handle input of all printable characters (including space:
\x20-\x7e):
!"#$%&'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
- Leading/trailing whitespace is allowed.
- You can assume the string will always be a square.
- All standard loopholes are forbidden.
Inspiration: Write a square program that outputs the number of times it has been "unrolled".
8 Answers 8
SOGL V0.12, (削除) 21 (削除ここまで) (削除) 20 (削除ここまで) (削除) 19 (削除ここまで) (削除) 18 (削除ここまで) 17 bytes
ø;[;ο4Noč▓┼NoTJι;jI
Try it Here! (→ added because this expects input on the stack)
Explanation:
ø;[;ο4Noč▓┼NoTJι;jI
ø; push an empty string below the input stack with the input GFE,HID,ABC
[ while [ToS (the array) isn't empty] do ["", [["G","F","E"],["H","I","D"],["A","B","C"]]]
stack at the second time looping
; duplicate 2nd from top [[[H,G], [I,F], [D,E]], "ABC"]
ο wrap it in an array [[[H,G], [I,F], [D,E]], ["ABC"]]
4 duplicate 2nd from top [[[H,G], [I,F], [D,E]], ["ABC"], [[H,G], [I,F], [D,E]]]
No reverse vertically [[[H,G], [I,F], [D,E]], ["ABC"], [[D,E], [I,F], [H,G]]]
č▓ join the inner arrays (┼ fails otherwise) [[[H,G], [I,F], [D,E]], ["ABC"], ["DE", "IF", "HG"]]
┼ add the 2 parts together [[[H,G], [I,F], [D,E]], ["ABCDE", " IF", " HG"]]
No reverse vertically again [[[H,G], [I,F], [D,E]], [" HG", " IF", "ABCDE"]]
T print that without popping [[[H,G], [I,F], [D,E]], [" HG", " IF", "ABCDE"]]
J take the last line off [[[H,G], [I,F], [D,E]], [" HG", " IF"], "ABCDE"]
ι remove the rest of the array [[[H,G], [I,F], [D,E]], "ABCDE"]
;j remove the last line of the original array ["ABCDE", [[H,G], [I,F]]]
I rotate it clockwise ["ABCDE", [[I,H], [F,G]]]
Python 2, (削除) 209 207 205 203 202 201 200 (削除ここまで) 196 bytes
-4 bytes thanks to @Quelklef!
s=input();l=len;k=''.join;exec"print s;s=[x for x in[' '*l(s[0])+k(x[:-1]for x in s[-2::-1])[t::l(s[0])-1]for t in range(l(s[0]))][:-1]+[s[-1]+k(x[-1]for x in s)[-2::-1]]if x.strip()];"*(2*l(s)-1)
Python 2, (削除) 219 217 215 213 212 211 (削除ここまで) 207 bytes
s=input();l=len;k=''.join;exec"print'\\n'.join(s);s=[x for x in[' '*l(s[0])+k(x[:-1]for x in s[-2::-1])[t::l(s[0])-1]for t in range(l(s[0]))][:-1]+[s[-1]+k(x[-1]for x in s)[-2::-1]]if x.strip()];"*(2*l(s)-1)
The first one outputs as a list of Strings, the second one outputs as ASCII-art.
-
\$\begingroup\$ I think
[::-1][1:]can be[-2::-1], like in Lynn's answer. \$\endgroup\$Quelklef– Quelklef2017年08月23日 21:38:44 +00:00Commented Aug 23, 2017 at 21:38 -
\$\begingroup\$ @Quelklef Thanks a lot! \$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年08月23日 21:40:38 +00:00Commented Aug 23, 2017 at 21:40
Charcoal, (削除) 42 (削除ここまで) 35 bytes
AEθSθW⊟θ«⪫θ¶AEι⮌⪫Eθ§μλωθ⊞υι↙←⮌⪫υωD⎚
Try it online! Link is to verbose version of code. Edit: Saved 7 bytes mostly by switching from character arrays to strings. Explanation:
AEθSθ
Read the input square as an array of strings into the variable q.
W⊟θ«
While the last string in the array is not empty, remove it.
⪫θ¶
Print the rest of the array.
AEι⮌⪫Eθ§μλωθ
Rotate the rest of the array by looping through each character of the last string and joining the lth character of every remaining string in the reversed array.
⊞υι↙←⮌⪫υω
Append the previously removed last string to u, which holds the unfurled value, and print it.
D⎚
Output the result and then clear the canvas ready for the next iteration.
Note that this version outputs the final unfurl on a separate line, if this is undesirable then for 38 bytes:
AEθSθW⊟θ«⊞υι←E+⟦⪫υω⟧⮌θ⮌κAEι⮌⪫Eθ§μλωθD⎚
Try it online! Link is to verbose version of code. Explanation: ←E+⟦⪫υω⟧⮌θ⮌κ reverses the current array, prepends the unfurled line, then reverses the characters in each line, then prints everything upside-down, thus producing the desired result.
-
\$\begingroup\$ I tried doing it a more Charcoal-y way but I couldn't work out where the
RotateandTrimcommands leave the cursor... \$\endgroup\$Neil– Neil2017年08月21日 15:50:05 +00:00Commented Aug 21, 2017 at 15:50
Haskell, (削除) 127 (削除ここまで) 120 bytes
e=[]:e
i#[x]=[]
i#s|t<-foldl(flip$zipWith(:))e$init s,j<-i++last s=(map((j>>" ")++)(init t)++[j++last t]):j#t
f s=s:""#s
Input is a list of lines, e.g. ["DC","AB"] for the second test case, output is a list of lists of lines: [["DC","AB"],[" D","ABC"],["ABCD"]]. Use mapM (putStrLn . unlines) to pretty-print the result.
Edit: Saved 7 bytes by noticing that the shorter transpose I found some while a go comes in handy because it can be modified to reverse each transposed directly.
05AB1E, 18 bytes
[Dí.Bí»,¤UR¦ζŽ`Xì)
Explanation
[ Ž # while stack is not empty, do:
D # duplicate current list
í # reverse each element
.B # pad with spaces to equal length
í # reverse each element again
», # join with newlines and print
¤U # store the last element in X
R¦ # reverse the list and remove the first element
ζ # zip with spaces as filler
` # split elements separately to stack
Xì # prepend X to the last element
) # join the stack to a list
J, 62 bytes
|."1@([:(#~[:-.[:*/"1' '=])|.@{:(}:@],{:@],[)|:@}:)^:(1<#)^:a:
I'm sure this can be golfed a lot. This prints extra whitespace, but only because of the way that J formats the arrays contained within the outputted array to have the same shape.
I think once I go in and comment out exactly what I'm doing, I might get a better idea of how to golf this (having done that now, I don't really know...). For purposes of golfing, it's worth noting that
- I have to special case 1 row inputs (the while part of the loop)
- I have to eliminate all lines consisting solely of whitespace (surely there must either be a builtin for this or a better way to do it), which is the filter near the end
- There are a lot of caps, identity functions, and atops
Explanation
In ungolfing this, I'll be splitting the main function in three.
unfurl_reversed =. |.@{: (}:@] , {:@] , [) |:@}:
whitespace_filter =. #~ [: -. [: */"1 ' ' = ]
unfurl =. |."1@(whitespace_filter @: unfurl_reversed) ^: (1 < #) ^: a:
test_case =. 3 3 $ 'GFEHIDABC'
We'll be working with the second test case.
unfurl_reversed
|.@{: (}:@] , {:@] , [) |:@}:
This gives one the string unfurled once, but in reverse. All of this is being done in reverse and in a specific order so that the way J automatically pads strings with spaces to match the shape of the array they're in will give the right spacing.
|:@}: is the transpose of the curtail of the input
|:@}: test_case
GH
FI
ED
|.@{: is the reverse of the tail of the input
|.@{: test_case
CBA
I think you can see what we want to do: we want to append the reverse of the tail to the last part of the transpose of the curtail (that's a mouthful, but basically attach CBA to the end of ED). This will give us one step of unfurling, reversed.
(}:@],{:@],[) does just that.
It appends CBA to ED, then joins that with the rest of the array. Our output therefore is
unfurl_reversed test_case
GH
FI
EDCBA
whitespace_filter
#~ [: -. [: */"1 ' ' = ]
' ' = ] Equate each element to space
*/"1 Product of each row (all true?)
-. Negate
#~ Filter rows that are true
Basically, this tests to see if any row is completely spaces, and removes it if it is. It doesn't do anything for the first iteration of the test case.
This is necessary (at least until I find an alternative) since otherwise we'll eventually be unfurling whitespace into our output string.
unfurl
|."1@(whitespace_filter @: unfurl_reversed) ^: (1 < #) ^: a:
Unfurl basically puts the other functions together and special cases single character inputs.
When the power of verb (^:) is given the empty box (a:), it applies a function on an input until it converges and collects the results in an array.
(1 < #) checks that the rows are always greater than 1 (to special case 1 row inputs).
|."1 reverses each row, so it inverts the results of whitespace_filter @: unfurl.
Python 2, (削除) 143 (削除ここまで) 132 bytes
a=input()
while 1:print'\n'.join(a);b=map(''.join,zip(*map(str.strip,a[-2::-1])));a[-1]+=b.pop();a[:-1]=[len(a[0])*' '+x for x in b]
In each iteration, b is the "head" of the string (first n−1 rows), rotated 90 degrees: if a is [" NML", " OPK", "ABCDEFGHIJ"] then b is ["ON", "PM", "KL"].
To unfurl a string once, we append the final line of b to a[-1] (giving "ABCDEFGHIJKL") and then recompute a[:-1] by adding spaces to the rest of the strings in b.
We terminate by attempting to pop from b when it’s empty.
Python 2, 132 bytes
a=input()
while 1:s=str.strip;print'\n'.join(a);a[:-1]=[len(a[0])*' '+''.join(x)for x in zip(*map(s,a[-2::-1]))];a[-1]+=s(a.pop(-2))
Same idea, written differently. We terminate by attempting to a.pop(-2) when a has only one element.
Perl 5, 155 bytes
$"=,ドル;@a=map[/./g],<>;while(@a){say' 'x(length$s)."@$_"for@a[0..@a-2];say$s.="@{pop@a}";say@b=();for$i(0..$#a){$q=0;$b[$q++][$#a-$i]=$_ for@{$a[$i]}}@a=@b}
Saved a few bytes without really modifying the logic. The flow below is still basically correct.
(削除) # Perl 5, 163 bytes (削除ここまで)
$"=,ドル;@a=map[/./g],<>;while(@a){say' 'x(length$s)."@{$a[$_]}"for 0..@a-2;say$s.="@{pop@a}";say@b=();for$i(0..$#a){$b[$_][$#a-$i]=$a[$i][$_]for 0..$#{$a[$i]}}@a=@b}
How?
$"=,ドル; #set the array output separator to null
@a=map[/./g],<>; # take the input as a 2-D array @a
while(@a){ # repeat while there are still things to unfurl
say' 'x(length$s)."@{$a[$_]}"for 0..@a-2; # output all but last
# line of the remaining
# square
say$s.="@{pop@a}"; # remove bottom row, add it to the unfurled string $s
# and output it
say@b=(); # clear temporary array; output empty array, causing
# a newline to output
# rotate remaining shape 90 degrees:
for$i(0..$#a){$b[$_][$#a-$i]=$a[$i][$_]for 0..$#{$a[$i]}}
@a=@b # replace input with rotated array
}
-
\$\begingroup\$ Nice method, but I'm after the output at each stage of unfurling, could you update to print all steps? Sorry! \$\endgroup\$Dom Hastings– Dom Hastings2017年08月21日 15:23:30 +00:00Commented Aug 21, 2017 at 15:23
-
1\$\begingroup\$ OK, I rewrote it. \$\endgroup\$Xcali– Xcali2017年08月21日 19:05:07 +00:00Commented Aug 21, 2017 at 19:05
-
\$\begingroup\$ Perfect, thanks! Sorry for causing extra bytes though... \$\endgroup\$Dom Hastings– Dom Hastings2017年08月21日 19:09:59 +00:00Commented Aug 21, 2017 at 19:09
["A","A"]for"A", like my program does (instead of["A"])? It seems reasonable to me since they're just the starting and the ending positions, and you only try to unfurl it once. \$\endgroup\$