Verificar cuadrado mágico

10

Un cuadrado mágico es una matriz cuadrada de números con el lado n que consiste en los enteros positivos distintos 1, 2, ..., dispuestos de manera tal que la suma de los n números en cualquier línea diagonal horizontal, vertical o principal es siempre el mismo número, que se conoce como la constante mágica.

Su programa debe ingresar, a través de std-in, un número que especifique la longitud del lado de su cuadrado, luego los números en el cuadrado. No se pueden usar números más de una vez, no se puede usar un número mayor que n ², y todos los números deben ser mayores que 0. El programa debe determinar si esa combinación de números es un cuadrado mágico.

Wrzlprmft
fuente

Respuestas:

4

CJam, 47 39 35 33 31 bytes

l~/{_1fb_,Y${\(_@=\}%:++\z}2*;=

Toma entrada como

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

Salidas 1si cuadrado mágico, de lo 0contrario.

Cómo funciona :

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";

Esto se puede jugar más al golf.

Pruébalo en línea aquí

Optimizador
fuente
6

Python 2: 132 caracteres

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])})

Un ejemplo de ejecución:

STDIN: 4,[16,3,2,13,5,10,11,8,9,6,7,12,4,15,14,1]
Output: True

Hay dos cosas para verificar:

  1. Las sumas son las filas, columnas y diagonales, todas iguales
  2. Los elementos son una permutación de [1,2,...,n*n].

El primero se verifica tomando sumas de sectores correspondientes a estos subconjuntos. Cada fila, columna o diagonal se describe por su valor inicial y su desplazamiento. Tomamos el corte correspondiente de la lista, truncamos a nelementos y lo sumamos. En la [start:end:step]notación de Python , las filas son [r*n::1], las columnas son [c::n]y las dos diagonales son [0::n+1]y [n-1::n-1]. Estos se almacenan como una lista de 2*n+2pares producidos por zip.

Tomamos los conjuntos de sumas y verificamos que tenga una longitud 1. Además, clasificamos la entrada y verificamos que sea la lista. [1,2,...,n*n].En realidad, combinamos ambos en una verificación multiplicando sorted(l)por la longitud de los conjuntos de suma, una verificación que siempre falla a menos que el conjunto de suma tenga longitud 1.

xnor
fuente
Me di cuenta de que puede codificar un par de manera (i,j)más eficiente como un solo número x, tomando i=x%Cy j=x/Cpara algunos lo suficientemente grande C. Podría darle una oportunidad más tarde.
xnor
5

APL, 35

∧/2=/(+⌿x,⍉x),+/↑1 1∘⍉¨x(⌽x←⎕⍴⍨,⍨⎕)

La explicación
x←⎕⍴⍨,⍨⎕ solicita entrada, dale forma de matriz y asigna a x
Invierte la matriz de izquierda a derecha
x(...)Crea una matriz de matrices: xe xinvierte
1 1∘⍉¨Para cada una de esas matrices, toma la diagonal en
+/↑forma de matriz 2 × n de los números en esas diagonales y suman las filas

⍉xTransponer x
x,luego concatenar con xpara formar una matriz × 2n
+⌿y sumar las columnas

(+⌿x,⍉x),+/↑1 1∘⍉¨x(⌽x←⎕⍴⍨,⍨⎕)concatenar para formar una matriz de las sumas
2=/verificar si pares consecutivos son iguales
∧/y Y todos esos resultados juntos

TwiNight
fuente
3

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

Toma datos como

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

Cierto

DavidC
fuente
Seguramente hay mucho espacio en blanco que se puede eliminar aquí
Beta Decay
Se puede eliminar todo el espacio en blanco. Lo dejé allí por legibilidad. Y no conté espacios en blanco innecesarios.
DavidC
Puede hacer Input[r=Reverse]para guardar un byte. #&@@es un byte más corto que [[1]]. Probablemente, además, puede usar la notación infija Partitionpara otro byte. Y Threaddebería funcionar en lugar de Transpose. Alternativamente, use este carácter Unicode como un operador post arreglo (Mathematica lo usa para el superíndice T para la transposición).
Martin Ender
3

APL 47 32

Usando la excelente solución de TwiNight y aplicando algunos ajustes adicionales:

∧/2=/+⌿(1 1∘⍉∘⌽,1 1∘⍉,⍉,⊢)⎕⍴⍨,⍨⎕

Explicación:

Utiliza los trenes de funciones, que se introdujeron en la v14 del intérprete Dyalog. APL se ejecuta de derecha a izquierda, los ⎕ son entradas, así que primero las dimensiones, luego el vector de números.

⎕⍴⍨, ⍨⎕ crea la matriz NxN

Después de eso viene el tren de funciones, que básicamente es solo una secuencia de funciones (entre paréntesis) aplicadas al argumento correcto. Las funciones son:

⊢ Devuelve el argumento correcto (esa es la matriz)

⍉ Transpone la matriz de argumento correcta

1 1∘⍉ Devuelve la diagonal

1 1∘⍉∘⌽ Devuelve la diagonal de la matriz invertida (horizontalmente)

Todos los resultados se concatenan con la función ","

En este punto, el resultado es una matriz cuyas columnas se suman (+ ⌿). Los valores obtenidos de esta manera se verifican para que sean los mismos con ∧ / 2 = /

Aquí también dejaré mi antigua solución:

{M←⍺ ⍺⍴⍵⋄d←M=⍉M⋄(⊃≡∪)((+/,+⌿)M),+/∘,¨d(⌽d)ר⊂M}

toma la dimensión como argumento izquierdo, el vector de elementos como argumento derecho, por ejemplo:

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

Puede probarse en línea aquí: www.tryapl.org

Moris Zucca
fuente
2

GolfScript 67 ( demo )

~]:q(/q(/zip+[q()/{(\;}%]+[q((/);(;{(\;}%]+{{+}*}%.&,2<q(2?,{)}%-!*
Cristian Lupascu
fuente
2

JavaScript (E6) 194

Usando el aviso para leer la entrada y mostrar la salida.
Prueba en consola con FireFox> 31 (Array.fill es muy nuevo)

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)

Menos golf

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);
edc65
fuente
2

Pyth, 24 30 bytes

&q1l{sM++JcEQCJm.e@bkd_BJqSlQS

Pruébelo en línea aquí .

&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)

Editar: reparó un error, gracias a @KevinCruijssen por avisarme: o)

Sok
fuente
Esto da como resultado Truecuadrados mágicos con números que son demasiado grandes o no todos únicos. Es decir, 4y [12,26,23,13,21,15,18,20,17,19,22,16,24,14,11,25]o 4y [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]salida de ambos True. (Sin embargo, casi todas las respuestas existentes tienen el mismo problema, pero como se publicaron hace más de 4 años, no me molesté en corregir sus errores en un comentario)
Kevin Cruijssen
@KevinCruijssen Maldición, me concentré tanto en verificar las sumas que me olvidé de los otros requisitos ... Soy un tonto
Sok
1

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)
jawo
fuente
1

05AB1E , 24 bytes

ô©O®øO®Å\O®Å/O)˜Ë²{¹nLQ*

Formato de entrada: 4\n[2,16,13,3,11,5,8,10,7,9,12,6,14,4,1,15]. Salidas 1/ 0para veracidad / falsey respectivamente.

Pruébelo en línea o verifique algunos casos de prueba más .

Explicación:

ô       # 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]]
 ©      # Store it in the register (without popping)
  O     # Take the sum of each row
        #  i.e. [[2,16,13,3],[11,5,8,10],[7,9,12,6],[14,4,1,15]] → [34,34,34,34]
®       # Push the matrix from the register again
 ø      # Zip/transpose; swapping rows/columns
        #  i.e. [[2,16,13,3],[11,5,8,10],[7,9,12,6],[14,4,1,15]]
        #   → [[2,11,7,14],[16,5,9,4],[13,8,12,1],[3,10,6,15]]
  O     # Sum each inner list again
        #  i.e. [[2,11,7,14],[16,5,9,4],[13,8,12,1],[3,10,6,15]] → [34,34,34,34]
®       # Push the matrix from the register again
 Å\     # Get the top-left to bottom-right main diagonal of it
        #  i.e. [[2,16,13,3],[11,5,8,10],[7,9,12,6],[14,4,1,15]] → [2,5,12,15]
   O    # Sum it together
        #  i.e. [2,5,12,15] → 34
®       # Push the matrix from the register again
 Å/     # Get the top-right to bottom-left main diagonal of it
        #  i.e. [[2,16,13,3],[11,5,8,10],[7,9,12,6],[14,4,1,15]] → [3,8,9,14]
   O    # Sum it together
        #  i.e. [3,8,9,14] → 34
)       # Wrap everything on the stack into a list
        #  → [[34,34,34,34],[34,34,34,34],34,34]
 ˜      # Flatten this list
        #  i.e. [[34,34,34,34],[34,34,34,34],34,34] → [34,34,34,34,34,34,34,34,34,34]
  Ë     # Check if all values are equal to each other
        #  i.e. [34,34,34,34,34,34,34,34,34,34] → 1 (truthy)
²       # Push the second input again
 {      # Sort it
        #  i.e. [2,16,13,3,11,5,8,10,7,9,12,6,14,4,1,15]
        #  → [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
        #  i.e. 4 → 16
    L   # Create a list in the range [1, squared_input]
        #  i.e. 16 → [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
     Q  # Check if the two lists are equal
        #  i.e. [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
        #   and [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] → 1 (truthy)
*       # Check if both checks are truthy by multiplying them with each other
        #  i.e. 1 and 1 → 1
        # (and output the result implicitly)
Kevin Cruijssen
fuente