Wind me a number snake!

34

4

Given an input integer n, draw a number snake, that is, a grid measuring n x n consisting of the numbers 1 through n^2 that are wound around each other in the following fashion:

Input n = 3:

7 8 9
6 1 2
5 4 3

Input n = 4:

 7  8  9 10
 6  1  2 11
 5  4  3 12
16 15 14 13

Input n = 5:

21 22 23 24 25
20  7  8  9 10
19  6  1  2 11
18  5  4  3 12
17 16 15 14 13

(Inspired by this problem from Project Euler.)

This is , the shortest answer in bytes wins!

Julius

Posted 2017-06-12T12:28:37.353

Reputation: 431

4Example: 4? Or any even number. – TheLethalCoder – 2017-06-12T12:30:51.177

May we output an array of arrays of ints? – TheLethalCoder – 2017-06-12T12:32:01.137

1May we assume the input is odd? – Mr. Xcoder – 2017-06-12T12:34:03.170

1Related – Emigna – 2017-06-12T12:35:58.223

Related Project Euler problem – Okx – 2017-06-12T12:36:51.387

@Okx I was inspired by that. – Julius – 2017-06-12T12:37:34.177

@TheLethalCoder I added an example for n = 4. – Julius – 2017-06-12T12:37:50.040

2Possible dupe? – Shaggy – 2017-06-12T13:10:11.340

Can the lines be outputted as an array or a sequence of cells? (asking for brainfuck) – Uriel – 2017-06-12T14:19:43.560

@Uriel No, please print the output in a grid. – Julius – 2017-06-12T18:10:20.647

1

See also http://www.perlmonks.com/?node_id=487200 with many solutions and links in replies.

– b_jonas – 2017-06-13T13:07:23.653

Answers

43

MATL, 3 bytes

1YL

Try it online!

Explanation

Built-in... ¯\_(ツ)_/¯

Luis Mendo

Posted 2017-06-12T12:28:37.353

Reputation: 87 464

31Why... why is this a built in? – TheLethalCoder – 2017-06-12T12:34:38.617

2I'm guessing this is something to do with the "Magic Square" stuff? – Magic Octopus Urn – 2017-06-12T12:39:37.753

8

@TheLethalCoder Because Matlab had it and I thought it would be useful (which it is indeed)

– Luis Mendo – 2017-06-12T12:41:26.650

18

C#, 203 202 196 193 178 bytes

n=>{var r=new int[n,n];for(int o=n-2+n%2>>1,i=r[o,o]=1,c=2,w=o,h=o,b=1-2*(i%2),j;n>i++;){r[h,w+=b]=c++;for(j=0;j<i-1;++j)r[h+=b,w]=c++;for(j=0;j<i-1;++j)r[h,w-=b]=c++;}return r;}

Saved a byte thanks to @StefanDelport.
Saved 22 bytes thanks to @FelipeNardiBatista.

This works by the following observation of how the squares are built up:

Image of square where n=5

As you can see each bit is added on to the previous square. For even numbers we go right of where we were, down till were one lower than where the square was and then left to the end. Odd numbers are essentially the opposite, we go left one, up till were one above the current height and then right to the end.

Full/Formatted version:

using System;
using System.Linq;

class P
{
    static void Main()
    {
        Func<int, int[,]> f = n =>
        {
            var r = new int[n, n];
            for (int o = n - 2 + n % 2 >> 1, i = r[o, o] = 1, c = 2, w = o, h = o, b = 1 - 2 * (i % 2), j; n > i++;)
            {
                r[h, w += b] = c++;

                for (j = 0; j < i - 1; ++j)
                    r[h += b, w] = c++;

                for (j = 0; j < i - 1; ++j)
                    r[h, w -= b] = c++;
            }

            return r;
        };

        Console.WriteLine(String.Join("\n", f(3).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
        Console.WriteLine(String.Join("\n", f(4).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
        Console.WriteLine(String.Join("\n", f(5).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");

        Console.ReadLine();
    }
}

public static class ArrayExtensions
{
    public static T[][] ToJagged<T>(this T[,] value)
    {
        T[][] result = new T[value.GetLength(0)][];

        for (int i = 0; i < value.GetLength(0); ++i)
            result[i] = new T[value.GetLength(1)];

        for (int i = 0; i < value.GetLength(0); ++i)
            for (int j = 0; j < value.GetLength(1); ++j)
                result[i][j] = value[i, j];

        return result;
    }
}

TheLethalCoder

Posted 2017-06-12T12:28:37.353

Reputation: 6 930

1++i<=n; can become n>++i, nothing else I can see, +1. – LiefdeWen – 2017-06-13T06:23:29.710

1n%2<1?2:1 to 2-x%2 ? I haven't tested it in C#, but in C and Python it worked. – Felipe Nardi Batista – 2017-06-13T10:42:32.950

1for(int o=n-2+n%2>>1,i=r[o,o]=1,c=2,w=o,h=o,j;n>i++;){var b=i%2<1; .... golfed a bit – Felipe Nardi Batista – 2017-06-13T11:11:58.277

@FelipeNardiBatista Awesome would never have thought of those two! Thanks. – TheLethalCoder – 2017-06-13T11:16:04.393

1var b=1-2*(i%2);r[h,w+=b]=c++;for(j=0;j<i-1;++j)r[h+=b,w]=c++;for(j=0;j<i-1;++j)r[h,w-=b]=c++; – Felipe Nardi Batista – 2017-06-13T11:25:23.517

15

Dyalog APL, 70 56 45 41 bytes

,⍨⍴∘(⍋+\)×⍨↑(⌈2÷⍨×⍨),(+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳

Try it online!

How?

(+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳

calculates the differences between the indices; 1 and ¯1 for right and left, ¯⍵ and for up and down.

1,⊢,¯1,- comes as 1 ⍵ ¯1 ¯⍵, +⍨⍴ stretches this array to the length of ⍵×2, so the final 2/⍳ can repeat each of them, with a repetition count increasing every second element:

      (1,⊢,¯1,-) 4
1 4 ¯1 ¯4
      (+⍨⍴1,⊢,¯1,-) 4
1 4 ¯1 ¯4 1 4 ¯1 ¯4
      (2/⍳) 4
1 1 2 2 3 3 4 4
      ((+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳) 4
1 4 ¯1 ¯1 ¯4 ¯4 1 1 1 4 4 4 ¯1 ¯1 ¯1 ¯1 ¯4 ¯4 ¯4 ¯4

then,

(⌈2÷⍨×⍨),

prepends the top-left element of the spiral,

×⍨↑

limit the first ⍵2 elements of this distances list,

+\

performs cumulative sum,

grades up the indices (⍵[i] = ⍵[⍵[i]]), to translate the original matrix with the indices of every element, and finally

,⍨⍴

shapes as a ⍵×⍵ matrix.

Uriel

Posted 2017-06-12T12:28:37.353

Reputation: 11 708

For those interested, this technique is discussed at length in this excellent article.

– Jonah – 2019-04-06T22:37:44.760

9

C, 321 307 295 284 283 282 bytes

Thanks to both @Zachary T and @Jonathan Frech for golfing a byte!

#define F for(b=a;b--;)l
i,j,k,a,b,m;**l;f(n){n*=n;l=calloc(a=m=3*n,4);F[b]=calloc(m,4);for(l[i=j=n][j]=a=k=1;n>k;++a){F[i][++j]=++k;F[++i][j]=++k;++a;F[i][--j]=++k;F[--i][j]=++k;}for(i=0;i<m;++i,k&&puts(""))for(j=k=0;j<m;)(a=l[i][j++])>0&&a<=n&&printf("%*d ",(int)log10(n)+1,k=a);}

Allocates a two-dimensional array of zeroes, then starts filling it from somewhere in the middle. Lastly the values that are larger than zero but smaller than or equal to the square of the input are printed.

Try it online!

Formatted:

#define F for(b=a; b--;)l
i, j, k, a, b, m; **l;
f(n)
{
    n *= n;
    l = calloc(a=m=3*n, 4);

    F[b] = calloc(m, 4);

    for(l[i=j=n][j]=a=k=1; n>k; ++a)
    {
        F[i][++j] = ++k;
        F[++i][j] = ++k;
        ++a;

        F[i][--j] = ++k;
        F[--i][j] = ++k;
    }

    for(i=0; i<m; ++i, k&&puts(""))
        for(j=k=0; j<m;)
            (a=l[i][j++])>0 && a<=n && printf("%*d ", (int)log10(n)+1, k=a);
}

Steadybox

Posted 2017-06-12T12:28:37.353

Reputation: 15 798

1Is it possible to replace i,j,k,a,b,m;f(n){n*=n;int**l=calloc(a=m=3*n,4); with i,j,k,a,b,m,**l;f(n){n*=n;l=calloc(a=m=3*n,4); to save a byte? – Zacharý – 2017-06-14T16:48:29.110

1You may be able to replace k<=n; with n>k; to save a byte. – Jonathan Frech – 2017-09-09T20:44:15.813

6

PHP, 192 bytes

for($l=strlen($q=($a=$argn)**2)+$d=1,$x=$y=$a/2^$w=0;$i++<$q;${yx[$w%2]}+=$d&1?:-1,$i%$d?:$d+=$w++&1)$e[$x-!($a&1)][$y]=sprintf("%$l".d,$i);for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);

Try it online!

Same way build a string instead of an array

PHP, 217 bytes

for($l=strlen($q=($a=$argn)**2)+$d=1,$x=$y=($a/2^$w=0)-!($a&1),$s=str_pad(_,$q*$l);$i++<$q;${yx[$w%2]}+=$d&1?:-1,$i%$d?:$d+=$w++&1)$s=substr_replace($s,sprintf("%$l".d,$i),($x*$a+$y)*$l,$l);echo chunk_split($s,$a*$l);

Try it online!

Jörg Hülsermann

Posted 2017-06-12T12:28:37.353

Reputation: 13 026

1[-1,1][$d&1] --> $d&1?:-1 – Titus – 2017-06-13T11:13:59.377

@Titus Thank You I have not see it – Jörg Hülsermann – 2017-06-13T11:18:50.453

1Here is one more byte: for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);. And another one: "%$l".d. And one more: $x*$l*$a+$y*$l --> ($x*$a+$y)*$l. – Titus – 2017-06-13T11:40:04.773

1And I think that in the second version You can initialize $s to a padded underscore (or letter or digit); that character will be overwritten. – Titus – 2017-06-13T11:46:36.690

@Titus Thank You and you can use the .d in your own approach to save 2 bytes – Jörg Hülsermann – 2017-06-13T12:13:38.563

6

PHP, 185 176 174 bytes

for(;$n++<$argn**2;${xy[$m&1]}+=$m&2?-1:1,$k++<$p?:$p+=$m++%2+$k=0)$r[+$y][+$x]=$n;ksort($r);foreach($r as$o){ksort($o);foreach($o as$i)printf(" %".strlen($n).d,$i);echo"
";}

Run as pipe with -nR or test it online.

breakdown

for(;$n++<$argn**2;     # loop $n from 1 to N squared
    ${xy[$m&1]}+=$m&2?-1:1, # 2. move cursor
    $k++<$p?:               # 3. if $p+1 numbers have been printed in that direction:
        $p+=$m++%2+             # increment direction $m, every two directions increment $p
        $k=0                    # reset $k
)$r[+$y][+$x]=$n;           # 1. paint current number at current coordinates

ksort($r);              # sort grid by indexes
foreach($r as$o){       # and loop through it
    ksort($o);              # sort row by indexes
    foreach($o as$i)        # and loop through it
        printf(" %".strlen($n).d,$i);   # print formatted number
    echo"\n";               # print newline
}

Titus

Posted 2017-06-12T12:28:37.353

Reputation: 13 814

6

APL (Dyalog Classic), 32 29 bytes

1+×⍨-{⊖∘⌽⍣⍵⌽{⌽⍉,⌸⍵+≢⍵}⍣2⍣⍵⍪⍬}

Try it online!

Uses ⎕io←1. Starts with a 0-by-1 matrix (⍪⍬). 2N times (⍣2⍣⍵) adds the height of the matrix (≢⍵) to each of its elements, puts 1 2...height on its right (,⌸), and rotates (⌽⍉). When that's finished, corrects the orientation of the result (⊖∘⌽⍣⍵⌽) and reverses the numbers by subtracting them from N2+1 (1+×⍨-).

ngn

Posted 2017-06-12T12:28:37.353

Reputation: 11 449

5

Mathematica, 177 bytes

(n=#;i=j=Floor[(n+1)/2];c=1;d=0;v={{1,0},{0,-1},{-1,0},{0,1}};a=Table[j+n(i-1),{i,n},{j,n}];Do[Do[Do[a[[j,i]]=c++;{i,j}+=v[[d+1]], {k,l}];d=Mod[d+1,4],{p,0,1}],{l,n-1}];Grid@a)&

J42161217

Posted 2017-06-12T12:28:37.353

Reputation: 15 931

8Waaait, no built-in for this in Mathematica? – Mr. Xcoder – 2017-06-12T15:35:52.097

5

Python 3, 249 247 bytes

I initialize an 2D array and find the starting point, which is the center for odd n or offset (-1,-1) for even n, then scale the fill/cursor pattern with the current 'ring' number. I feel like I'm missing a trick for interpreting the directions but I haven't come up with anything cheaper.

def f(n):
 M=[n*[0]for a in range(n)]
 x=y=n//2-1+n%2
 M[x][y]=i=s=1
 while 1:
  t=s*2
  for d in'R'+'D'*(t-1)+'L'*t+'U'*t+'R'*t:
   if i==n*n:print(*M,sep='\n');return
   v=[1,-1][d in'LU']
   if d in'UD':x+=v
   else:y+=v
   M[x][y]=i=i+1
  s+=1

Try it online!

-2 thanks to Zachary T!

nocturama

Posted 2017-06-12T12:28:37.353

Reputation: 111

how did you count your bytes? tabs, spaces and newlines counts as well – Felipe Nardi Batista – 2017-06-13T11:56:06.240

I replaced every \n and \t with " " and took a len(). I just copied the above and redid it to make sure I didn't change anything and forget to recount but I got the same number. Did I miss something? – nocturama – 2017-06-13T13:21:31.570

i'm counting \t and \n as 1 byte and still getting 249 bytes – Felipe Nardi Batista – 2017-06-13T13:23:16.057

e:^^^is there a better/easier method I should use? they always appeared to be used interchangeably to me.^^^ Strange, this is what I get in IDLE: len("def f(n): M=[n*[0]for a in range(n)] x=y=n//2-(n%2<1) M[x][y]=i=s=1 while 1: t=s*2 for d in'R'+'D'*(t-1)+'L'*t+'U'*t+'R'*t: if i==n*n:print(*M,sep='\n');return v=[1,-1][d in'LU'] if d in'UD':x+=v else:y+=v M[x][y]=i=i+1 s+=1") 223 – nocturama – 2017-06-13T13:29:54.493

usually text editors tell you how many characters are selected, so CTRL+A and read what it says – Felipe Nardi Batista – 2017-06-13T14:32:24.877

I think you can change x=y=n//2-(n%2<1) to x=y=n//2-1+n%2 to save two bytes. – Zacharý – 2017-06-14T16:38:07.360

5

C++, 245 228 bytes

void f(){for(int i=0,j=-1,v,x,y,a,b;i<n;i++,j=-1,cout<<endl)while(++j<n){x=(a=n%2)?j:n-j-1;y=a?i:n-i-1;v=(b=y<n-x)?n-1-2*(x<y?x:y):2*(x>y?x:y)-n;v=v*v+(b?n-y-(y>x?x:y*2-x):y+1-n+(x>y?x:2*y-x));cout<<setw(log10(n*n)+1)<<v<<' ';}}

Try it online!

The function calculates and prints the value of each number of the matrix depending on its x, y position by applying this logic:

Snake values calculation depending on position

Formatted version:

#include <iostream>
#include <iomanip>
#include <math.h>

using namespace std;

void f(int n)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int value = 0;

            // Invert x and y when n is even
            int x = n % 2 == 0 ? n - j - 1 : j;
            int y = n % 2 == 0 ? n - i - 1 : i;
            if (y < (n - x))
            {
                // Left-top part of the matrix
                int padding = x < y ? x : y;
                value = n - 1 - padding * 2;
                value *= value;
                value += y >= x ? n - x - y : n + x - y - (y * 2);
            }
            else
            {
                // Right-bottom part of the matrix
                int padding = x > y ? n - x : n - y;
                value = n - padding * 2;
                value *= value;
                value += x > y ? y - padding + 1 : n + y - x - (padding * 2) + 1;
            }

            cout << setw(log10(n * n) + 1);
            cout << value << ' ';
        }

        cout << endl;
    }
}

int main()
{
    int n;
    while (cin >> n && n > 0)
    {
        f(n);
        cout << endl;
    }
}

Julio E. Rodríguez Cabañas

Posted 2017-06-12T12:28:37.353

Reputation: 151

5

Wolfram Language (Mathematica), (...) 83 bytes

Byte measured in UTF8, \[LeftFloor] () and \[RightFloor] () cost 3 bytes each. Mathematica doesn't have any special byte character set.

Table[Max[4x^2-Max[x+y,3x-y],4y
y-{x+y,3y-x}]+1,{y,b+1-#,b=⌊#/2⌋},{x,b+1-#,b}]&

Try it online!


Uses the closed form for each of the 4 cases, then takes the maximum carefully to get the desired result.

Returns a 2D array of integers. I'm not sure if this is allowed, and although it has been asked in the comments, the OP didn't reply.

user202729

Posted 2017-06-12T12:28:37.353

Reputation: 14 620

4

Clojure, 206 bytes

(defmacro F[s]`(if(~'r(+ ~'p ~'v ~s))~'v ~s))
#(loop[i 1 p(*(quot(dec %)2)(inc %))v 1 r{}](if(<(* % %)i)(partition %(map r(range i)))(recur(inc i)(+ p v)({1(F %)-1(F(- %))%(F -1)(- %)(F 1)}v)(assoc r p i))))

I guess this is a decent start, builds the board in sequence to a hash-map and then partitions it into n x n lists. That defmacro ended up being quite long, but the code is still shorter with it than without. Is there a more succint syntax to describe it?

Bulk of bytes calculate the starting point, and build the look-up logic of the next velocity v. Perhaps a nested vec would be better, but then you've got two indexes and velocities to keep track of.

NikoNyrh

Posted 2017-06-12T12:28:37.353

Reputation: 2 361

3

J, 41 bytes

(]|.@|:@[&0](|.@|:@,.*/@$+#\)@]^:[1:)2*<:

Try it online!

Does the same thing as ngn’s APL submission but starts with a 1-by-1 matrix and repeats 2×N−2 times.

FrownyFrog

Posted 2017-06-12T12:28:37.353

Reputation: 3 112

Can you improve my alternative approach (now tied at 41) to beat yourself? I've given it my best golf so far, but I suspect at least a few more bytes could be shaved off.

– Jonah – 2019-04-07T06:58:05.837

1

Python 165 (or 144)

from pylab import *
def S(n):
 a=r_[[[1]]];r=rot90;i=2
 while any(array(a.shape)<n):
  q=a.shape[0];a=vstack([range(i,i+q),r(a)]);i+=q
 if n%2==0:a=r(r(a))
 print(a)

This creates a numpy array, then rotates it and adds a side until the correct size is reached. The question didn't specify if the same start point needs to be used for even and odd numbers, if that's not the case the line if n%2==0:a=r(r(a)) can be removed, saving 21 bytes.

user2699

Posted 2017-06-12T12:28:37.353

Reputation: 538

1this isn't Python, it's Python + numpy – ASCII-only – 2019-04-07T03:30:13.443

@ASCII-only Is there a master list of acceptable language names somewhere? This is perfectly valid python. – user2699 – 2019-04-08T02:16:59.913

It uses a library, so you need to include the library's name as well... as for allowed languages, any language with a publicly available implementation you can get to run is allowed – ASCII-only – 2019-04-08T03:02:07.567

@ASCII-only where's that written out? I haven't seen it done with most python answers. – user2699 – 2019-04-08T03:06:21.797

Yes, because most of them don't use numpy... and the stdlib doesn't count as an external library – ASCII-only – 2019-04-08T03:12:23.110

0

Python 3 (Stackless), 192 188 179 150 bytes

lambda n:[list(map(v,list(range(t-n,t)),[y]*n))for t in[1+n//2]for y in range(n-t,-t,-1)]
v=lambda x,y,r=0:y>=abs(x)and(3-2*r+4*y)*y+x+1or v(y,-x,r+1)

Try it online!

The algorithm here is to form a phasor for each coordinate in the grid, and then rotate it 90-degrees clockwise until the phasor lies between the upper diagonals. A simple formula can be used to calculate the value based on the coordinates and the number of clockwise rotations: $$ (2y+1)^2-(y-x)-2yr $$

Saved 4-bytes since 90-degree phasor rotation is easily done without complex numbers

SmileAndNod

Posted 2017-06-12T12:28:37.353

Reputation: 119

0

J, 41 bytes

,~$[:/:[:+/\_1|.1&,(]##@]$[,-@[)2}:@#1+i.

standard formatting

,~ $ [: /: [: +/\ _1 |. 1&, (] # #@] $ [ , -@[) 2 }:@# 1 + i.

This approach is based off At Play With J Volutes (Uriel's APL uses a similar technique).

It's unexpected and elegant enough to justify a 2nd J answer, I thought.

Essentially, we don't do anything procedural or even geometric. Instead, we arithmetically create a simple sequence that, when scan summed and graded up, gives the correct order of the spiraled number from left to right, top to bottom. We then shape that into a matrix and are done.

I'll add a more detailed explanation when time permits, but the linked article explains it in depth.

Try it online!

Jonah

Posted 2017-06-12T12:28:37.353

Reputation: 8 729

0

R, 183 bytes

x=scan()
b=t(d<-1)
while(2*x-1-d){m=max(b)
y=(m+1):(m+sum(1:dim(b)[2]|1))
z=d%%4
if(z==1)b=cbind(b,y)
if(z==2)b=rbind(b,rev(y))
if(z==3)b=cbind(rev(y),b)
if(z==0)b=rbind(y,b)
d=d+1}
b

Try it online!

Output is a matrix snake (or snake matrix, whatever). It's probably not the most efficient method, and it could likely be golfed, but I thought it was worth showing. I'm rather proud of this actually!

The method builds the matrix from the inside out, always appending an additional number of integers equal to the number of columns in the matrix before appending. The pattern that follows is either binding by columns or by rows, while also reversing some values so they are appended in the correct order.

193 bytes

Exact same as above, but final b is

matrix(b,x)

Try it online!

which gives slightly cleaner output, but I didn't see any special criteria for output, so the first answer should work if I'm not mistaken.

Sumner18

Posted 2017-06-12T12:28:37.353

Reputation: 1 334