Skip to main content
2 of 4
Golf more and add minor explanation
anderium
  • 613
  • 5
  • 9

Python 3, 371 274 bytes

def f(s,n):
 for y in(a:=range(n)):
  for x in a:r=min(x,y,n+~x,n+~y);i=4*r*(n-r)-2*r+x+y+2*(2*(n+~r)-x-y)*(y>x);H=max(n+~y,y)>x>min(y-2,n-y-2);b=x+1>n/2;D=(n+~x-x)*b+x==n+~y;print(s[i]if i<len(s)else".<.>"[D+n%2*2]if(n+2*~x)*b+x==y-1else"|'-'"[D+2*H],end=" -"[H])
  print()

Try it online!

Minus 64 bytes thanks to @noodleman and another 11 bytes thanks to @Kevin Cruijssen! I then saved another 22 bytes.

Instead of most other solutions (as far as I can tell), I tried calculating the index into the string. I dug up a post on StackOverflow that helped with this, though a lot was just throwing random equations and seeing what they do. Maybe the indexing equation can be simplified with a bit more thought, but it's surprisingly short already.

There are lots of places where -x-1 is replaced with +~x (or variants). Booleans are heavily used for indexing and cancelling parts of equations with multiplication.

Ungolfed:

def function(string: str, number: int):
  for y in range(number):
    for x in range(number):
      rounds = min(x, y, number - x - 1, number - y - 1)
        # total increments after `rounds` revolutions and fix for overcounting
      index = 4 * rounds * (number - rounds) - 2 * rounds
      index += x + y  # east + south increment
      index += 2 * (2 * (number - rounds - 1) - x - y) * (y > x)  # west + north

      is_horizontal = max(number - y + 1, y + 2) > x + 2 > min(y, number - y)
      is_right = x + 1 > number / 2
      is_up_corner = x + is_right * (number - 2 * (x + 1)) == y - 1  # inlined
      is_down_corner = x + is_right * (number - 1 - 2 * x) == number - y - 1

      # is_middle = x + 1 - number % 2 == y == number // 2
      # is_middle = is_up_corner and is_down_corner
      # is_down = y > number / 2
      # is_left_corner = y + is_down * (number - 2 * y) == x + 1
      # is_right_corner = y + is_down * (number - 1 - 2 * y) != number - x - 1

      print(
        string[index] if index < len(string) else
        ".<.>"[is_down_corner + 2 * (number % 2)] if is_up_corner else
        "|'-'"[is_down_corner + 2 * is_horizontal],
        end=" -"[is_horizontal]
      )
    print()

Explanation of is_horizontal boolean: There are effectively four quadrants in which we need to determine whether the coordinate is a horizontal part in the snake, we can do this for the upper right corner with number - y - 1 > x. On its own this is not enough, because the lower part of the snake is now messed up. Taking y > x works for the lower right quadrant, but messes up the snake above. Combining these two equations into max(number - y - 1, y) > x leaves only the left part of the snake to fix. Creating conditions for the other corners you can combine x > min(y - 2, number - y - 2) into one large expression.

------------.                 ------------.                 ------------.
.---------. |                 .---------. |                 .---------. |
--.-----. | |                 --.-----. | |                 | .-----. | |
----.-> | | |     becomes     ----.-> | | |     becomes     | | .-> | | |
----' | ' | |                 ----'---' | |                 | | '---' | |
--' | | | ' |                 --'-------' |                 | '-------' |
' | | | | | '                 '-----------'                 '-----------'
anderium
  • 613
  • 5
  • 9