Produza o quadrado mágico de Dürer


14

O desafio

Saída de uma representação de matriz ou string do famoso quadrado mágico de Dürer :

insira a descrição da imagem aqui

isso é,

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

Algumas propriedades deste quadrado, que talvez possam ser exploradas, são:

  • Ele contém cada número inteiro de 1que 16exatamente uma vez
  • A soma de cada coluna ou linha, bem como a soma de cada uma das duas diagonais, é a mesma. Esta é a propriedade definidora de um quadrado mágico . A soma é a constante mágica do quadrado.
  • Além disso, para esse quadrado em particular, a soma de cada um dos quatro quadrantes também é igual à constante mágica, assim como a soma dos quatro quadrados do centro e a soma dos quatro quadrados do canto.

Regras

Bultins que geram quadrados mágicos não são permitidos (como Matlab magicou Mathematica MagicSquare). Qualquer outro built-in pode ser usado.

O código pode ser um programa ou uma função.

Não há entrada.

Os números devem estar na base 10. O formato de saída é flexível, como de costume. Algumas possibilidades são:

  • Uma matriz aninhada (saída da função ou sua representação de cadeia, com ou sem separadores, qualquer tipo de colchetes):

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

    {16, 3, 2, 13; 5, 10, 11, 8; 9, 6, 7, 12; 4, 15, 14, 1}
    
  • Uma matriz de quatro cadeias ou uma cadeia que consiste em quatro linhas. Os números podem estar alinhados à direita

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

    ou alinhado à esquerda

    16 3  2  13
    5  10 11  8
    9  6  7  12
    4  15 14  1
    
  • Uma sequência com dois separadores diferentes para linha e coluna, como

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

O formato de saída deve diferenciar claramente linhas e colunas. Por exemplo, não é permitido gerar uma matriz plana ou uma sequência com todos os números separados por espaços.

Código de golfe. Vitórias mais curtas.



4
Curiosamente, os números 5, 8, 9 e 12 estão em suas posições (indexadas 1), 6, 7, 10 e 11 foram refletidos verticalmente, 2, 3, 14 e 15 foram refletidos horizontalmente e 1, 4, 13 e 16 foram girados 180 °. Duvido que isso ajude alguém.
Neil

2
Observação possivelmente útil: se você decrementar 1 de cada número, poderá gerar o quadrado começando com a matriz [15], concatenando-o repetidamente com seu reverso com cada item XORed por 13, 3, 8 e 15, respectivamente.
ETHproductions

6
Isso parece bastante difícil de compactar em idiomas que não são de golfe. Eu acho que um quadrado mágico maior teria feito melhor.
Xnor

1
Estou bastante certo de que cada rotação ou reflexo do quadrado teria as mesmas propriedades.
Dennis

Respostas:


7

Gelatina , 15 bytes

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

TryItOnline!

Muito chato, desculpe:

Preparação: pegue o quadrado, leia-o por linhas, convertido da base bijetiva 16, converta-o na base 250, procure os índices da página de códigos para esses "dígitos" ( ¡6ṡƘ[²Ḳi<).

O Jelly lê os índices para formar um número base 250, converte para a base bijetiva 16 ( ḃ⁴) e divide-se em pedaços do tamanho 4 ( s4).


Se for permitido produzir uma orientação diferente, é possível de cabeça para baixo em 14 :

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

Teste


Em teoria, com memória suficiente para 16!números inteiros, o seguinte nos daria a orientação correta em 14 :

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

Isso criaria todas as permutações de [1,16] com ⁴Œ!e escolheria o valor no índice 19800593106060 (baseado em 1) com o uso da representação base 250 ŒCġŀḌ;e dividiria em pedaços de comprimento 4 com s4.


Desde então, tenho acrescentou quatro novos átomos ( Œ?, Œ¿, œ?e œ¿) para Jelly para enfrentar tais situações.
A mônada Œ?pega um número inteiro (ou iterável de números inteiros) e retorna a menor permutação possível da execução de números naturais que teria o índice (ou índices) fornecido em uma lista de lista lexicograficamente classificada de todas as permutações desses números.
... e faz isso sem criar nenhuma lista de permutações.
Como tal, o seguinte funcionaria agora para 12 (obviamente não concorrentes):

“ŒCġŀḌ;’Œ?s4

Dê uma chance!


Isso deve ser mais curto no seu garfo Jelly (que eu havia esquecido até agora, desculpe).
Dennis

Oh? Como você pensa?
Jonathan Allan

8

Pitão, 18 bytes

c4.PC"H#ût"_S16

Execute o 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

A reversão da faixa destinava-se a diminuir o índice de permutação, uma vez que a saída começa com 16, mas acho que ela só quebrou.

Isso superou uma estratégia mais chata de converter a tabela diretamente na base 17 e depois uma string ( link ) para 20 bytes:

c4jC"úz(ás¸H"17 

7

Geléia , 16 15 bytes

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

Experimente online!

fundo

Se subtrairmos 1 dos números no quadrado e os dividirmos por 4 (quociente de computação e restante), um padrão se tornará aparente.

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

A matriz restante segue um padrão óbvio e é fácil de gerar. A matriz quociente pode ser obtida transpondo a matriz restante e trocando as linhas do meio.

Como 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

Economizou 10 bytes graças a milhas!

4 4$1+19800593106059 A.i.16

Agora com menos chato! Isso leva a 19800593106059permutação da lista i.16, que é 15 2 1 12 4 9 10 7 8 5 6 11 3 14 13 0. Então, isso é incrementado e, então, é modelado em uma lista 4por 4.

Versão alternativa, sem espaço em branco:

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

Saída, para posteridade:

   _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

Eu acho que _4]\1+19800593106059&A.i.16funciona, mas poderia ser feita mais curta, possivelmente
milhas

@miles oo, bom uso de A.. Como você encontrou esse número?
Conor O'Brien

Monádico A.encontra o índice de permutação de uma permutação zero indexada
milhas

@miles huh. Acho que deveria aprender um pouco mais sobre essas funções.
Conor O'Brien

4

05AB1E , 18 17 bytes

Agradecemos a Emigna por salvar um byte!

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

Usa a codificação CP-1252 . Experimente online!


Incrementar antes de chunking salva um byte ( >4ô).
Emigna

@Emigna Ahh, é claro! Obrigado! :)
Adnan

4

Ruby, 49 bytes (menor que a solução ingênua!)

Foram necessárias algumas tentativas para escrever um trecho para esse desafio em um idioma convencional que era mais curto do que o avaliado! De acordo com as regras usuais, eu criei um programa adicionando um ppara produzi-lo.

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

Ele gera (a representação em cadeia de) uma matriz de matrizes. É mais longo que a solução Ruby da wat, que gera uma string de formato diferente, mas um byte menor que o programa ingênuo abaixo, que simplesmente retorna a 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

Explicação: comece com os números 0..15 (38 bytes!)

Foi aqui que comecei e é muito mais fácil. Se convertermos o quadrado 0..15 em binário, notamos que cada célula contém o valor na parte inferior da coluna XORed com o valor no lado direito da linha:

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

A partir disso, derivamos o código abaixo. Mas, usando a primeira coluna em vez da última, economizamos um byte, como mostrado.

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

A versão exigida de 1 a 16 foi mais difícil. No final, percebi que a maneira de fazer isso era adicionar 1 a cada célula do quadrado 0..15. Mas como ^tem prioridade mais baixa do que +eu precisava de muitos parênteses, que comiam bytes. Finalmente, tive a ideia de usar ^=. O novo valor de ié calculado por atribuição aumentada ^=antes que o 1 seja adicionado a ele, portanto, o cálculo é feito na ordem correta.


Boa caracterização! Uma realização simples em Python é 6 caracteres acima hardcode: for a in 12,7,11,0:print[(a^b)+1for b in 3,14,13,0]. Ganharia se pudéssemos fazer 0 a 15 com 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 novas linhas e vírgulas. Duvido que haja uma maneira mais curta ...


Sim, este é provavelmente o mais curto possível.
Conor O'Brien

2

sed 39 bytes

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

Experimente Online!

Não pode ficar muito mais simples que isso. E, infelizmente, também não acho que possa ficar mais curto.


2

Gelatina, 20 bytes

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

Experimente online!

Isso simplesmente consulta o ponto de código Jelly de cada caractere e, em seguida, divide em sub-matrizes de comprimento 4 com s4.


2

DASH , 24 bytes

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

Substitua os períodos pelos caracteres dos códigos 16, 3, 2, 13, 5, 10, 11, 8, 9, 6, 7, 12, 4, 15, 14 e 1, respectivamente.

Explicação

Simplesmente converte os caracteres em uma matriz de códigos e blocos por 4.


2

Na verdade , 22 bytes

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

Experimente online!

Explicação:

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

Analise cada um como dígito hexidecimal e adicione 1, agrupe por 4 em uma matriz 2D.

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

Mais curto, mas também mais lamer:

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

2

Javascript ES6, 66 65 55 bytes

Sim, não é o mais curto. E sim, pode ser reduzido.

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

Por enquanto, não é perfeito. Mas é alguma coisa!


Graças à sugestão de @Neil , que pode salvar de 5 a 8 bytes, e que inspirou a sugestão de @ETHproductions, que economiza 10 bytes!

Isso torna a resposta apenas 12 bytes mais longa que sua solução de 43 bytes .


1
Você pode usar em gvez de 0e em parseInt(c,17)vez disso, o que eu acho que economiza 4 bytes, ou você pode usar + 0x${c}|| 16, que eu acho que economiza 5 bytes e, em seguida, você pode subtrair 1 de todos os dígitos e adicioná-lo novamente mais tarde, o que eu acho que economiza mais um byte.
Neil

1
Com base nas sugestões de @ Neil, você pode salvar pelo menos 10 bytes no total .
ETHproductions

@ Neil Muito obrigado pela idéia. Usar base17 realmente salva alguns bytes. Realmente é algo que eu não pensei.
Ismael Miguel

@ETHproductions Muito obrigado pela sugestão! Ainda estou tentando entender como isso funciona. Mas acho que vou chegar lá. Agora, basta diminuir 13 bytes para bater em você. Mas parece que sua resposta é a mais curta possível em Javascript
Ismael Miguel

1

PowerShell v2 +, 40 bytes

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

Uma sequência multilinha literal, deixada no pipeline. A saída via implícita Write-Outputacontece na conclusão do programa. Bom e chato.


Versão construída, 77 bytes

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

Pega a string, -splitfaz cada quatro elementos, faz um loop neles, muda cada um para um hex 0x$_e adiciona 1, canaliza isso para iex(abreviado Invoke-Expressione semelhante a eval) e, em seguida, -joiné o resultado em uma string com ,o separador. Produz quatro strings no pipeline, com impressão implícita.


1

Ruby, 60 bytes - primeira tentativa

%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ä

Explicação

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

O índice da permutação foi encontrado usando a fórmula:

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

Onde as variáveis ​​são substituídas pelo número de elementos subsequentes menores que o número no índice atual para cada número na lista de destino
[16, 3, 2, 13, 5, 10, 11, 8, 9, 6, 7, 12, 4, 15, 14, 1]

que para a nossa permutação procurada é
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

Isso nos dá a 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 é igual a 19800593106059.


1

Matlab, 38 35 bytes

Função anônima:

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

Impressão direta (38 bytes):

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

No Matlab, a melhor maneira de produzir uma matriz de números inteiros é através de uma string.


O uso de uma função anônima salvaria alguns bytes:@()['pcbm';'ejkh';'ifgl';'dnoa']-96
Luis Mendo 1/16

@LuisMendo Eu não percebi que retornar valor também é aceitável, obrigado!
Pajonk

1

Scala, 52 bytes

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

Ungolfed:

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

Inspirado por nível do rio St resposta rubi .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.