22
\$\begingroup\$

Given an input string of length 2 or longer consisting solely of alphabetical characters [A-Z] or [a-z] (your choice if they're all uppercase or all lowercase), output a continuous string of characters forming a double diamond pattern.

The input string starts on the center line and extends down-and-right at a diagonal until the end of the input string is reached. Then, the pattern continues up-and-right at a diagonal until you're as far above the center line as the length of the input string minus 1. Continue down-and-right back to the center line, then down-and-left, then up-and-left (going "behind" the center character), and finally down-and-left back to the starting character.

That's a little wordy, and it's better demonstrated by some examples:

"YOU"
  U   Y
 Y O U O
Y   O   U
 O Y U Y
  U   O

  ^   ^
 ↙ ↖ ↗ ↘
↘   ↗   >
 ↘ ↗ ↖ ↙
  V   V

See how the YOU starts at the center line and follows down-and-right, then up-and-right, etc., until it loops back to the beginning. Note especially how the Y on the up-and-left portion is "behind" the O and therefore not shown.

Some further examples:

"HI"
 I I
H H H
 I I

"TEST"
   E     E
  S T   T S
 T   T T   T
T     S     T
 E   E E   E
  S T   T S
   T     T

"HELLO"
    L       L
   O L     E L
  H   E   H   O
 E     H O     H
H       L       E
 E     L L     L
  L   E   L   L
   L H     E O
    O       H

  • Input and output can be given by any convenient method.
  • The input is guaranteed to be at least two letters long (i.e., you'll never receive "" as input).
  • You can print it to STDOUT or return it as a function result.
  • Either a full program or a function are acceptable.
  • Any amount of extraneous whitespace is acceptable, so long as the characters line up appropriately (e.g., feel free to pad as a rectangle).
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
\$\endgroup\$
5
  • \$\begingroup\$ Not sure that it matters, really, but why does the second (up left) pass go behind the first (up right) pass? Makes less intuitive sense and also a little annoying to either skip or re-draw that letter. \$\endgroup\$
    – BradC
    Oct 4, 2019 at 20:19
  • 2
    \$\begingroup\$ @BradC I was playing with a Möbius strip at my desk when I came up with the challenge, and the strip kinda goes "behind" so that's why. No other reason. \$\endgroup\$ Oct 4, 2019 at 20:21
  • \$\begingroup\$ Might be an idea to include a "drawing" of the path using arrow characters, to help us visualise it. \$\endgroup\$
    – Shaggy
    Oct 4, 2019 at 20:23
  • \$\begingroup\$ @Shaggy Added a drawing. \$\endgroup\$ Oct 4, 2019 at 20:29
  • \$\begingroup\$ Nice one, This one is more challenging then first glance.. \$\endgroup\$
    – booshlinux
    Oct 4, 2019 at 21:25

7 Answers 7

10
\$\begingroup\$

Charcoal, 17 bytes

GH<↗↘>↖↙LθθGH<Lθθ

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

GH

Draw along a path.

<↗↘>↖↙

Draw in the directions ↘↗↗↘↙↖↖↙ (the < and > are shorthands for those two pairs, but the other pairs don't have shorthands.)

Lθ

Each path segment has the same length, including the ends, of the length of the input.

θ

Use the input as the text to be written along the path.

GH<Lθθ

Print the first two parts of the path again so that the middle character is correct.

\$\endgroup\$
2
  • 3
    \$\begingroup\$ This challenge seems tailor made for Charcoal \$\endgroup\$
    – Jonah
    Oct 5, 2019 at 0:42
  • \$\begingroup\$ @Jonah Sadly, the text path command doesn't draw the last character if the path is closed, so you can't use the reverse drawing trick here. (Although if it did, it would be the same byte count anyway, since rotating the string costs 6 bytes.) \$\endgroup\$
    – Neil
    Oct 6, 2019 at 9:24
9
\$\begingroup\$

05AB1E, 12 bytes

gIR7._•Íη•Λ

Try it online!

           Λ    use the canvas function
g               with the length of input for each segment
 IR7._          the input reversed and rotated left by 7 characters (we will draw this backwards to have the right center character)
      •Íη•     and the directions 1, 3, 3, 1, 7, 5, 5, 7 as a compressed number. 
\$\endgroup\$
2
  • \$\begingroup\$ Did you mean 1, 3, 3, 1, 7, 5, 5, 7? \$\endgroup\$
    – Neil
    Oct 6, 2019 at 9:19
  • \$\begingroup\$ Oh, you're right. I mixed up the numbers a little bit \$\endgroup\$
    – Dorian
    Oct 6, 2019 at 9:32
7
\$\begingroup\$

JavaScript (ES6),  157 155  154 bytes

Returns a matrix of characters.

s=>(y=n=s.length,y+=i=X=Y=-1,m=[...Array(y+n)].map(_=>r=Array(4*n-3).fill` `),g=x=>x?g(x-=r[m[y][++i==6*n-6||+x]=s[i%n],y-=m[y-Y]?Y:Y=-Y,x-X]?X:X=-X):m)``

Try it online!

How?

Given the length \$n\$ of the input string, we build a matrix of size \$w\times h\$, with:

  • \$w = 4n-3\$
  • \$h = 2n-1\$

We run a simulation of a 'ball' bouncing in this matrix, starting at \$(0,n-1)\$ and heading South-East, until it's back to its initial position.

The 0-based index of the center character that must be skipped in the diamond shape is:

$$p=6n-6$$

Example for \$n=4\$:

enter image description here

Commented

s => (                           // s = input string
  y = n = s.length,              // n = length of s
  y += i = X = Y = -1,           // y = n - 1; i = X = Y = -1
  m =                            // create a matrix m[]:
    [...Array(y + n)].map(_ =>   //   - of height 2n-1
      r = Array(4 * n - 3)       //   - of width 4n-3 (save one of these rows in r[])
          .fill` `               //   - initially filled with spaces
    ),                           //
    g = x =>                     // g is a recursive function taking x
      x ?                        //   if x is truthy:
        g(                       //     do a recursive call:
          x -= r[                //       update x:
            m[y][                //         update m[y][x]:
              ++i == 6 * n - 6   //           unless this is the 2nd pass through the
              || +x              //           center cell, set it to the next character
            ] = s[i % n],        //           in s (otherwise we write to m[y][true]
                                 //           instead, which has no effect)
            y -=                 //         update y:
              m[y - Y] ? Y       //           bounce vertically if m[y - Y] is undefined
                       : Y = -Y, //
            x - X                //         bounce horizontally
          ] ? X                  //         if r[x - X] is undefined
            : X = -X             //
        )                        //     end of recursive call
      :                          //   else:
        m                        //     stop recursion and return m[]
)``                              // initial call to g with x = [''] (zero-ish but truthy)
\$\endgroup\$
2
  • \$\begingroup\$ I have a 136 byte solution that's inspired by your solution, although I think by now it might be different enough to qualify as a separate answer. \$\endgroup\$
    – Neil
    Oct 5, 2019 at 10:46
  • \$\begingroup\$ @Neil You should probably post it as a new answer. \$\endgroup\$
    – Arnauld
    Oct 5, 2019 at 10:50
3
\$\begingroup\$

JavaScript (ES6), 136 bytes

f=
(s,l=s.length-1,z=l*4,a=[...Array(l-~l)].map(_=>Array(z+1).fill` `),g=x=>x--?g(x,a[a[y=(x+l)%z]?y:z-y][x>z?z+z-x:x]=s[x%-~l]):a)=>g(z+z)
<input oninput=o.textContent=f(this.value).map(c=&gt;c.join``).join`\n`><pre id=o>

Returns a two-dimensional array. Works by drawing the string into the array directly computing the destination co-ordinates working backwards from the end so that the centre cell is overwritten automatically. Explanation:

(s

Input string.

,l=s.length-1

Distance between "bounces", also half the last row index and one less than the length.

,z=l*4

Last column index, also half of the length of text to draw.

,a=[...Array(l-~l)].map(_=>Array(z+1).fill` `)

Array of spaces.

,g=x=>x--

Count down from the last cell to the first.

  ?g(x

Recursive call to process the remaining cells.

    ,a[a[y=(x+l)%z]?y:z-y]

Calculate the row of this cell.

      [x>z?z+z-x:x]=s[x%-~l])

Calculate the column of this cell and the character that belongs there.

  :a

Finish by returning the array.

)=>g(z+z)

Start at the end of the text.

\$\endgroup\$
1
  • \$\begingroup\$ That's a nice one, +1 \$\endgroup\$
    – Ver Nick
    Oct 8, 2019 at 7:36
3
\$\begingroup\$

J, 79 77 75 bytes

(|.@$~8*])`([:;/(1,~<:@])+/\@,(_2{&1 _1\#:33495)}.@#~])`(' '$~1+2 4*])}<:@#

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C (clang), 201 196 188 bytes

x,y,i,v,m,n;f(s,z){char*a=s,o[i=(y=z*2-1)*(x=y+y)];for(v=x*2-2;i;n=m=1)o[--i]=i%x?32:10;for(i=x*--z;v--;i+=x*m+n)o[i]==32?o[i]=*a:0,a=*++a?a:s,n=i%x>x-3?-1:n,m=i/x?i/x<y-1?m:-1:1;puts(o);}

Try it online!

-13 @ceilingcat suggestions

\$\endgroup\$
0
0
\$\begingroup\$

Python 2, 137 bytes

s=input();n=len(s);m=2*n-2
for r in range(m+1):print''.join([s[[x,-8-x][(x<=m)==(m>2*r)]%n],' '][r!=(x+1-n)%m!=m-r]for x in range(4*n-3))

Try it online!

A full program that takes a string as input as prints out the diamondized version.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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