34
\$\begingroup\$

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!

\$\endgroup\$
  • 4
    \$\begingroup\$ Example: 4? Or any even number. \$\endgroup\$ – TheLethalCoder Jun 12 '17 at 12:30
  • 1
    \$\begingroup\$ May we assume the input is odd? \$\endgroup\$ – Mr. Xcoder Jun 12 '17 at 12:34
  • 1
    \$\begingroup\$ Related \$\endgroup\$ – Emigna Jun 12 '17 at 12:35
  • 2
    \$\begingroup\$ Possible dupe? \$\endgroup\$ – Shaggy Jun 12 '17 at 13:10
  • 1
    \$\begingroup\$ See also perlmonks.com/?node_id=487200 with many solutions and links in replies. \$\endgroup\$ – b_jonas Jun 13 '17 at 13:07

17 Answers 17

43
\$\begingroup\$

MATL, 3 bytes

1YL

Try it online!

Explanation

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

\$\endgroup\$
  • 31
    \$\begingroup\$ Why... why is this a built in? \$\endgroup\$ – TheLethalCoder Jun 12 '17 at 12:34
  • 2
    \$\begingroup\$ I'm guessing this is something to do with the "Magic Square" stuff? \$\endgroup\$ – Magic Octopus Urn Jun 12 '17 at 12:39
  • 8
    \$\begingroup\$ @TheLethalCoder Because Matlab had it and I thought it would be useful (which it is indeed) \$\endgroup\$ – Luis Mendo Jun 12 '17 at 12:41
18
\$\begingroup\$

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;
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ ++i<=n; can become n>++i, nothing else I can see, +1. \$\endgroup\$ – LiefdeWen Jun 13 '17 at 6:23
  • 1
    \$\begingroup\$ n%2<1?2:1 to 2-x%2 ? I haven't tested it in C#, but in C and Python it worked. \$\endgroup\$ – Felipe Nardi Batista Jun 13 '17 at 10:42
  • 1
    \$\begingroup\$ for(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 \$\endgroup\$ – Felipe Nardi Batista Jun 13 '17 at 11:11
  • \$\begingroup\$ @FelipeNardiBatista Awesome would never have thought of those two! Thanks. \$\endgroup\$ – TheLethalCoder Jun 13 '17 at 11:16
  • 1
    \$\begingroup\$ var 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++; \$\endgroup\$ – Felipe Nardi Batista Jun 13 '17 at 11:25
15
\$\begingroup\$

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.

\$\endgroup\$
9
\$\begingroup\$

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);
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Is 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? \$\endgroup\$ – Zacharý Jun 14 '17 at 16:48
  • 1
    \$\begingroup\$ You may be able to replace k<=n; with n>k; to save a byte. \$\endgroup\$ – Jonathan Frech Sep 9 '17 at 20:44
6
\$\begingroup\$

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!

\$\endgroup\$
  • 1
    \$\begingroup\$ [-1,1][$d&1] --> $d&1?:-1 \$\endgroup\$ – Titus Jun 13 '17 at 11:13
  • \$\begingroup\$ @Titus Thank You I have not see it \$\endgroup\$ – Jörg Hülsermann Jun 13 '17 at 11:18
  • 1
    \$\begingroup\$ Here 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. \$\endgroup\$ – Titus Jun 13 '17 at 11:40
  • 1
    \$\begingroup\$ And I think that in the second version You can initialize $s to a padded underscore (or letter or digit); that character will be overwritten. \$\endgroup\$ – Titus Jun 13 '17 at 11:46
  • \$\begingroup\$ @Titus Thank You and you can use the .d in your own approach to save 2 bytes \$\endgroup\$ – Jörg Hülsermann Jun 13 '17 at 12:13
6
\$\begingroup\$

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
}
\$\endgroup\$
6
\$\begingroup\$

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+×⍨-).

\$\endgroup\$
5
\$\begingroup\$

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)&
\$\endgroup\$
  • 8
    \$\begingroup\$ Waaait, no built-in for this in Mathematica? \$\endgroup\$ – Mr. Xcoder Jun 12 '17 at 15:35
5
\$\begingroup\$

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;
    }
}
\$\endgroup\$
5
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ how did you count your bytes? tabs, spaces and newlines counts as well \$\endgroup\$ – Felipe Nardi Batista Jun 13 '17 at 11:56
  • \$\begingroup\$ 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? \$\endgroup\$ – nocturama Jun 13 '17 at 13:21
  • \$\begingroup\$ i'm counting \t and \n as 1 byte and still getting 249 bytes \$\endgroup\$ – Felipe Nardi Batista Jun 13 '17 at 13:23
  • \$\begingroup\$ 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 \$\endgroup\$ – nocturama Jun 13 '17 at 13:29
  • \$\begingroup\$ usually text editors tell you how many characters are selected, so CTRL+A and read what it says \$\endgroup\$ – Felipe Nardi Batista Jun 13 '17 at 14:32
5
\$\begingroup\$

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.

\$\endgroup\$
4
\$\begingroup\$

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.

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

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.

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – Jonah Apr 7 at 6:58
1
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ this isn't Python, it's Python + numpy \$\endgroup\$ – ASCII-only Apr 7 at 3:30
  • \$\begingroup\$ @ASCII-only Is there a master list of acceptable language names somewhere? This is perfectly valid python. \$\endgroup\$ – user2699 Apr 8 at 2:16
  • \$\begingroup\$ 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 \$\endgroup\$ – ASCII-only Apr 8 at 3:02
  • \$\begingroup\$ @ASCII-only where's that written out? I haven't seen it done with most python answers. \$\endgroup\$ – user2699 Apr 8 at 3:06
  • \$\begingroup\$ Yes, because most of them don't use numpy... and the stdlib doesn't count as an external library \$\endgroup\$ – ASCII-only Apr 8 at 3:12
0
\$\begingroup\$

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!

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

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

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

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.

\$\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.