| Bytes | Lang | Time | Link |
|---|---|---|---|
| 047 | Wolfram Language Mathematica | 220216T071342Z | alephalp |
| 046 | Julia | 220216T135544Z | MarcMush |
| 151 | R | 220131T150247Z | Xi'a |
| 079 | Factor + math.matrices | 220201T093726Z | chunes |
| 067 | R | 220127T210244Z | pajonk |
| 078 | R | 220128T142808Z | Giuseppe |
| 016 | APL Dyalog Unicode | 220127T084235Z | Bubbler |
| 011 | MATL | 220126T191535Z | Giuseppe |
| 073 | Python | 220127T025655Z | loopy wa |
| 013 | 05AB1E | 220127T132644Z | Kevin Cr |
| 040 | Charcoal | 220126T213927Z | Neil |
| 029 | BQN | 220126T194809Z | ovs |
| 101 | JavaScript ES7 | 220127T015045Z | Arnauld |
| 091 | JavaScript Node.js | 220127T041609Z | tsh |
| 013 | Jelly | 220127T042618Z | Bubbler |
| 032 | Jelly | 220127T015329Z | Jonathan |
| 108 | JavaScript Node.js | 220127T025229Z | tsh |
| 035 | APL Dyalog Unicode | 220126T193010Z | Adá |
Wolfram Language (Mathematica), 47 bytes
-13 bytes thanks to @att.
Nest[Reverse[{--i,##}&@@@#]&,{{}},i=2#-1]-i&
Julia, 46 bytes
m\n=[1:n n.+rotl90(m')]'
!n=[n<2||!~-n\~-n\n;]
the simple rotate and add row, with some trickery with ' (transpose)
starts with 1
R, 187 183 151 bytes
function(n){w=which
X=diag(0,n)
X[n,]=m=n:1
while(!min(X)){i=w(!X)[1]
j=w(!!X[-1:-i])
X[i-1+1:j]=max(X)+j:1
X=t(X)[m,]}
`if`(n%%2,t(t(X)[m,])[m,],X)-1}
A clumsier version of rotate and fill!
Factor + math.matrices, 82 79 bytes
[ 2 * { } [ dup length [ m+n flip [ reverse ] map ] keep iota prefix ] repeat ]
Port of @Bubbler's excellent Jelly answer.
R, 84 81 67 bytes
Or R>=4.1, 60 bytes by replacing the word function with a \.
Edit: -14 bytes thanks to @Giuseppe inspired by @Bubbler's Jelly answer.
function(n){m=t(1)
while(T<n)m=rbind(1:n,(T=nrow(m))+t(m[T:1,]))
m}
Uses the common "rotate and add a row on top" approach.
R, 78 bytes
function(n)matrix(order(cumsum(rep(rep(c(n,1,-n,-1),,x<-2*n-1),n-1:x%/%2))),n)
Direct construction of the matrix, no rotations required.
APL (Dyalog Unicode), 18 17 16 bytes
(⍉⍳⍨,⊖+≢)⍣2⍣⎕⊤⍨⍬
Full program. TIO uses ⍵ instead of ⎕ for easier test case demonstration. For the core algorithm, refer to my Jelly answer.
The only additional trick here is the ⊤⍨⍬, which is one of the shortest expressions that give a 0-by-0 matrix (0 0⍴0). This one in particular is handy because it doesn't mess up by stranding with the input value.
-1 byte using ⍳∘≢ → ⍳⍨; the rows are guaranteed to be distinct, so finding indices of items in itself gives the vector of indices for the leading axis.
Also -1 byte by moving ⍉ to the end of the train to save a ∘. Add first row to a transposed matrix == Add first column and then transpose it.
MATL, 12 11 bytes
UG1YL-GoQ&P
MATL (like MATLAB) has a spiral matrix which spirals clockwise from the center, so this performs the necessary flips and subtracts the matrix from N^2.
Probably Luis Mendo knows how to golf this... Thanks to Luis Mendo for −1 byte.
% Implicit input N
U % Square
G1YL % Push the N×N spiral matrix (S)
% clockwise from the center, starting at 1
- % N^2 - S, element-wise
GoQ % Push mod(N,2)+1
&P % Flip along that dimension:
% for odd N, flips the rows; for even N, flips the columns
% Implicit output
Python, 73 bytes (@ovs)
f=lambda n,m=0,p=-1:n*[n]and((*range(m,n),),*zip(*f(2*n-m+p,n,~p)[::-1]))
Old Python, 74 bytes (@DialFrost)
f=lambda n,m=0,p=-1:n and((*range(m,n),),*zip(*f(2*n-m+p,n,~p)[::-1]))or()
Old Python, 76 bytes
f=lambda n,m=0,p=-1:n>m and((*range(m,n),),*zip(*f(2*n-m+p,n,~p)[::-1]))or()
-15 by reversing order of recursion.
Old Python, 91 bytes
lambda n:g((n*n-1,)) g=lambda*s:(l:=s[0][0])and g((*range(l-len(s),l),),*zip(*s[::-1]))or s
Builds the spiral from inside to out by recursively rotating 90° and adding a row on the top.
05AB1E, 13 bytes
¯I·FāUøí¬g+Xš
1-based.
Port of @Bubbler's Jelly answer, so make sure to upvote him as well!
Try it online or verify all test cases.
Explanation:
¯ # Start with an empty list []
I· # Push the input and double it
F # Pop and loop that many times:
ā # Push a list in the range [1,length] (without popping the matrix)
U # Pop and store this list in variable `X`
øí # Rotate the matrix 90 degrees clockwise:
ø # Zip/transpose; swapping rows/columns
í # Reverse each row
¬ # Push the first row (without popping the matrix)
g # Pop and push its length
+ # Add that to each value in the matrix
Xš # Prepend `X` as first row
# (after the loop, the resulting matrix is output implicitly)
Charcoal, 48 41 40 bytes
F⊗N≔⁺⟦Eυλ⟧E∧υ⌊υ⁺LυE⮌υ§μλυEυ⪫Eι◧IλL⌈Eυ⌈ν
Try it online! Link is to verbose version of code. Edit: Saved 4 bytes by porting @Bubbler's observation that you can vectorised add the current length of the array to all of its elements on each iteration, 3 bytes by special-casing an empty array to avoid having to perform the first step manually, and 1 byte by golfing my rotation code. Explanation:
F⊗N
Repeat 2n times.
≔⁺⟦Eυλ⟧E∧υ⌊υ⁺LυE⮌υ§μλυ
Rotate the spiral while adding its length to it values and prefix an additional row of numbers from 0 up to its length. (Unfortunately Charcoal won't let me vectorised add the length to the whole matrix at once but fortunately I can at least do it a row at a time as part of the rotation.) Also handle the edge case of the initially empty spiral which produces a zero-length array.
Eυ⪫Eι◧IλL⌈Eυ⌈ν
Display the final spiral as a grid.
BQN, 29 bytesSBCS
{⍉⌽∘⍉∘∾´≍¨⌽(/«⥊2↕↕𝕩+1)⊔⌽↕𝕩⋆2}
A port of Bubbler's Jelly answer comes in at 20 bytes:
{(⊒˜∾⍉∘⌽+≠)⍟2⍟𝕩↕0‿0}
JavaScript (ES7), 111 101 bytes
Saved 9 bytes thanks to @tsh
Returns a matrix. The results are 1-indexed.
n=>[...Array(n)].map((x=-n/2,y,a)=>a.map(_=>n*n-(i=4*(++x*x>y*y?x:y)**2)+(x>y||-1)*(i**.5+x+y),y+=x))
JavaScript (Node.js), 91 bytes
f=(n,s=[[n*n-1]],[l]=t=s[0])=>l?f(n,[0,...t].map((_,i)=>s.map(r=>r[i-1]||--l).reverse())):s
A port of loopy walt's Python answer. Although I don't really understand what happening.
Jelly, 13 bytes
⁸JW;ṚZ+LƲƲ2¡¡
A nilad function or full program that takes a number from stdin and returns the 1-based involute of size n × n.
How it works
⁸JW;ṚZ+LƲƲ2¡¡
⁸ Empty list ([])
2¡¡ Take n from stdin and repeat 2n times starting from the above:
Given previous matrix m,
ṚZ+LƲ Rotate m and add the number of rows of m
JW; Ʋ Prepend a row of 1..(number of rows of m)
The involute can be constructed iteratively as follows:
Start with m = [] (think of it as 0-row, 0-col matrix)
Repeat 2n times:
If m has r rows, add r to every cell of m
Rotate m 90deg clockwise
Attach 0..r-1 (or 1..r) as a new row at the top of m
After every step, the matrix m is always an involute for some rectangular size (square at even steps). For example, using 1-based indexing, doing a single step on
1 2 3
8 9 4
7 6 5
gives
1 2 3
10 11 4
9 12 5
8 7 6
and then
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
Jelly, 34 33 32 bytes
I would have thought Jelly would be better at this, maybe a more mathematical approach will triumph?
ŒMḢḢ
+þ`¬ZṚ$ṛ¬Ç$¦€Ç¦‘ɼ$ḣÇȦƊ?ƬȦƇṂ
A monadic Link accepting a positive integer that yields a list of lists of positive integers (top-left 1 option).
How?
Start with an \$N\times N\$ table of zeros, then repeatedly either fill in the next number in the first zero of the first row that contains a maximal value, unless that row is filled in which case rotate. This process terminates with a full table but rotated further than we want, so we collect all the states along the way then pick the one we need out (using ȦƇṂ).
ŒMḢḢ - Helper Link: list of list of integers (current state)
ŒM - multidimensional indices of maximal elements
Ḣ - head
Ḣ - head -> row index containing the maximum value
+þ`¬ZṚ$ṛ¬Ç$¦€Ç¦‘ɼ$ḣÇȦƊ?ƬȦƇṂ - Link: positive integer, N
+þ` - [1..N] addition table with [1..N]
¬ - logical NOT -> N×N table of zeros
Ƭ - collect inputs while distinct applying:
? - if...
Ɗ - ...condition: last three links as a monad:
Ç - call our helper link
ḣ - head (the current state) to that index
Ȧ - all truthy when flattened?
$ - ...then: last two links as a monad:
Z - transpose
Ṛ - reverse
- this rotates when we've finished a row
$ - ...else: last two links as a monad:
ɼ - apply to the register (initially 0) & yield:
‘ - increment
¦ - sparse application...
Ç - ...to indices: call our helper link
€ - ...apply: for each:
¦ - sparse application...
$ - ...to indices: last two links as a monad:
¬ - logical NOT (vectorises)
Ç - call our helper link
ṛ - ...apply: the incremented register value
Ƈ - filter keep those for which:
Ȧ - all truthy when flattened?
Ṃ - minimum (of the rotate tables we have left)
Another approach, but even more lengthy at 39:
RµṚĖm€0F;Ɱ"ḊṚ’$ṖṚ4ƭ³’Ḥ¤Ð¡UÐeẎIƇŒṬ€×"J$S
This one works by building a list of the two-dimensional indices ordered by their final value then composing the table by adding up tables that are all zeros except the bottom-rightmost entry which is the number we want there in the end.
JavaScript (Node.js), 108 bytes
n=>[...Array(n)].map((_,Y,a)=>a.map(g=(y=Y,x,_,s=n)=>y?--s-x?s-y?x?s*4+g(y-1,x-1,_,s-1):4*s-y:3*s-x:s+y:x));