Produce el cuadrado mágico de Durero


14

El reto

Imprime una matriz o una representación de cadena del famoso cuadrado mágico de Durero :

ingrese la descripción de la imagen aquí

es decir,

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

Algunas propiedades de este cuadrado, que tal vez puedan explotarse, son:

  • Contiene cada número entero de 1que 16exactamente una vez
  • La suma de cada columna o fila, así como la suma de cada una de las dos diagonales, es la misma. Esta es la propiedad definitoria de un cuadrado mágico . La suma es la constante mágica del cuadrado.
  • Además, para este cuadrado en particular, la suma de cada uno de los cuatro cuadrantes también es igual a la constante mágica, al igual que la suma de los cuatro cuadrados del centro y la suma de los cuatro cuadrados de la esquina.

Reglas

Bultins que generan cuadrados mágicos no están permitidos (como los de Matlab magico Mathematica MagicSquare). Se puede usar cualquier otro incorporado.

El código puede ser un programa o una función.

No hay entrada

Los números deben estar en la base 10. El formato de salida es flexible como de costumbre. Algunas posibilidades son:

  • Una matriz anidada (salida de función o su representación de cadena, con o sin separadores, cualquier tipo de paréntesis coincidentes):

    [[16, 3, 2, 13], [5, 10, 11, 8], [9, 6, 7, 12], [4, 15, 14, 1]]
    
  • Una matriz 2D:

    {16, 3, 2, 13; 5, 10, 11, 8; 9, 6, 7, 12; 4, 15, 14, 1}
    
  • Una matriz de cuatro cadenas, o una cadena que consta de cuatro líneas. Los números pueden estar alineados a la derecha

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

    o alineado a la izquierda

    16 3  2  13
    5  10 11  8
    9  6  7  12
    4  15 14  1
    
  • Una cadena con dos separadores diferentes para fila y columna, como

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

El formato de salida debe diferenciar claramente las filas y columnas. Por ejemplo, no está permitido generar una matriz plana o una cadena con todos los números separados por espacios.

Código de golf. Las victorias más cortas.



44
Curiosamente, los números 5, 8, 9 y 12 están en sus posiciones (1 indexado), 6, 7, 10 y 11 se han reflejado verticalmente, 2, 3, 14 y 15 se han reflejado horizontalmente y 1, 4, 13 y 16 han sido rotados 180 °. Sin embargo, dudo que eso ayude a alguien.
Neil

2
Observación posiblemente útil: si disminuye 1 de cada número, puede generar el cuadrado comenzando con la matriz [15], luego concatenando repetidamente con su reverso con cada elemento XORed por 13, 3, 8 y 15, respectivamente.
ETHproductions

66
Esto parece bastante difícil de comprimir en idiomas que no son de golf. Creo que un cuadrado mágico más grande hubiera sido mejor.
xnor

1
Estoy bastante seguro de que cada rotación o reflexión del cuadrado tendría las mismas propiedades.
Dennis

Respuestas:


7

Jalea , 15 bytes

“¡6ṡƘ[²Ḳi<’ḃ⁴s4

TryItOnline!

Bastante aburrido, lo siento:

Prep: Tomó el cuadrado, lo leyó por filas, lo convirtió de la base biyectiva 16, lo convirtió a la base 250, buscó los índices de la página de códigos para esos "dígitos" ( ¡6ṡƘ[²Ḳi<).

Jelly luego lee los índices para formar un número base 250, se convierte en base biyectiva 16 ( ḃ⁴) y se divide en trozos de tamaño 4 ( s4).


Si se nos permite emitir una orientación diferente, es posible al revés en 14 :

“#⁷ƙ¤ṆWȷỤ’ḃ⁴s4

Prueba


En teoría, dada la memoria suficiente para 16!enteros, lo siguiente nos daría la orientación correcta en 14 :

⁴Œ!“ŒCġŀḌ;’ịs4

Esto crearía todas las permutaciones de [1,16] con ⁴Œ!y seleccionaría el valor en el índice 19800593106060 (basado en 1) usando la representación de base 250 ŒCġŀḌ;y la dividiría en trozos de longitud 4 con s4.


Desde entonces he añadido cuatro nuevos átomos ( Œ?, Œ¿, œ?, y œ¿) a la jalea para abordar dichas situaciones.
La mónada Œ?toma un número entero (o iterable de enteros) y devuelve la permutación más corta posible de números naturales en ejecución que tendrían el índice (o índices) dado en una lista de listas ordenadas lexicográficamente de todas las permutaciones de esos números.
... y lo hace sin crear ninguna lista de permutación.
Como tal, el siguiente sería ahora trabajar por 12 (obviamente no competitivo):

“ŒCġŀḌ;’Œ?s4

¡Darle una oportunidad!


Esto debería ser más corto en su tenedor Jelly (que me había olvidado hasta ahora, lo siento).
Dennis

¿Oh? ¿Cómo crees que?
Jonathan Allan el

8

Pyth, 18 bytes

c4.PC"H#ût"_S16

Ejecuta el código.

c4.PC"H#ût"_S16

    C"H#ût"       Convert the packed string to the number 1122196781940
  .P       _S16   Take that-numbered permutation of the reversed range [16,15,...,1]
c4                Chop into piece of length 4

Revertir el rango estaba destinado a reducir el índice de permutación, ya que la salida comienza con 16, pero creo que solo llegó a un punto de equilibrio.

Esto superó una estrategia más aburrida de convertir la tabla directamente a la base 17 y luego una cadena ( enlace ) de 20 bytes:

c4jC"úz(ás¸H"17 

7

Jalea , 16 15 bytes

4Œ!.ịm0µZḂÞ’×4+

Pruébalo en línea!

Antecedentes

Si restamos 1 de los números en el cuadrado y los dividimos por 4 (calculando el cociente y el resto), se hace evidente un patrón.

quotients and remainders    quotients    remainders

   3 3  0 2  0 1  3 0        3 0 0 3      3 2 1 0
   1 0  2 1  2 2  1 3        1 2 2 1      0 1 2 3
   2 0  1 1  1 2  2 3        2 1 1 2      0 1 2 3
   0 3  3 2  3 1  0 0        0 3 3 0      3 2 1 0

La matriz restante sigue un patrón obvio y es fácil de generar. La matriz del cociente se puede obtener transponiendo la matriz restante e intercambiando las filas del medio.

Cómo funciona

4Œ!.ịm0µZḂÞ’×4+  Main link. No arguments.

4Œ!              Compute the array of all permutations of [1, 2, 3, 4], in
                 lexicographical order.
   .ị            Take the permutations at the indices adjacent to 0.5, i.e., the
                 ones at indices 0 ([4, 3, 2, 1]) and 1 ([1, 2, 3, 4]).
     m0          Concatenate the resulting [[4, 3, 2, 1], [1, 2, 3, 4]] with a
                 reversed copy, yielding the matrix
                 M := [[4, 3, 2, 1], [1, 2, 3, 4], [1, 2, 3, 4], [4, 3, 2, 1]].
       µ         Begin a new, monadic chain. Argument: M
        Z        Zip/transpose M, yielding the matrix
                 [[4, 1, 1, 4], [3, 2, 2, 3], [2, 3, 3, 2], [1, 4, 4, 1]].
         ḂÞ      Sort the rows by the lexicographical order of their parities,
                 yielding [[4, 1, 1, 4], [2, 3, 3, 2], [3, 2, 2, 3], [1, 4, 4, 1]].
           ’     Subtract 1 to yield the matrix of quotients, i.e.,
                 [[3, 0, 0, 3], [1, 2, 2, 1], [2, 1, 1, 2], [0, 3, 3, 0]].
            ×4+  Multiply the quotient by 4 and add the result to M (remainders).

5

J, 37 27 bytes

¡Ahorró 10 bytes gracias a millas!

4 4$1+19800593106059 A.i.16

Ahora con menos aburrido! Esto toma la 19800593106059permutación de la lista i.16, que es 15 2 1 12 4 9 10 7 8 5 6 11 3 14 13 0. Luego, eso se incrementa, luego se forma en un 4by4 lista .

Versión alternativa, sin espacios en blanco:

_4]\1+19800593106059&A.i.16

Salida, para la posteridad:

   _4]\1+19800593106059&A.i.16
16  3  2 13
 5 10 11  8
 9  6  7 12
 4 15 14  1
   4 4$1+19800593106059 A.i.16
16  3  2 13
 5 10 11  8
 9  6  7 12
 4 15 14  1

Creo que _4]\1+19800593106059&A.i.16funciona, pero podría acortarse posiblemente
millas

@miles oo, buen uso de A.. ¿Cómo encontraste ese número?
Conor O'Brien

Monadic A.encuentra el índice de permutación de una permutación de índice cero
millas

@miles eh. Supongo que debería aprender un poco más sobre esas funciones entonces.
Conor O'Brien el

4

05AB1E , 18 17 bytes

¡Gracias a Emigna por guardar un byte!

•3øѼž·Üý;•hSH>4ô

Utiliza la codificación CP-1252 . Pruébalo en línea!


Incrementar antes de fragmentar ahorra un byte ( >4ô).
Emigna

@Emigna Ahh, por supuesto! ¡Gracias! :)
Adnan

4

Ruby, 49 bytes (¡más corto que la solución ingenua!)

¡Se necesitaron bastantes intentos para escribir un fragmento de este desafío en un lenguaje convencional que fuera más corto de lo que se evaluó! Según las reglas habituales, he hecho un programa agregando unp para generarlo.

p [15,4,8,3].map{|i|[1+i,1+i^=13,1+i^=3,1+i^=13]}

Produce (la representación de cadena de) una matriz de matrices. Es más largo que la solución Ruby de wat que genera una cadena con un formato diferente, pero un byte más corto que el programa ingenuo a continuación que simplemente devuelve la matriz literal.

p [[16,3,2,13],[5,10,11,8],[9,6,7,12],[4,15,14,1]] #naive solution, 50 bytes
p [15,4,8,3].map{|i|[1+i,1+i^=13,1+i^=3,1+i^=13]}  #submission, 49 bytes

Explicación: comience con los números 0..15 (38 bytes!)

Aquí es donde empecé y es mucho más fácil. Si convertimos el cuadrado 0..15 en binario, notamos que cada celda contiene el valor en la parte inferior de su columna XORed con el valor en el lado derecho de su fila:

15 2  1  12            1111 0010 0001 1100
4  9  10 7             0100 1001 1010 0111
8  5  6  11            1000 0101 0110 1011
3  14 13 0             0011 1110 1101 0000

De esto derivamos el siguiente código. Pero al usar la primera columna en lugar de la última columna, guardamos un byte, como se muestra.

p [12,7,11,0].map{|i|[i^3,i^14,i^13,i]}            #0..15 square, 39 bytes         
p [15,4,8,3].map{|i|[i,i^13,i^14,i^3]}             #0..15 square, 38 bytes

La versión requerida de 1..16 fue más difícil. Al final me di cuenta de que la forma de hacerlo era agregar 1 a cada celda del cuadrado 0..15. Pero como ^tiene menor prioridad de la +que necesitaba muchos paréntesis, que comían bytes. Finalmente llegué a la idea de usar ^=. El nuevo valor de ise calcula mediante asignación aumentada ^=antes de que se le agregue el 1, por lo que el cálculo se realiza en el orden correcto.


Buena caracterización! Una realización simple en Python es de 6 caracteres anteriores hardcode: for a in 12,7,11,0:print[(a^b)+1for b in 3,14,13,0]. Ganaría si pudiéramos hacer 0 a 15 con for a in 12,7,11,0:print[a^3,a^14,a^13,a].
xnor

3

JavaScript (ES6), 43 bytes

_=>`16,3,2,13
5,10,11,8
9,6,7,12
4,15,14,1`

Separado por nuevas líneas, luego comas. Dudo que haya un camino más corto ...


Sí, este es probablemente el más corto posible.
Conor O'Brien el

2

sed 39 bytes

c16,3,2,13|5,10,11,8|9,6,7,12|4,15,14,1

Pruébalo en línea!

No puede ser mucho más simple que esto. Y, desafortunadamente, tampoco creo que pueda acortarse.


2

Jalea, 20 bytes

“Ѥ£Æ¦½¿®µ©¬€¥ÐÇ¢‘s4

Pruébalo en línea!

Esto simplemente busca el punto de código Jelly de cada personaje, luego se corta en subconjuntos de longitud 4 con s4.


2

DASH , 24 bytes

<|>4tc"................"

Reemplace los puntos con los caracteres de los códigos de barras 16, 3, 2, 13, 5, 10, 11, 8, 9, 6, 7, 12, 4, 15, 14 y 1 respectivamente.

Explicación

Simplemente convierte los caracteres en una serie de códigos de barras y fragmentos por 4.


2

En realidad , 22 bytes

4"►♥☻♪♣◙♂◘○♠•♀♦☼♫☺"♂┘╪

Pruébalo en línea!

Explicación:

4"►♥☻♪♣◙♂◘○♠•♀♦☼♫☺"♂┘╪
 "►♥☻♪♣◙♂◘○♠•♀♦☼♫☺"     push a string containing the numbers in the magic square, encoded as CP437 characters
                   ♂┘   convert to ordinals
4                    ╪  chunk into length-4 slices

2

Groovy, 57 bytes / 46 bytes

"F21C49A7856B3ED0".collect{Eval.me("0x$it")+1}​.collate(4)​

Analice cada uno como dígito hexadecimal y agregue 1, clasifique por 4 en una matriz 2D.

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

Más corto, pero también más tranquilo:

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

2

Javascript ES6, 66 65 55 bytes

Sí, no es el más corto. Y sí, se puede reducir.

_=>`f21c
49a7
856b
3ed0`.replace(/./g,_=>'0x'+_-~0+' ')

Por ahora, no es perfecto. Pero es algo!


Gracias a la sugerencia de @Neil que podría ahorrar 5-8 bytes, y que inspiró a @ETHproductions sugerencia de que ahorra 10 bytes!

Esto hace que la respuesta sea solo 12 bytes más larga que su solución de 43 bytes .


1
Podrías usar en glugar de 0y en su parseInt(c,17)lugar, lo que creo que te ahorra 4 bytes, o puedes usar + 0x${c}|| 16, que creo que te ahorra 5 bytes, y luego puedes restar 1 de todos los dígitos y agregarlo más tarde, que creo que te ahorra otro byte.
Neil

1
Sobre la base de las sugerencias de @ Neil, puede guardar al menos 10 bytes en total .
ETHproductions

@Neil Muchas gracias por la idea. Usar base17 realmente ahorra unos pocos bytes. Realmente es algo en lo que no pensé.
Ismael Miguel

@ETHproductions ¡Muchas gracias por la sugerencia! Todavía estoy tratando de entender cómo funciona. Pero creo que llegaré allí. Ahora, solo necesito acortar 13 bytes para vencerte. Pero parece que su respuesta es la más corta posible en Javascript
Ismael Miguel

1

PowerShell v2 +, 40 bytes

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

Una cadena multilínea literal, dejada en la tubería. La salida a través de lo implícito Write-Outputocurre al finalizar el programa. Agradable y aburrido.


Versión construida, 77 bytes.

'f21c59a7856b3dc0'-split'(....)'-ne''|%{([char[]]$_|%{"0x$_+1"|iex})-join','}

Toma la cadena, -splites cada cuatro elementos, los recorre en bucles, cambia cada uno a un hexadecimal 0x$_y agrega 1, canaliza eso a iex(abreviado Invoke-Expressiony similar a eval), luego -joins el resultado en una cadena con ,el separador. Emite cuatro cadenas en la tubería, con impresión implícita.


1

Ruby, 60 bytes - primer intento

%w(f21c 49a7 856b 3ed0).map{|i|i.chars.map{|i|i.to_i(16)+1}}

Ruby, 45 bytes - barato

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


1

05AB1E , 15 bytes

16Lœ•iPNÍš¯•è4ä

Explicación

16L              # range [1 ... 16]
   œ             # compute all permutations of the range
    •iPNÍš¯•è    # take the permutation at index 19800593106059
             4ä  # split the permutation into 4 parts

El índice de la permutación se encontró usando la fórmula:

a*15! + b*14! + c*13!+ ... + o*1! + p*0!

Donde las variables se reemplazan con el número de elementos sucesivos que son más pequeños que el número en el índice actual para cada número en la lista de destino
[16, 3, 2, 13, 5, 10, 11, 8, 9, 6, 7, 12, 4, 15, 14, 1]

que para nuestra codiciada permutación es
a=15, b=2, c=1, d=10, e=2, f=6, g=6, h=4, i=4, j=2, k=2, l=2, m=1, n=2 o=1, p=0

Esto nos da la fórmula: 15*15!+2*14!+1*13!+10*12!+2*11!+6*10!+6*9!+4*8!+4*7!+2*6!+2*5!+2*4!+1*3!+2*2!+1*1!+0*0!

que es igual a 19800593106059.


1

Matlab 38 35 bytes

Función anónima:

@()['pcbm';'ejkh';'ifgl';'dnoa']-96

Impresión directa (38 bytes):

disp(['pcbm';'ejkh';'ifgl';'dnoa']-96)

En Matlab, la mejor manera de producir una matriz de enteros es a través de una cadena.


El uso de una función anónima ahorraría algunos bytes:@()['pcbm';'ejkh';'ifgl';'dnoa']-96
Luis Mendo

@LuisMendo No noté que el valor de retorno también es aceptable, ¡gracias!
pajonk

1

Scala, 52 bytes

()=>Seq(15,4,8,3)map(x=>Seq(x,x^13,x^14,x^3)map(1+))

Sin golf:

()=>
  Seq(15, 4, 8, 3)
  .map(x=>
    Seq(x, x^13, x^14, x^3)
    .map(1+)
  )

Inspirado por el nivel del río San respuesta rubí .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.