21
\$\begingroup\$

Last time you made a square of text, but now, can you make a cube of text?

The Challenge

Given a string, output the string in the form of a cube.

You can assume the string will always have 2 chars or more, and will only have printable ascii characters.

How to Make a Text Cube

terrible mspaint skills.png

Test Cases

Input:
Test

Output:
   Test
  e  ss
 s  e e
tseT  T
s  e e
e  ss
Test

Input:
Hello, world!

Output:
            Hello, world!
           e           dd
          l           l l
         l           r  r
        o           o   o
       ,           w    w

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

,           w    w
o           o   o
l           r  r
l           l l
e           dd
Hello, world!

Input:
Hi

Output:
 Hi
iHH
Hi

Reference Implementation in Python

text = raw_input("Enter a string: ")

print " " * (len(text) - 1) + text

spaces = len(text) - 2
_spaces = spaces

for i in range(1, len(text) - 2 + 1):
    print " " * spaces + text[i] + " " * _spaces + text[(i + 1) * -1] + " " * (_spaces - spaces) + text[(i + 1) * -1]
    spaces -= 1

print text[::-1] + " " * _spaces + text[0]

spaces = _spaces - 1

for i in range(1, len(text) - 2 + 1):
    print text[(i + 1) * -1] + " " * _spaces + text[i] + " " * spaces + text[i]
    spaces -= 1

print text

Rules

  • This is , so shortest answer in bytes wins! Tiebreaker is most upvoted.
  • Standard loopholes are disallowed.
  • Trailing newline and trailing spaces are allowed.

Leaderboard

Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

/* Configuration */

var QUESTION_ID = 92410; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 48934; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });  
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];
  
  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    });
    
    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });
    
  });
  
  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;
    
    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    if (/<a/.test(lang)) lang = jQuery(lang).text();
    
    languages[lang] = languages[lang] || {lang: a.language, user: a.user, size: a.size, link: a.link};
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function (a, b) {
    if (a.lang > b.lang) return 1;
    if (a.lang < b.lang) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body { text-align: left !important}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<div id="language-list">
  <h2>Winners by Language</h2>
  <table class="language-list">
    <thead>
      <tr><td>Language</td><td>User</td><td>Score</td></tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>

\$\endgroup\$
7
  • \$\begingroup\$ Are trailing spaces allowed? \$\endgroup\$
    – Neil
    Commented Sep 6, 2016 at 23:36
  • \$\begingroup\$ @Neil Yes. (15 chars) \$\endgroup\$
    – acrolith
    Commented Sep 7, 2016 at 0:02
  • \$\begingroup\$ Just curious, what's with the additional characters in the challenge title? \$\endgroup\$ Commented Sep 7, 2016 at 18:12
  • \$\begingroup\$ @TimmyD "A cube of text" is 14 characters long, the title needs to be at least 15 characters long, so I added a small dot. I think it's this one. \$\endgroup\$
    – acrolith
    Commented Sep 7, 2016 at 18:30
  • \$\begingroup\$ Ah, OK. It shows up as a much larger circle in IE on my computer, hence my question. \$\endgroup\$ Commented Sep 7, 2016 at 18:35

9 Answers 9

4
\$\begingroup\$

Python 2, 228 223 221 203 199 195 189

t=input()
x=" "
l=len(t)-1
q=l-1
f=range(q,0,-1)
print x*l+t
for i in f:print x*i+t[l-i]+x*q+t[i]+x*(q-i)+t[i]
print t[::-1]+x*q+t[0]
for i in f:print t[i]+x*q+t[l-i]+x*(i-1)+t[l-i]
print t

Python 3, 192 188 182

t=input()
x=" "
l=len(t)-1
q=l-1
p=print
f=range(q,0,-1)
p(x*l+t)
for i in f:p(x*i+t[l-i]+x*q+t[i]+x*(q-i)+t[i])
p(t[::-1]+x*q+t[0])
for i in f:p(t[i]+x*q+t[l-i]+x*(i-1)+t[l-i])
p(t)
\$\endgroup\$
5
  • \$\begingroup\$ That's 203 bytes. Also, you can save 4 bytes by replacing raw_input() with input(). \$\endgroup\$
    – acrolith
    Commented Sep 6, 2016 at 23:19
  • \$\begingroup\$ Right you are, thanks! \$\endgroup\$ Commented Sep 6, 2016 at 23:26
  • \$\begingroup\$ x*(q)? You should be able to remove the parens, yes? \$\endgroup\$
    – Value Ink
    Commented Sep 7, 2016 at 0:11
  • \$\begingroup\$ You're right, silly me ;) Fixing it now haha \$\endgroup\$ Commented Sep 7, 2016 at 0:13
  • \$\begingroup\$ x*(i-1) -> x*~-i \$\endgroup\$
    – mbomb007
    Commented Sep 7, 2016 at 20:26
3
\$\begingroup\$

x86 (IA-32) machine code, 126 bytes

Hexdump:

60 8b f9 57 33 c0 f2 ae 5e 2b fe 4f 87 fa 8d 1c
12 8b c3 48 f6 e3 c6 04 07 00 48 c6 04 07 20 75
f9 8b ea 4d 53 8d 04 2a 50 53 8b c5 f6 e3 8d 44
68 01 50 53 2b c2 8b c8 50 4b 53 55 53 03 c5 50
f7 d3 53 50 53 95 f6 e2 6b c0 04 50 43 53 51 6a
01 4a 52 6a 01 50 6a ff 51 b0 0a 6a 0b 8b dc 59
8b 6c cb fc 88 04 2f 03 2c cb 89 6c cb fc 83 f9
0a 75 01 ac e2 ea 4a 79 e0 83 c4 58 61 c3

This is a bit long, so to explain it I'll give C code first:

void doit(const char* s, char out[])
{
    int n = strlen(s);
    int w = 2 * n;
    int h = w - 1;
    int m = n - 1;

    memset(out, ' ', h * w);
    out[h * w] = 0;

    int offset1 = n + m;
    int offset2 = w * m + 2 * m + 1; // 2 * n * n - 1
    int offset3 = offset2 - n; // 2 * n * n - n - 1
    int offset4 = 4 * n * m; // 4 * n * n - 4 * n

    int offsets[] = {
        offset3, -1,
        offset4, 1,
        m, 1,
        offset3, 1 - w,
        offset4, -w,
        offset2 - 1, -w,
        offset2 - 1, w - 1,
        m, w - 1,
        offset3, w,
        offset2, w,
        offset1, w,
    };

    do
    {
        char c = *s++;
        for (int i = 0; i < 11; ++i)
        {
            if (i == 9)
                c = '\n';
            int offset = offsets[i * 2];
            assert(offset > 0 && offset < w * h);
            out[offset] = c;
            offsets[i * 2] += offsets[i * 2 + 1];
        }
    } while (--n);
}

Here n is the length of the input string.

The dimensions of the output area are 2n (width) by 2n-1 (height). First, it fills everything with spaces (and adds a terminating null byte). Then, it travels along 11 straight lines in the output area, and fills them with text:

  • 2 lines are filled with end-of-line bytes (=10)
  • 9 lines are filled with the consecutive bytes of the input string

Each line is represented by two numbers, a start offset and a stride. I stuffed them both into the array offsets, to make access "easy".

The interesting part is filling the array. There is little importance for the order of the entries in the array; I tried to rearrange them to minimize the number of register conflicts. In addition, quadratic formulas have some freedom in choosing the way of calculation; I tried to minimize the number of subtractions (because additions can be implemented by the flexible LEA instruction).

Assembly source:

    pushad;

    ; // Calculate the length of the input string
    mov edi, ecx;
    push edi;
    xor eax, eax;
    repne scasb;
    pop esi; // esi = input string
    sub edi, esi;
    dec edi;

    ; // Calculate the size of the output area
    xchg edi, edx;  // edx = n
                    // edi = output string
    lea ebx, [edx + edx]; // ebx = w
    mov eax, ebx;
    dec eax; // eax = h
    mul bl; // eax = w * h

    ; // Fill the output string with spaces and zero terminate it
    mov byte ptr [edi + eax], 0;
myfill:
    dec eax;
    mov byte ptr [edi + eax], ' ';
    jnz myfill;

    mov ebp, edx;
    dec ebp; // ebp = m

    ; // Fill the array of offsets
    push ebx; // w
    lea eax, [edx + ebp];
    push eax; // offset1
    push ebx; // w
    mov eax, ebp;
    mul bl;
    lea eax, [eax + 2 * ebp + 1];
    push eax; // offset2
    push ebx; // w
    sub eax, edx;
    mov ecx, eax; // ecx = offset3
    push eax; // offset3
    dec ebx;
    push ebx; // w - 1
    push ebp; // m
    push ebx; // w - 1
    add eax, ebp;
    push eax; // offset2 - 1
    not ebx;
    push ebx; // -w
    push eax; // offset2 - 1
    push ebx; // -w
    xchg eax, ebp; // eax = m
    mul dl;
    imul eax, eax, 4;
    push eax; // offset4
    inc ebx;
    push ebx; // 1 - w
    push ecx; // offset3
    push 1;
    dec edx; // edx = n - 1
    push edx;
    push 1;
    push eax;
    push -1;
    push ecx;

    ; // Use the array of offsets to write stuff to output
myout:
    mov al, '\n';
    push 11;
    mov ebx, esp;
    pop ecx;
myloop:
    mov ebp, [ebx + ecx * 8 - 4];
    mov [edi + ebp], al;
    add ebp, [ebx + ecx * 8];
    mov [ebx + ecx * 8 - 4], ebp;
    cmp ecx, 10;
    jne skip_read;
    lodsb;
skip_read:
    loop myloop;
    dec edx;
    jns myout;

    add esp, 11 * 8;

    popad;
    ret;

I used byte multiplications here, limiting the length of the input string to 127. This avoids clobbering the register edx - the product is calculated in ax instead.

A minor glitch: when filling the array, the length of the string gets decreased by 1. So I adjusted the loop exit condition:

    jns myout

It counts down to -1.

\$\endgroup\$
3
\$\begingroup\$

Ruby, 148 144 bytes

+1 byte from the n flag. Shows newlines instead of semicolons for readability (same functionality).

S=" "
X=S*s=$_.size-2
puts X+S+I=$_,(r=1..s).map{|i|c=I[~i];S*(s-i+1)+I[i]+X+c+S*~-i+c},I.reverse+X+I[0],r.map{|i|c=I[i];I[~i]+X+c+S*(s-i)+c},I

Run like so. Input is a line of STDIN, with no trailing newline, so it likely needs to be piped from file.

ruby -ne 'S=" ";X=S*s=$_.size-2;puts X+S+I=$_,(r=1..s).map{|i|c=I[~i];S*(s-i+1)+I[i]+X+c+S*~-i+c},I.reverse+X+I[0],r.map{|i|c=I[i];I[~i]+X+c+S*(s-i)+c},I'
\$\endgroup\$
3
\$\begingroup\$

Vyxal, 13 bytes

L?∞Ṫ»∨¹0²H»ø∧

Try it Online! Indirectly -1 byte thanks to Kevin Cruijssen, I forgot how canvas operator overloading works.

           ø∧ # Draw on the canvas with
L             # Line length: length of input
 ?∞Ṫ          # String: Input, palindromised with last character removed
    »∨¹0²H»   # Directions: digits of 24560125406


    .>2>.
   ⇗   ⇙v
  1   5 4
 ⇗   ⇙  v
.<6<.   .
^   v  ⇙
0   4 5
^   v⇙
.<6<.
\$\endgroup\$
2
\$\begingroup\$

Pyth, 78 bytes

AtBtlQJ_SH
+*dGQVJs[*Nd@Q-GN*dHK@QN*d-HNK;
++_Q*dHhQVJs[@QN*dH@Q-GN*dtN@Q-GN;

With trailing newline. Inspired by Joshua de Haan's Python 3 answer.

Try it online here!

\$\endgroup\$
2
\$\begingroup\$

05AB1E, 35 12 bytes

gIû¨•5ÏlÐθ•Λ

-23 bytes by porting emanresuA's Vyxal answer, so make sure to upvote that answer as well!

Try it online.

Original 35 bytes answer:

g¸ÞI¸Þð13ÅÉǝ•6´XdªÅ~ßмñD>γ•₃в)øvy`Λ

Try it online.

Explanation:

g               # Push the length of the (implicit) input-string
 I              # Push the input-string
  û             # Palindromize it
   ¨            # And then remove the last character
    •5ÏlÐθ•     # Push compressed integer 24560125406
           Λ    # Use the Canvas builtin with those three arguments
                # (which is output immediately as result)
g               # Push the length of the (implicit) input-string
 ¸Þ             # Wrap it into a list, and repeat it infinitely
I               # Push the input-string
 ¸Þ             # Repeat it infinitely as well
   ð            # Push a space character " "
    13ÅÉ        # Push a list of odd integers <= 13: [1,3,5,7,9,11,13]
        ǝ       # Insert spaces at those 0-based indices into the infinite list
•6´XdªÅ~ßмñD>γ• # Push compressed integer 506660546965149280261611581961
  ₃в            # Convert it to base-95 as list:
                #  [1,8,84,80,2,80,5,82,0,82,5,85,2,85,0,86]
)               # Wrap all three lists on the stack into a list
 ø              # Zip/transpose; swapping rows/columns,
                # which also discards the infinite portions
  vy            # Loop over each triplet:
    `           #  Pop and push the three values in the triplet to the stack
     Λ          #  Use the Canvas builtin with these three values as arguments
                #  (which is output immediately every iteration)

See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand why •6´XdªÅ~ßмñD>γ• is 506660546965149280261611581961 and •6´XdªÅ~ßмñD>γ•₃в is [1,8,84,80,2,80,5,82,0,82,5,85,2,85,0,86].

Additional explanation of the Canvas builtin Λ/:

It takes 3 arguments to draw an ASCII shape:

  1. Length of the lines we want to draw
  2. Character/string to draw
  3. The direction to draw in, where each digit represents a certain direction:
7   0   1
  ↖ ↑ ↗
6 ← X → 2
  ↙ ↓ ↘
5   4   3

And there are certain special 'directions': +×8.

g16иI16иð13ÅÉǝ•6´XdªÅ~ßмñD>γ•₃в)ø with input Hello, world! creates the following list of Canvas arguments:

[[13,"Hello, world!",1],
 [13," ",8],
 [13,"Hello, world!",84],
 [13," ",80],
 [13,"Hello, world!",2],
 [13," ",80],
 [13,"Hello, world!",5],
 [13," ",82],
 [13,"Hello, world!",0],
 [13," ",82],
 [13,"Hello, world!",5],
 [13," ",85],
 [13,"Hello, world!",2],
 [13," ",85],
 [13,"Hello, world!",0],
 [13,"Hello, world!",86]]
  1. The first 13,"Hello, world!",1 will draw (all) 13 characters of string "Hello, world!" in direction 1/↗: try just this first step online;
  2. The second 13," ",8 will with special direction 8 reset back to the origin (the 13 and " " are ignored): try just the first two steps online;
  3. The third 13,"Hello, world!",84 will first reset back to the origin with direction 8 (step 2 is kinda a no-op to save a byte on the 13ÅÉ), and then again draw (all) 13 characters of string "Hello, world!" in direction 4/↓: try just the first three steps online;
  4. The fourth 13," ",80 will first reset back to the origin with direction 8 again, and then draw 13 space characters in direction 0/↑: try just the first four steps online;
  5. The fifth 13,"Hello, world!",2 will then continuing from that position to draw (all) 13 characters of string "Hello, world!" in direction 2/→: try just the first five steps online;
  6. etc. etc.
  • The sixteenth 13,"Hello, world!",86 will again reset, and then draw in direction 6/←, which also fixes the space at the origin position to the first letter of the input: try all sixteen steps online (feel free to remove trailing lines to see the other untreated intermediate steps).

See this 05AB1E tip of mine to learn more about the Canvas builtin.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You might want to look at how my vyxal answer avoids canvas backtracking \$\endgroup\$
    – emanresu A
    Commented May 30 at 20:54
  • \$\begingroup\$ @emanresuA Thanks, that's indeed 1/3rd of the byte-count. ;) \$\endgroup\$ Commented May 31 at 0:00
1
\$\begingroup\$

Javascript, 225 198 bytes

Saved 27 bytes thanks to @Neil

f=(s,l=s.length-2,d=' ',r='repeat',t=d[r](l))=>[d+t+s,...a=[...Array(l)].map((_,i)=>d[r](l-i)+s[i+1]+t+(p=s[l-i])+d[r](i)+p),[...s].reverse().join``+t+s[0],...a.map(v=>v.trim()).reverse(),s].join`
`
  • [...] instead of .concat
  • [...]+map instead of for loop
  • only one statement by moving variables as function parameters
  • better initialization for l and t

Original answer:

f=s=>{l=s.length,d=' ',r='repeat',a=[],t=d[r](l-2)+s;for(i=1;i++<l-1;)a.push(d[r](l-i)+s[i-1]+d[r](l-2)+(p=s[l-i])+d[r](i-2)+p);console.log(d+[t].concat(a,[...t].reverse().join``+s[0],a.map(v=>v.trim()).reverse(),s).join`
`)}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice, although golfable: (s,l=s.length-2,d=' ',r='repeat',t=d[r](l))=>[d+t+s,...a=[...Array(l)].map((_,i)=>d[r](l-i)+s[i+1]+t+(p=s[l-i])+d[r](i)+p),[...s].reverse().join``+t+s[0],...a.map(v=>v.trim()).reverse(),s].join`\n` (using \n because you can't put newlines in comments). \$\endgroup\$
    – Neil
    Commented Sep 7, 2016 at 0:03
1
\$\begingroup\$

Ruby, 114 bytes

->s{t="#{" "*w=2*v=s.size}
"*u=w-1
v.times{|i|9.times{|j|t[[u*v,~v,u][j/3]-[1,~w,w][j%3]*~(j%-4/3*2)*i]=s[~i]}}
t}

Try it online!

Ruby, 120 118 bytes

->s{w=2*v=s.size
t=(" "*w+$/)*w
v.times{|i|9.times{|j|t[[v*w+~v,~v*3,w-2][j/3]-[1,~w,w][j%3]*~(j%-4/3*2)*i]=s[~i]}}
t}

Try it online!

An anonymous function that takes the input string as an argument s and returns a string t.

Explanation

We start by setting up a field of w=2*s.size rows each of w spaces terminated by a newline.

We then substitute, character by character, nine copies of the input string, starting at the endpoint. There are 3 endpoints each with text in 3 different directions x,y,z. This is easier to handle than starting at the beginning, since there are 4 possible startpoints each with text either in 2 or 3 directions. Variable i denotes the distance from the endpoint and s[~i] represents the character in the string, indexed in the reverse direction.

The expressions for the three endpoints are [v*w+~v,~v*3,w-2] (note that ~v*3 is negative - Ruby counts negative numbers backwards from the end of the string starting at -1). The three forward directions (for text on the outside edge of the figure) are [1,~w,w]. w is the diagonal z direction (because each line is newline terminated it has 1+w characters, so w is 1 less than this.) 1 is the x direction and ~w = -(1+w) is the y direction.

Text for edges inside the figure (those that run from the top front right corner) run in the opposite direction. These edges are written when j/3==j%3 or equivalently j%4=0. This is managed by the expression (j%-4/3*2) which evaluates to either 0 or -2. The ~ outside the bracket converts this to -1 or 1. After applying this sign correction we multiply by i to find the right point in the output string.

Commented code

->s{                         #take an input s
  w=2*v=s.size                 #v is the input length. w is double this
  t=(" "*w+$/)*w               #set up a string of w rows of w spaces, newline terminated
  v.times{|i|                  #iterate through characters in s 
    9.times{|j|                  #iterate though edges
      t[[v*w+~v,~v*3,w-2][j/3]-    #pick an end point based on j/3
        [1,~w,w][j%3]*             #subtract direction based on j%3 mutiplied by
        ~(j%-4/3*2)*               #+1 or -1 depending on whether j/3==j%3
        i]=                        #multipy by i
        s[~i]                      #assign character from s to this cell
    }
  }
t}                            #return string t
\$\endgroup\$
0
\$\begingroup\$

Java 7, 283 bytes

void a(String s){int h=s.length(),n=h*2-1,t=n-h,u=n-1;char[][]c=new char[n][n];for(int i=0;i<h;i++){c[0][t+i]=c[i][t-i]=c[t][t-i]=c[t+i][t]=c[t+i][u-i]=c[t-i][t+i]=c[t-i][u]=c[u][i]=c[u-i][0]=s.charAt(i);}for(int y=0;y<n;y++){System.out.println(new String(c[y]).replace('\0',' '));}}

Try it here!

Ungolfed:

void a(String s) {
    int length=s.length(),
        n=length*2-1,
        mid=n-length,
        doubleMid=n-1;
    char[][]c=new char[n][n];
    for(int i=0;i<length;i++) {
        c[0][mid+i]= 
        c[i][mid-i]=
        c[mid][mid-i]=
        c[mid+i][mid]=
        c[mid+i][doubleMid-i]=
        c[mid-i][mid+i]=
        c[mid-i][doubleMid]=
        c[doubleMid][i]=
        c[doubleMid-i][0]=s.charAt(i);
    }
    for(int y=0;y<n;y++){
        System.out.println(new String(c[y]).replace('\0',' '));
    }
}
\$\endgroup\$

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.