Quadrados Mágicos do Módulo


11

Eu sou um grande fã da teoria dos números. Uma grande coisa na teoria dos números é a aritmética modular; a definição sendo se e somente se . Uma coisa divertida a se fazer é aumentar os poderes: especialmente quando o módulo é um número primo. Em particular, ficou provado que se e são relativamente primos (não compartilham fatores comuns além de ), existe um número tal que .abmodmmabam1eae1modm

Vou explicar o que é o exercício por um exemplo. Vamos dar um módulo . Uma saída possível do programa ou função seria:m=7

3 2 6 4 5 1
2 4 1 2 4 1
6 1 6 1 6 1
4 2 1 4 2 1
5 4 6 2 3 1
1 1 1 1 1 1

Cada linha é uma lista dos poderes do primeiro número nessa linha: a primeira linha é , o que equivale a módulo . A segunda linha do quadrado acima são as potências de , etc., até a última linha, que são apenas potências de 1 .3,32,33,,363,2,6,4,5,1721

Este é um quadrado de módulo mágico porque:

  • O quadrado é simétrico; isto é, a i ésima coluna é a i ésima linha.
  • Todos os valores de 1 a m1 aparecem pelo menos uma vez.

Abaixo está a única outra saída válida para m=7 , começando com potências de 5 :

5 4 6 2 3 1
4 2 1 4 2 1
6 1 6 1 6 1
2 4 1 2 4 1
3 2 6 4 5 1
1 1 1 1 1 1

O desafio

Crie uma função ou programa que, dado um número primo, pproduza um quadrado de módulo mágico, ou seja, um quadrado com comprimentos laterais p-1, de modo que cada linha seja uma lista dos poderes consecutivos do primeiro elemento na linha e o mesmo para as colunas. Todos os números entre 0e pdevem ocorrer, e o quadrado pode conter apenas números nesse intervalo.

A entrada é um número ou uma string e a saída pode ser ascii, uma matriz, uma matriz de matrizes (qualquer formato razoável).

Isso é código-golfe, então o código mais curto vence.


Sequência OEIS relacionada: A001918 (o menor valor válido para o canto superior esquerdo).
Arnauld

2
" Vou explicar qual é o exercício por um exemplo. " Não. Explique-o em seus próprios termos e dê um exemplo para ilustrar. Eu acho que o que você está pedindo é uma matriz tal que é um primitivo modulo raiz e , mas é muito esforço extrair essa especificação da pergunta como ela está. AA1,1pAi,j=A1,1ijmodp
Peter Taylor

2
@ PeterTaylor é verdade, e é isso que quero dizer, mas em primeiro lugar, isso estraga parte da diversão da exploração e, em segundo lugar, conta com o conhecimento sobre raízes primitivas e aritmética modular. Queria que essa pergunta fosse respondida por um público mais amplo do que isso, então tentei explicar o que quero dizer em termos mais fáceis.
vrugtehagel

Respostas:


5

Geléia , 13 10 bytes

-3 graças a Nick Kennedy

Sente como o código repetido deve ser é o golfe-capaz, mas eu não conseguiu d -lo ...

*€Ṗ%µQƑƇḢị

Experimente online! (rodapé formatos bonitos como uma grade)

Quão?

*€Ṗ%µQƑƇḢị - Link: integer, p
 €         - for each n in [1..p]
*          -   exponentiate with:
  Ṗ        -     pop = [1..p-1]
           - ...i.e [[1^1,1^2,...,1^(p-1)],[2^1,2^2,...,2^(p-1)],...,[....,p^(p-1)]]
   %       - modulo p
    µ      - start a new monadic chain (call that list of lists X)
       Ƈ   - keep those which:
      Ƒ    -   are invariant under:
     Q     -     de-duplicate
        Ḣ  - head
         ị - index into the list of lists X


Ahha, agora eu me sinto lento; p obrigado!
Jonathan Allan

3

Carvão , 36 bytes

≔E…¹θ﹪Xι…¹θIθηE⊟Φη⁼¹№ι¹⪫E§η⊖ι◧IλL⊖θ 

Experimente online! Link é a versão detalhada do código. Nota: Espaço à direita. Explicação:

≔E…¹θ﹪Xι…¹θIθη

Criar um p-1por p-1conjunto de poderes 1..p-1da índices 1..p-1(módulo p).

E⊟Φη⁼¹№ι¹

Mapeie sobre uma das linhas que possui exatamente uma 1.

⪫E§η⊖ι◧IλL⊖θ 

Reorganize as linhas na ordem dada pela linha selecionada e formate a saída.




2

JavaScript (ES7),  91  86 bytes

Esta versão tenta calcular os poderes antes de aplicar o módulo e falhará em devido à perda de precisão. Caso contrário, está usando a mesma lógica da versão comentada abaixo.p11

f=(p,k)=>(g=k=>[...Array(i=p-1)].map(_=>k**++i%p))(k).sort()[1]>1?g(k).map(g):f(p,-~k)

Experimente online!


JavaScript (ES6),  92  87 bytes

Esta versão usa exponenciação modular para suportar valores de entrada (muito) mais altos.

f=(p,k)=>(g=k=>[...Array(p-1)].map(_=>n=n*k%p,n=1))(k).sort()[1]>1?g(k).map(g):f(p,-~k)

Experimente online!

Quão?

Localizando a primeira linha

Dado , usamos a função auxiliar para calcular para .1k<pgak(n)=knmodp1n<p

g = k =>              // k = input
  [...Array(p - 1)]   // generate an array of size p - 1
  .map(_ =>           // for each entry in there:
    n = n * k % p,    //   update n to (n * k) mod p
    n = 1             //   starting with n = 1
  )                   // end of map()

Procuramos modo que haja apenas um valor tal que . Fazemos isso classificando a matriz e testando se o 2 nd elemento é maior do que .knak(n)=11

g(k).sort()[1] > 1

Isso funciona mesmo em ordem lexicográfica - que é o comportamento padrão de sort()- porque:

  • se houver vários 's, todos eles serão movidos para a frente como se estivessem em ordem numérica1
  • se houver apenas um único , o valor será maior que , independentemente de ser realmente o valor em ordem numérica ou não11

Exemplo:

Para :p=17

  • para , obtemos: k=1
    • a1=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
    • classificado como[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
  • para , obtemos: k=2
    • a2=[2,4,8,16,15,13,9,1,2,4,8,16,15,13,9,1]
    • classificado como[1,1,13,13,15,15,16,16,2,2,4,4,8,8,9,9]
  • para , obtemos: k=3
    • a3=[3,9,10,13,5,15,11,16,14,8,7,4,12,2,6,1]
    • classificados como[1,10,11,12,13,14,15,16,2,3,4,5,6,7,8,9]

Construindo a matriz

Depois de encontrarmos , invocamos novamente (para recuperar a versão não classificada da matriz) e invocamos em cada elemento de para criar as linhas da matriz.kg(k)gg(k)

Esta parte pode ser simplesmente escrita como:

g(k).map(g)

.indexOf(1)>p-3economiza 3 bytes acima .every.
Neil

@ Neil Obrigado. Mas encontrei um caminho mais curto depois de uma boa noite de sono. :)
Arnauld

2

Zsh , 117 90 bytes

b=$1
c=(eval set -- '$[x**'{1..$[b-1]}%b\])
for ((;${#${(u)@}}-b+1;++x))$c
for x;$c&&<<<$@

Experimente online! Experimente online!

Que Deus tenha piedade da minha alma. Há muita prática ruim envolvida aqui, deixe-me explicar pelo menos o maior infrator:

c=(eval set -- '$[x**'{1..$[b-1]}%b\])
                      {1..$[b-1]}        # brace expansion, expands immediately
               '$[x**'           %b\]    # string literals, expand during eval
   eval set --                           # sets the positional parameters
c=(                                   )  # defines c to the words contained

Exemplo para b=4:

c=(eval set -- '$[x**'{1..$[b-1]}%b\])
c=(eval set -- '$[x**'{1..3}%b\]     )                # $[b-1] => 3
c=(eval set -- '$[x**1%b]' '$[x**2%b]' '$[x**3%b]' )  # brace expansion

Finalmente, onde $caparece no restante do programa, os elementos da matriz são avaliados como eval set -- .....

Por fim, ${#${(u)@}}conta os elementos únicos nos parâmetros posicionais (ou seja: existe um ciclo / existem 1?)

Comentários relevantes para a resposta de 117 bytes abaixo.


Desafios que temos que superar:

  • Nenhuma matriz multidimensional ou aninhada. Em vez disso, imprimimos as strings à medida que as juntamos.
  • Opções para testar se uma determinada linha possui vários 1s:
    • ${#${(M)a:#1}: :#remove a correspondência e (M)reverte a correspondência. Portanto, isso será expandido para o número ( ${# }) de 1s na matriz. Infelizmente, essa expansão não funciona muito bem com o loop for aritmético que usamos aqui. Se o fizesse, poderia salvar potencialmente um byte.
    • ${${:-1}:*a}: Esta é a interseção do conjunto entre o singleton 1e o conjunto a. Isso será expandido para o único 1se for encontrado na matriz. Usando essa opção, salvamos um caractere aqui, mas perdemos 1 no geral, adiando a adição de 1s na última linha e coluna até o final.
f(){ # f [element] [modular base], puts powers up to n-2 into array $a
    a=()
    for i ({1..$[$2-2]})
        a+=($[$1**i%$2])
}
a=(1)                     # put 1 in a to force first loop iteration
for ((;${${:-1}:*a};))    # test for 1 in array $a
    f $[++x] $1           # increment x, iterate through all elements mod $1
for y ($a 1){             # for all elements in the [last array, 1]
    f $y $1               # put that row in $a
    <<<$a\ 1              # print out $a with 1 appended (space-delimited string)
}

1

Perl 6 , 65 57 bytes

{.[|.first(*.Set+2>$_)]}o{.&{@=(($++X**1..^$_)X%$_)xx$_}}

Experimente online!

Provavelmente, há alguma maneira de apenas exibir o quadrado em si, mas isso faz o mesmo processo descrito na pergunta, classificando as listas por suas posições na primeira lista, que é apenas uma permutação de 1 para entrada-1. Retorna como uma lista de listas.

BTW, existem muitas brincadeiras, tentando contornar algumas das irritantes limitações do Perl 6 que envolvem sequências versus matrizes e variáveis ​​anônimas.

Explicação:

                               $++               xx$_    # Map 0 to i-1 to
                              (   X**1..^$_)             # n, n^2, n^3... n^(i-1)
                             (              X%$_)        # All modulo i
{                      }o{.&{                        }}  # Pass to the next function
 .[                   ]    # Index into that list of lists
   |.first(          )     # The list of the first list that
           *.Set+2>$_        # Has all the elements in the range 1 to i-1


1

05AB1E , 19 16 bytes

LεI<LmI%}ÐΘOÏн<è

-3 bytes graças a @Emigna .

Experimente on-line (o rodapé é para imprimir a lista em 2D).

Explicação:

L          # Create a list in the range [1, (implicit) input]
 ε         # Map each number `y` in the list to:
  I<L      #  Create a list in the range [1, input-1]
     m     #  Get number `y` to the power of each number in this list
      I%   #  Take modulo-input on each number
         # After the map: triplicate this modified matrix
   ΘO      # Get the amount of 1s in each row
     Ï     # And only leave the rows with exactly one 1
      н    # Then only leave the first row which contains a single 1
       <   # Decrease each value by 1 to make it 0-indexed
        è  # And index each into the rows of the modified matrix to create a new matrix
           # (which is output implicitly as result)

1
LεI<LmI%}ÐΘOÏн<èpor 16 bytes.
Emigna 13/05/19

@Emigna Thanks! Não sabia que teria sido suficiente em vez do que UΣXykeu tinha.
Kevin Cruijssen 13/05/19



0

APL (NARS), 29 caracteres, 58 bytes

{k←⍵∣⍺*⍳⍵-1⋄⊃{m∣k*⍵}¨⍳¯1+m←⍵}

teste:

  f←{k←⍵∣⍺*⍳⍵-1⋄⊃{m∣k*⍵}¨⍳¯1+m←⍵}
  3 f 7
3 2 6 4 5 1
2 4 1 2 4 1
6 1 6 1 6 1
4 2 1 4 2 1
5 4 6 2 3 1
1 1 1 1 1 1
  5 f 7
5 4 6 2 3 1
4 2 1 4 2 1
6 1 6 1 6 1
2 4 1 2 4 1
3 2 6 4 5 1
1 1 1 1 1 1 
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.