| Bytes | Lang | Time | Link |
|---|---|---|---|
| 2018 | 05AB1E | 190121T110435Z | Kevin Cr |
| 033 | K ngn/k | 210101T210707Z | coltim |
| 027 | Husk | 201005T135202Z | Razetime |
| 030 | Pyth | 190121T143612Z | Sok |
| 035 | APL | 141021T093217Z | TwiN |
| 031 | CJam | 141017T153634Z | Optimize |
| 032 | APL | 141021T091411Z | Moris Zu |
| 186 | LUA 186 Chars | 141021T080358Z | jawo |
| 194 | JavaScript | 141018T142449Z | edc65 |
| nan | 141018T153105Z | Cristian | |
| 125 | Mathematica | 141017T163140Z | DavidC |
| 132 | Python 2 | 141017T052057Z | xnor |
05AB1E, 24 21 20 (or 18) bytes
If the size of the input-list can be irregular:
ôDøí‚D€Å\‚O˜Ë²{¹nLQ*
Inputs in the order: \$n,list\$, on separated STDIN lines. Outputs 1/0 for truthy/falsey respectively.
Try it online or verify some more test cases.
If the size of the input-list is guaranteed to be of length \$n^2\$:
ôDøí‚D€Å\‚O˜Ë²{āQ*
Same I/O.
Try it online or verify some more test cases.
Explanation:
ô # Split the 2nd (implicit) input into parts of a size of the 1st
# (implicit) input
# i.e. [2,16,13,3,11,5,8,10,7,9,12,6,14,4,1,15] and 4
# → [[2,16,13,3],[11,5,8,10],[7,9,12,6],[14,4,1,15]]
D # Duplicate this matrix
øí # Rotate the copy once clockwise:
ø # Zip/transpose; swapping rows/columns
# → [[2,11,7,14],[16,5,9,4],[13,8,12,1],[3,10,6,15]]
í # Reverse each inner row
# → [[14,7,11,2],[4,9,5,16],[1,12,8,13],[15,6,10,3]]
‚ # Pair the two matrices together
# → [[[2,16,13,3],[11,5,8,10],[7,9,12,6],[14,4,1,15]],
# [[14,7,11,2],[4,9,5,16],[1,12,8,13],[15,6,10,3]]]
D # Duplicate the pair of matrices
€ # Map over both matrices in the duplicated pair:
Å\ # Get the top-left to bottom-right main diagonal of it
# → [[2,5,12,15],[14,9,8,3]]
‚ # Pair the two together
# → [[[[2,16,13,3],[11,5,8,10],[7,9,12,6],[14,4,1,15]],
# [[14,7,11,2],[4,9,5,16],[1,12,8,13],[15,6,10,3]]],
# [[2,5,12,15],[14,9,8,3]]]
O # Take the sum of each inner-most list:
# → [[[34,34,34,34],[34,34,34,34]],[34,34]]
˜ # Flatten this list
# → [34,34,34,34,34,34,34,34,34,34]
Ë # Check if all values are equal to each other
# → 1 (truthy)
² # Push the second input again
{ # Sort it
# → [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
¹n # Push the first input again, and take its square
# → 16
L # Create a list in the range [1, squared_input]
# → [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
Q # Check if the two lists are equal
# → 1 (truthy)
* # Check if both checks are truthy by multiplying them with each other
# → 1 (truthy)
# (after which the result is output implicitly)
ā # Push a list in the range [1,length] (without popping the list)
# → [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
# (the rest is the same)
K (ngn/k), 36 33 bytes
-3 bytes from improvements by @ngn
{1=#?{+/x,'x@'!#x}'(|+:)\(x,x)#y}
May be non-qualifying, as this is a function taking two args; the length of the square, and a list of the square's values.
(x,x)#ybuildx-by-xmatrix of the values fromy(|+:)\build list of all rotations of the matrix{...}'inner lambda, called on each rotationx@'!#xget the main diagonal elementsx,'xzip them with the original values+/take the column-wise sum (the last column being the main diagonal)
1=#?is there only one distinct sum?
Husk, 27 bytes
&=O¹ḣ□³Λ=mΣ+mo►L∂Se↔C³¹S+TC
I don't know any other techniques to golf this further, but it would be really cool if I could get it any lower.
Explanation coming later.
Takes inputs as 2 command line args, since Husk does not have the feature of taking from STDIN.
Pyth, 24 30 bytes
&q1l{sM++JcEQCJm.e@bkd_BJqSlQS
Try it online here.
&q1l{sM++JcEQCJm.e@bkd_BJqSlQSQ Implicit: Q = evaluated 1st input (contents), E = evaluated 2nd input (side length)
Trailing Q inferred
cEQ Chop E into pieces or length Q
J Store in J
_BJ Pair J with itself with rows reversed
m Map the original and it's reverse, as d, using:
.e d Map each row in d, as b with index k, using:
@bk Get the kth element of b
The result of this map is [[main diagonal], [antidiagonal]]
+J Prepend rows from J
+ CJ Prepend columns from J (transposed J)
sM Sum each
{ Deduplicate
l Length
q1 Is the above equal to 1?
& Logic AND the above with...
SlQ ... is the range [1-length(Q)]...
q ... equal to...
SQ ... sorted(Q)
Edit: fixed a bug, thanks to @KevinCruijssen for letting me know :o)
APL, 35
∧/2=/(+⌿x,⍉x),+/↑1 1∘⍉¨x(⌽x←⎕⍴⍨,⍨⎕)
Explanation
x←⎕⍴⍨,⍨⎕ prompts for input, shape it into a matrix, and assign to x
⌽ Reverses the matrix left-to-right
x(...) Create a array of matrices: x and x reverse
1 1∘⍉¨ For each of those matrices, take the diagonal
+/↑ form a 2×n matrix of the numbers on those diagonals and sum the rows
⍉x Transpose x
x, then concatenate with x to form a n×2n matrix
+⌿ and sum the columns
(+⌿x,⍉x),+/↑1 1∘⍉¨x(⌽x←⎕⍴⍨,⍨⎕) concatenate to form an array of the sums
2=/ check if consecutive pairs equal
∧/ and AND together all those results
CJam, 47 39 35 33 31 bytes
l~/{_1fb_,Y${\(_@=\}%:++\z}2*;=
Takes input like
4 [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
Outputs 1 if magic square, 0 otherwise.
How it works:
l~/ "Evaluates the input and split the array into chunks"
"of size N where N is the first integer";
{ }2* "Run this code block 2 times";
_1fb "Copy the 2D array and calculate sum of each row of copy";
_, "Copy the array containing sum of each row and get"
"its length. This is equal to N";
Y${ }% "Run this code block for each array of the original"
"2D array that we copied from stack";
\(_ "Put the length number to top of stack, decrement and"
"copy that";
@=\ "Take the element at that index from each row and put"
"N back behind at second position in stack";
:+ "Take sum of elements of the array. This is sum of"
"one of the diagonals of the 2D array";
+ "Push diagonal sum to row sum array";
\z "Bring original array to top and transpose columns";
; "At this point, the stack contain 3 arrays:"
" Array with sum of rows and main diagonal,"
" Array with sum of columns and secondary diagonal and"
" The original array. Pop the original array";
= "Check if sum of rows + main diagonal array is equal to ";
"sum of columns + secondary diagonal array";
This can be golfed further.
APL 47 32
Using TwiNight's excellent solution and applying some more tweaking:
∧/2=/+⌿(1 1∘⍉∘⌽,1 1∘⍉,⍉,⊢)⎕⍴⍨,⍨⎕
Explanation:
This uses function trains, which were introduced in v14 of the Dyalog interpreter. APL is executed from right to left, ⎕'s are inputs, so first the dimensions, then the vector of numbers.
⎕⍴⍨,⍨⎕ creates the matrix NxN
After that comes the function train which are basically just a sequence of functions (between brackets) applied to the right argument. The functions are:
⊢ Returns just right argument (that is the matrix)
⍉ Transposes the right argument matrix
1 1∘⍉ Returns the diagonal
1 1∘⍉∘⌽ Returns the diagonal of the reversed (horizontally) matrix
All the results are concatenated with the function ","
At this point, the result is a matrix whose columns are then summed (+⌿). The values obtained this way are then checked to be the same with ∧/2=/
I'll leave my old solution here too:
{M←⍺ ⍺⍴⍵⋄d←M=⍉M⋄(⊃≡∪)((+/,+⌿)M),+/∘,¨d(⌽d)ר⊂M}
takes dimension as left argument, vector of elements as right argument, for example:
4{M←⍺ ⍺⍴⍵⋄d←M=⍉M⋄(⊃≡∪)((+/,+⌿)M),+/∘,¨d(⌽d)ר⊂M}16 3 2 13 5 10 11 8 9 6 7 12 4 15 14 1
1
Can be tried online here: www.tryapl.org
LUA 186 Chars
s=io.read(1)v=io.read(2)d=0 r=0 for i=1,#s do t=0 for j = 1, #s do t=t+s[i][j]end d=d+s[i][i] r=r+s[i][#s-i+1]if t ~= v then o=true end end if d~=v and r~= v then o=true end print(not o)
JavaScript (E6) 194
Using prompt to read input and display output.
Test in console with FireFox >31 (Array.fill is very new)
z=(p=prompt)(n=p()|0).split(' '),u=Array(2*n).fill(e=d=n*(n*n+1)/2),z.map((v,i)=>(r=i/n|0,u[r+n]-=v,u[c=i%n]-=v,d-=v*(r==c),e-=v*(r+c+1==n))),o=!(e|d|u.some(v=>v)),z.sort((a,b)=>a-b||(o=0)),p(o)
Less golfed
n = prompt()|0; // input side length
z = prompt().split(' '); // input list of space separeted numbers
e = d = n*(n*n+1)/2; // Calc sum for each row, column and diagonal
u = Array(2*n).fill(e), // Init check values for n rows and n columns
z.map( (v,i) => { // loop on number array
r = i / n | 0; // row number
c = i % n; // column number
u[r+n] -= v; // subtract current value, if correct it will be 0 at loop end
u[c] -= v;
if (r==c) d -= v; // subtract if diagonal \
if (r+c+1==n) e -=v; // subtract if diagonal /
}),
o=!(e|d|u.some(v=>v)); // true if values for rows, cols and diags are 0
z.sort((a,b)=>a-b||(o=0)); // use sort to verify if there are repeated values in input
alert(o);
GolfScript 67 (demo)
~]:q(/q(/zip+[q()/{(\;}%]+[q((/);(;{(\;}%]+{{+}*}%.&,2<q(2?,{)}%-!*
Mathematica 128 125
d = Diagonal; r = Reverse; i = Input[];
Length@Union[Tr /@ Join[p = Partition[i[[2]], i[[1]]],
t = Transpose@p, {d@p}, {d@t}, {d@r@p}, {d@r@t}]] == 1
Takes input such as
{4,{16, 3, 2, 13, 5, 10, 11, 8, 9, 6, 7, 12, 4, 15, 14, 1}}
True
Python 2: 132 chars
n,l=input()
r=range
print r(1,n*n+1)==sorted(l)*len({sum(l[i::j][:n])for(i,j)in zip(r(n)+r(0,n*n,n)+[0,n-1],[n]*n+[1]*n+[n+1,n-1])})
An example run:
STDIN: 4,[16,3,2,13,5,10,11,8,9,6,7,12,4,15,14,1]
Output: True
The are two things to check:
- The sums are the rows, columns, and diagonals are all equal
- The elements are a permutation of
[1,2,...,n*n].
The first is checked by taking sums of slices corresponding to these subsets. Each row, column, or diagonal is described by its starting value and its displacement. We take the list corresponding slice, truncate to n elements, and sum it. In Python's [start:end:step] notation, rows are [r*n::1], columns are [c::n] and the two diagonals are [0::n+1] and [n-1::n-1]. These are stored as a list of 2*n+2 pairs produced by zip.
We take the sets of sums and check that it has length 1. Also, we sort the input and check that it is the list [1,2,...,n*n]. Actually, we combine both into one check by multiplying sorted(l) by the length of the sum-sets, a check that always fails unless the sum-set has length 1.