This question already has an answer here:

Sometimes when you're lying in bed and reading a message, your phone screen will pop into landscape mode right in the middle of a sentence. Only being able to read left to right, you find yourself incapacitated, unable to process the text in front of you.

To ensure that this won't happen again, you decide to make every message readable from any angle, whether your phone screen is rotated or mirrored. To make this happen, each message is printed as a square, with each side of the square containing the message, either in the original order or in reverse.

  • For backwards compatibility, the top side of the square should be the original message.

  • To make each message square as compact as possible, the first and last character of the message should be a part of two sides of the square. This means that the top side reads normally, the bottom side is in reverse, the left side reads top-bottom, and the right side reads bottom-top.

Input

A single string, with 2 or more characters. You should not assume that the string only contains alphanumerical characters or similar.

Output

The Squarification™ of the string. It is permissible to leave some whitespace at the end of each line, and a single newline at the end of the output.

Examples

Input: 'ab'
ab
ba

Input: 'abc'

abc
b b
cba

Input: 'Hello, world!'
Hello, world!
e           d
l           l
l           r
o           o
,           w

w           ,
o           o
r           l
l           l
d           e
!dlrow ,olleH

This challenge looks like A cube of text, but I'm hoping that it's different enough that there will be some clever answers.

As this is code-golf, get ready to trim some bytes!

marked as duplicate by Mr. Xcoder code-golf Oct 19 at 22:08

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Can the horizontal lines contain spaces between letters, as long as they align with margins? Example: the first line of output for abc would be a b c. Alternatively, can we output a list of lines? Nice challenge, btw – Mr. Xcoder Oct 8 at 6:30
  • @Mr.Xcoder You may not have spaces in the middle of a line, so abc is always abc. EDIT: outputting a list of lines is allowed, just make sure that you have the joining in the footer so that answers can be verified easily. – maxb Oct 8 at 6:52
  • Can we return a list of lines? – Jo King Oct 8 at 6:56
  • @JoKing Yes, a list of lines is allowed. – maxb Oct 8 at 8:02
  • 1
    "To ensure that this won't happen again, you decide to make every message readable from any angle, whether your phone screen is rotated or mirrored." - Or you could just, you know, enable the orientation lock for your phone... – Arnav Borborah Oct 8 at 11:13

37 Answers 37

Charcoal, 4 bytes

S‖O^

Try it online! Link is to verbose version of code. Explanation:

S       Input the string and implicitly print it
 ‖      Reflect...
  O     ... overlapping the first and last character...
   ^    ... in the ↙↘ directions (^ is shorthand for ↙↘).
  • I'm beyond impressed, nicely done! – maxb Oct 8 at 8:04
  • 1
    This challenge is a perfect fit for charcoal :) – Quintec Oct 8 at 11:36

05AB1E, 12 11 bytes

Saved 1 byte thanks to Kevin Cruijssen

g4иsûûŽ9¦SΛ

Try it online!

Explanation

g            # length of input
 4и          # quadruplicate in a list
             # these are the string lengths we'll print
   s         # push input
    ûû       # palendromize twice
             # this is the string we'll print
      Ž9¦S   # push [2,4,6,0]
             # these are the directions we'll print
          Λ  # paint on the canvas
  • This is just bizarre, very impressive! – maxb Oct 8 at 6:54
  • @maxb: Will be interesting to see if Charcoal can do even shorter :) – Emigna Oct 8 at 6:56
  • Wouldn't Canvas also be suitable for something like this? I haven't coded anything in it myself, but from the other answers I've seen in Canvas it seems to be perfect for printing stuff – maxb Oct 8 at 6:58
  • @maxb: It should be yes. I think this kind of challenge is pretty much what it was made for. – Emigna Oct 8 at 7:25
  • It is. In fact, I'm surprised that this question isn't a duplicate... – Neil Oct 8 at 8:12

Python 2, 80 76 71 70 69 bytes

lambda s:[s]+map((' '*len(s[2:])).join,zip(s,s[:0:-1]))[1:]+[s[::-1]]

Try it online!

Python 3, 70 bytes

lambda s:[s,*map((' '*len(s[2:])).join,zip(s[1:],s[-2:0:-1])),s[::-1]]

Try it online!

Canvas, 6 bytes

⤢n:±⇵n

Try it here!

Explanation:

⤢       transpose the input
 n      and overlap that over the input
  :     duplicate that
   ±⇵   reverse it vertically & horizontally
     n  and overlap over the old version

Python 3, 78 76 Bytes

-2 bytes thanks to maxb!

lambda x:[x]+[x[i]+" "*(len(x)-2)+x[~i]for i in range(1,len(x)-1)]+[x[::-1]]

Try it Online!

  • 2
    Outputting a list of lines is allowed! Also, -i-1 can be written as ~i to save two bytes. – maxb Oct 8 at 7:00

MATL, 8 bytes

YTO6Lt&(

Try it online!

Explanation

Consider input 'abcd' as an example. Stack is shown bottom to top.

YT     % Implicit input: string. Create Toeplitz matrix of chars
       % STACK: ['abcd';
                 'babc';
                 'cbab';
                 'dcba']
O      % Push 0
       % STACK: ['abcd';
                 'babc';
                 'cbab';
                 'dcba']
                 0
6L     % Push [2, -1+1j]. Used as an index, this means 2:end
       % STACK: ['abcd';
                 'babc';
                 'cbab';
                 'dcba']
                 0,
                [2, -1+1j]
t      % Duplicate
       % STACK: ['abcd';
                 'babc';
                 'cbab';
                 'dcba']
                 0,
                [2, -1+1j],
                [2, -1+1j]
&(     % Write 0 into the internal entries of the char matrix.
       % STACK: ['abcd';
                 'b  c';
                 'c  b';
                 'dcba']
       % Implicitly display. Char 0 is shown as a space

05AB1E, 14 bytes

¦¨s¨š.BsRøJIRª

Try it online!

Outputs as a list of lines, but the TIO link uses the old version which printed instead – Try an alternative online!. Thought I'd be nice to show how awesome the canvas is by comparing that approach to others that don't use it. See Emigna's answer for a canvas version, then compare it to mine :)

How?

¦¨s¨š.BsRøJ»,R=    Full program. Accepts a string from STDIN. | Example: "abcd"
¦¨                 Tail and pop.                              | STACK: ["bc"]
  s¨               Swap and pop.                              | STACK: ["bc", "abc"]
    š              Prepend a to b as a list.                  | STACK: [["abc", "b", "c"]]
     .B            Squarify.                                  | STACK: [["abc", "b  ", "c  "]]
       sRøJ        Interleave with the reversed input.        | STACK: [["abcd", "b  c", "c  d"]].
           »,      Join by newlines, pop and print.           | STACK: [] (the above is removed after being printed)
             R=    Print the reversed input (taken implicitly due to the empty stack).

The only thing which is different in the 14-byter is that the reversed input is appended to the list rather than printed.

  • 1
    Not too far off Canvas. Nice! – Emigna Oct 8 at 7:29
  • What's the difference between = and ,? I always (falsely) assumed = prints the last item of a list or something like that, but apparently it just prints the top of the stack with trailing newline, just like , does.. Is there a difference, or is it a duplicated 1-byte command we could use for something else? – Kevin Cruijssen Oct 8 at 10:18
  • @Kevin , pops, = doesn't. I have used them both while golfing, to be honest, so I guess each has its own purpose. :-) – Mr. Xcoder Oct 8 at 10:38
  • @Mr.Xcoder Ah ok. Personally I haven't used = yet, but I now understand the difference, thanks. :) – Kevin Cruijssen Oct 8 at 10:43

Japt -R, 22 15 bytes

U+ÕÅ+UÔÅ Õ·hJUw

Try it online!

Pyth, 16 15 bytes

LXXb0Qt0_Qy.tym

Try it online here, or verify all the test cases at once here (test suite joins output on newlines for easier verification, as per OP request).

LXXb0Qt0_Qy.tymdQ   Implicit: Q=eval(input())
                    Trailing d,Q inferred
L                   Define a function, y(b), as:
  Xb                  Replace in b...
    0                 ... at position 0...
     Q                ... the input string
 X                    Replace in the above...
      t0              ... at position -1 (decrement 0)
        _Q            ... the reversed input string
              mdQ   Split the input string into array of characters
                      (The exact contents of the array don't matter, as long as the array
                       has the same length as the input string and the elements are
                       of length < 2)
             y      Apply the function y (defined above) to the array
                      (For Q="abc", yields ["abc", "b", "cba"]
           .t       Transpose, padding with spaces
                      (For Q="abc", yields ["abc", "b b", "c a"]
          y         Apply y to the above

Edit: OP clarified that a list of lines is acceptable as output, so removed j to join on newlines - previous version LXXb0Qt0_Qjy.tym

Perl 6, 55 51 bytes

{$_,|.comb[1..*-2].&{(@_ X~' 'x@_)Z~[R,] @_},.flip}

Try it online!

Returns a list of lines.

Explanation:

{                                                 }  # Anonymous code block
 $_,    # The given string as the first line
     .comb[1..*-2]   # The string as a list of chars without the first or last char
                  .&{                      }  # Passed to a function
                     (@_ X~' 'x@_)  # Each character padded with space
                                  Z~[R,] @_   # And zipped with the reverse
    |   # Flattened
                                            ,.flip  # And the reverse of the string

JavaScript (Node.js), 93 91 87 80 78 77 76 74 bytes

x=>[...x].map(c=>(w+=z=x[--j])[1]?j?c.padEnd(l-1)+z:w:x,w="",l=j=x.length)

Try it online!

Returns list of lines.

Explanation

x =>                     // Main function
 [...x].map(c =>         // For each character in the input:
  (w += z = x[--j])[1]   //  Check whether this is not the first row (by producing w, the
                         //  reverse of x, character by character, and check if len(w) > 1)
  ?                      //  If so:
   j                     //   Check if this is not the last row
   ? c.padEnd(l - 1) + z //   If so: return the needed row
   : w                   //   If not (i.e. last row): return w, the reverse of x
  : x,                   //  If not (i.e. first row): return x
  w = "",                // Stores the reverse of w
  l = j = x.length       // A variable that stores the length of the string, and a counter
 )                       // Golfing from 78 onwards is tough work.

Haskell, 80 76 72 71 bytes

  • Saved four eight nine bytes thanks to Laikoni.
f s=s:m[c:m(' '<$s)++[d]|(c,d)<-zip s$r s]++[r s];m=init.tail;r=reverse

Try it online!

  • 1
    Welcome to golfing in Haskell :) zip(m s)$m$r s can be zip<*>r$m s, though it's still 73 bytes.. – BMO Oct 9 at 20:12
  • (' '<$m s) can be m(' '<$s). – Laikoni Oct 10 at 5:07
  • 71 byte alternative: Try it online! – Laikoni Oct 10 at 5:15
  • Also regarding your footer: sequence.map is mapM and intercalate"\n" is unlines. – Laikoni Oct 10 at 5:17

Z80Golf, 48 bytes

00000000: 1525 13cd 0380 3806 ff4d 2377 18f5 3e0a  .%....8..M#w..>.
00000010: ff7b b928 1113 1aff 4105 2805 3e20 ff18  .{.(....A.(.> ..
00000020: f82b 7eff 18e8 131a b720 0176 ff1b 18f7  .+~...... .v....

Try it online!

  dec d
  dec h
  inc de
get:
  call $8003
  jr c, got
  rst 38h
  ld c, l
  inc hl
  ld (hl), a
  jr get

got:
  ld a, '\n'
  rst 38h
  ld a, e
  cp c
  jr z, final
  inc de
  ld a, (de)
  rst 38h
  ld b, c
spaces:
  dec b
  jr z, doneb
  ld a, ' '
  rst 38h
  jr spaces
doneb:
  dec hl
  ld a, (hl)
  rst 38h
  jr got

final:
  inc de
reverse:
  ld a, (de)
  or a
  jr nz, cont
  halt
cont:
  rst 38h
  dec de
  jr reverse

Java 11, 143 142 141 140 bytes

s->{for(int l=s.length(),i=l;i>0;)System.out.println(i--<l?i<1?new StringBuffer(s).reverse():s.charAt(l+~i)+" ".repeat(l-2)+s.charAt(i):s);}

-1 byte thanks to @OlivierGrégoire.

Try it online.

Explanation:

s->{                                // Method with String parameter and no return-type
  for(int l=s.length(),             //  Length of the input-String
      i=l;i>0;)                     //  Loop `i` in the range (length,0]
    System.out.println(             //   Print with trailing newline:
     i--<l?                         //    If it's NOT the first iteration:
                                    //    (and decrease `i` by 1 at the same time)
      i<1?                           //    If it's the last iteration:
       new StringBuffer(s).reverse() //     Print the input reversed
      :                              //    Else:
       s.charAt(l+~i)                //     Print the `l-i-1`'th character,
       +" ".repeat(l-2)              //     appended with length-2 amount of spaces,
       +s.charAt(i):                 //     appended with the `i`'th character
     :                               //   Else (it is the first iteration):
      s);}                           //    Print the input as is
  • 1
    141 bytes while moving everything to get that l+~i which saves the byte. – Olivier Grégoire Oct 8 at 11:47
  • @OlivierGrégoire Thanks. Hadn't thought about reversing the loop. And 1 more byte could be saved with your approach by changing the if-else order a bit (by using i--<l instead of i--==l). – Kevin Cruijssen Oct 8 at 12:09

Powershell, 93 bytes

param($s)$s
if(($m=$s.Length-2)-gt0){1..$m|%{$s[$_]+' '*$m+$s[$m-$_+1]}}
-join($s[($m+2)..0])

Test script:

$f = {

param($s)$s
if(($m=$s.Length-2)-gt0){1..$m|%{$s[$_]+' '*$m+$s[$m-$_+1]}}
-join($s[($m+2)..0])

}

&$f ab
&$f abc
&$f Hello...
&$f 'Hello, world!'

Output:

ab
ba
abc
b b
cba
Hello...
e      .
l      .
l      o
o      l
.      l
.      e
...olleH
Hello, world!
e           d
l           l
l           r
o           o
,           w

w           ,
o           o
r           l
l           l
d           e
!dlrow ,olleH

Red, 145 127 bytes

func[s][print a: s b: tail s repeat n l:(length? s)- 2[print rejoin[pad first a:
next a l + 1 first b: back b]]print reverse s]

Try it online!

Ruby, 78 bytes

->s{[s.b,*s.chars.zip(s.reverse!.chars).map{|a|"%s%#{s.size-1}s"%a}[1..-2],s]}

Try it online!

  • Nice solution. -1 byte: *s.chars.zip ->s.chars.zip – Idva Oct 9 at 10:00
  • I want my function to return a flattened list, so I'm keeping the splat. – G B Oct 9 at 10:04
  • Do you mind explaining why you would want that? It doesn't seem to affect the output – Idva Oct 9 at 10:10
  • The output of the test is the same because puts flattens the list, but the result of the function is a nested array, which is not what I want to return. – G B Oct 9 at 10:31
  • Ok, I see. Thanks for the explination. – Idva Oct 9 at 12:05

APL(NARS), 59 chars, 118 bytes

{y←⊖⍵⋄0=z←¯2+⍴⍵:⊃,¨⍵ y⋄⊃(⊂⍵),({(∊1(z⍴0)1)\⍵}¨¯1↓1↓⍵,¨y),⊂y}

test

  f←{y←⊖⍵⋄0=z←¯2+⍴⍵:⊃,¨⍵ y⋄⊃(⊂⍵),({(∊1(z⍴0)1)\⍵}¨¯1↓1↓⍵,¨y),⊂y} 
  f '12'
12
21
  f '123'
123
2 2
321
  f '1234'
1234
2  3
3  2
4321
  f 'Hello World!'
Hello World!
e          d
l          l
l          r
o          o
           W
W           
o          o
r          l
l          l
d          e
!dlroW olleH
  f 'Hello, World!'
Hello, World!
e           d
l           l
l           r
o           o
,           W

W           ,
o           o
r           l
l           l
d           e
!dlroW ,olleH

JavaScript, 92 85 bytes

Early morning golf on the bus. Not happy with it; there's definitely a shorter way :\

s=>s+`
`+(g=r=>--x?s[l-x].padEnd(l)+s[--y]+`
`+g(r+s[y]):r+s[0])(s[l=x=y=s.length-1])

Try it online

MathGolf, 20 19 15 bytes

p╡╞▒x_xh *+m+nx

Try it online!

Edited to an improved version of maxb's original 22 byte solution. Zip operator is sadly lacking though the map operator has a partial implementation.

Explanation:

p                 Print the original string ["abcd"]
 ╡╞               Remove from the start and end of the string  ["bc"]
   ▒              Convert to a list of chars  [["b","c"]]
    x_x           Reverse, dupe and reverse back again [["c","b"],["b","c"]]
       h          Get length of array without popping  [["c","b"],["b","c"],2]
         *        Create a string with that many spaces [["c","b"],["b","c"],"  "]
          +       Map adding it to every character [["c","b"],["b  ","c  "]]
           m+     Zip add each character of the reversed string [["b  c","c  b"]]
             n    Join with newlines and print
              x   Reverse the original string and implicitly output
  • You actually beat my MathGolf script that gave inspiration to this challenge! You're right, the zip operator is needed, and mapping for lists is quite rudimental. I'll see how I want that to work. – maxb Oct 8 at 8:07

Japt, 28 bytes

Takes the input as an array of characters

íUz2)£Y©Y<UÊÉ?XqSpUÊ-2:UqÃow

íUz2)£Y©Y<UÊÉ?XqSpUÊ-2:UqÃow    Full program. Implicity input U
                                ["a", "b", "c"]
 Uz2)                           Duplicate and rotate 180°
                                ["a", "b", "c"], ["c", "b", "a"]
í                               Pair each item at the same index
                                [["a","c"],["b","b"], ["c","a"]]
     £                          Map
      Y©Y<                      If index is positive and less than
          UÊÉ?                  Length - 1
              Xq                Join with...
                SpUÊ-2          Space repeated (U length - 2) times
                                [["a","c"],"b b", ["c","a"]]
                      :Uq       Else return joined input
                                ["abc","b b", "abc"]
                         Ãow    Map last item and reverse
                                ["abc","b b", "cba"]
                                Implicity output array joined with new lines
                                "abc
                                 b b
                                 cba"

Try it online!

Jelly, 20 bytes

W;ḊW€$O‘z0ṚUoƊo33’ỌY

Try it online!

Assuming that unprintables can also be in the input.

Stax, 10 bytes

▄▀τƒ○≡ë'▲.

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

{       start a block to repeat
  Mr    rotate matrix counter-clockwise
  0     actually just a literal 0
  x     retrieve "string" from x register, initially the input string
  rX    reverse, and write it back to register
  &     assign reversed "string" to 0 index of matrix (first row)
}4*     exectue block 4 times
m       output matrix as line-separated rows

Run this one

  • Would í,ñl♠τ¢∞█ be fine for 9, outputting as a list of lines? – Mr. Xcoder Oct 8 at 21:02
  • @Mr.Xcoder: I'm not sure, but if it is, this 8 byte solution would also work. Ç¢å╒Γ8Q# Personally, I don't really like it. For languages that don't have real functions I think the output should be formatted correctly on standard output, so there's nothing left to interpretation about what the internal state of different languages mean. But on the other hand, I'm in favor of smaller programs! – recursive Oct 8 at 22:01

JavaScript (Node.js), 87 bytes

s=>[...s].map((e,i,a,n=s.length)=>i<1?s:i>n-2?a.reverse().join``:e.padEnd(n-1)+a[n+~i])

Question Title is Be there, for the Square but all answers print a Rectangle

So here's the one printing square:

s=>[...s].map((e,i,a,n=s.length)=>i<1?a.join` `:i>n-2?a.reverse().join` `:e.padEnd(2*n-2)+a[n+~i])


Try it online!

  • 2
    s[n+~i] saves 1 byte over n-i-1. – Mr. Xcoder Oct 8 at 7:09

Jelly,  19  18 bytes

-1 thanks to Erik the Outgolfer (managing to use another repeat, , to inline my helper Link)

WẋL¬o1¦³ṚUƊ⁺ZƊ⁺o⁶Y

A full program.

Try it online!

How?

WẋL¬o1¦³ṚUƊ⁺ZƊ⁺o⁶Y - Main Link: list of characters s
W                  - wrap s in a list
  L                - length of s
 ẋ                 - repeat (yielding a length(s) list of copies of s)
   ¬               - logical NOT (makes every element a zero - giving us a square of zeros)
             Ɗ     - last three links as a monad (say F(x)):
          Ɗ        -   last three links as a monad (say G(x)):
      ¦            -     sparse application...
     1             -       ...to indices: [1]
    o  ³           -       ...do: logical OR with the input (s)
                   -              (replaces the first list with the input)
        Ṛ          -     reverse               }
         U         -     upend (reverse each)  } (turn whole thing 180 degrees)
           ⁺       -   repeat previous link (i.e. G(that result))
            Z      -   transpose
              ⁺    - repeat previous link (i.e. F(that result))
               o⁶  - logical OR with a space character (replace all remaining zeros with spaces)
                 Y - join with newlines
                   - implicitly print

My 19 byters...

;⁶ɓJ»þ`n\«\aƊUṚ»ƊịY

Try this one, which works by building a table of indices filled with zeros and then indexing into the input with an extra space (in order to relace the 0s with spaces)

...and the one Erik improved to 18 for me:

o1¦³ṚU
WẋL¬ÇÇZƊ⁺o⁶Y

Try this one.

R, 113 102 bytes

function(s,N=nchar(s),m=matrix(" ",N,N)){m[1,]=m[,1]=el(strsplit(s,""))
write(pmax(m,rev(m)),1,N,,"")}

Try it online!

Thanks to JayCe for saving 6 bytes!

Writes the string to the first row and column of the array. So long as the string contains only characters with ASCII codepoints greater or equal than 32 (space), which seems allowable by "alphanumeric characters", then the parallel maximum of the matrix and its reverse yields the appropriate matrix, which is then printed out by write.

  • 111 bytes using intToUtf8 and cat – JayCe Oct 10 at 1:43
  • actually your solution can be made 107 bytes easily :) – JayCe Oct 10 at 1:44
  • @JayCe oh duh! I mostly just played with the indices until they were right and didn't even think to golf them! I even managed to find a few more :-) – Giuseppe Oct 10 at 15:41
  • pmax is a really good trick. I've been trying to use a vector like this but I am not managing to save bytes. – JayCe Oct 10 at 16:26

C (gcc), 100 103 102 bytes

  • Saved a byte thanks to ceilingcat; golfing an alternative solution.
o,O;v(char*_){for(O=puts(_,o=0)-2;O-++o;)printf("%c%*c\n",_[o],O,_[O-o]);for(o=O;~o;putchar(_[o--]));}

Try it online!

Java (JDK), 109 bytes

s->{int l=s.length,i=0;var r=new char[l][l--];for(char c:s)r[i][0]=r[0][i]=r[l-i][l]=r[l][l-i++]=c;return r;}

Try it online!

Returning a 2D array containing the characters to print. The inner of the array is filled with \0 instead of spaces because no rules said spaces have to be used.

PHP, 207 Bytes

$k=str_pad('',($L=mb_strlen($s=$argv[1]))-2,' ');$p=[];for($i=1;$i<=$L;$i++){$p[]=($j=mb_substr($s,$L-$i,1));if($i==1)$b=$s;elseif($i==$L)$b=implode('',$p);else$b=mb_substr($s,$i-1,1).$k.$j;echo$b.PHP_EOL;}

Not quite a creative entry, but it supports UTF-8 at least...

Retina 0.8.2, 78 bytes

(.+).
$1¶$&
O$^r`.\G

+`^(.*)(.)(¶(.*).)
$1¶$2$4$3
^¶

T`p` `(?<=.¶.).*(?=.¶.)

Try it online! Handliy beating my previous attempt. Explanation:

(.+).
$1¶$&

Duplicate all but one character.

O$^r`.\G

Reverse the original.

+`^(.*)(.)(¶(.*).)
$1¶$2$4$3

Move characters from the duplicate to the original one at a time, creating a filled square.

Delete the blank line now that the duplicate has been processed.

T`p` `(?<=.¶.).*(?=.¶.)

Change all inner characters to spaces.

Not the answer you're looking for? Browse other questions tagged or ask your own question.