Definir um campo com 256 elementos

15

Um campo em matemática é um conjunto de números, com operações de adição e multiplicação definidas, de modo a satisfazer certos axiomas (descritos na Wikipedia; veja também abaixo).

Um campo finito pode ter elementos p n , onde pé um número primo e né um número natural. Neste desafio, vamos pegar p = 2e n = 8, então vamos criar um campo com 256 elementos.

Os elementos do campo devem ser números inteiros consecutivos em um intervalo que contém 0e 1:

  • -128 ... 127
  • 0 ... 255
  • ou qualquer outro intervalo

Defina duas funções (ou programas, se isso for mais fácil), a(x,y)para "adição" m(x,y)abstrata e "multiplicação" abstrata, de modo a satisfazer os axiomas do campo:

  • Consistência: a(x,y)e m(x,y)produz o mesmo resultado quando chamado com os mesmos argumentos
  • Fechamento: o resultado de ae mé um número inteiro no intervalo relevante
  • Associatividade: para qualquer x, ye zno intervalo, a(a(x,y),z)é igual a a(x,a(y,z)); o mesmo param
  • Comutatividade: para qualquer xe yna faixa, a(x,y)é igual a a(y,x); o mesmo param
  • Distributividade: para qualquer x, ye zdentro da faixa, m(x,a(y,z))é igual aa(m(x,y),m(x,z))
  • Elementos neutros: para qualquer um xno intervalo, a(0,x)é igual a x, e m(1,x)é igual ax
  • Negação: para qualquer pessoa xno intervalo, existe uma yque a(x,y)seja0
  • Inverso: para qualquer pessoa x≠0no intervalo, existe uma yque m(x,y)seja1

Os nomes ae msão apenas exemplos; você pode usar outros nomes ou funções sem nome. A pontuação da sua resposta é a soma dos comprimentos de bytes para ae m.

Se você usar uma função interna, descreva também em palavras o resultado que ela produz (por exemplo, forneça uma tabela de multiplicação).

anatolyg
fonte
3
@LeakyNun "adição" é apenas uma operação abstrata aqui que satisfaz as propriedades acima. Não há necessidade a(2,1) = 3, você pode ter a(2,1) = 5enquanto os axiomas acima forem satisfeitos. anão precisa fazer nada com a adição usual a que você está acostumado, por exemplo, no campo dos números racionais.
Martin Ender
2
Um anel comutativo é trivial. Um campo ... não é tão fácil.
Neil
Há algo de errado com a=+ m=×?
Adám 14/06/16
4
@ Adám Sim - 2 não teria o inverso sem=×
SP3000
2
Relacionados
Peter Taylor

Respostas:

4

Intel x86-64 + AVX-512 + GFNI, 11 bytes

add:
    C5 F0 57 C0     # vxorps     xmm0, xmm1, xmm0
    C3              # ret
mul:
    C4 E2 79 CF C1  # vgf2p8mulb xmm0, xmm0, xmm1
    C3              # ret

Usa a nova GF2P8MULBinstrução nas CPUs Ice Lake.

A instrução multiplica elementos no campo finito GF (2 8 ), operando em um byte (elemento de campo) no primeiro operando de origem e o byte correspondente em um segundo operando de origem. O campo GF (2 8 ) é representado na representação polinomial com o polinômio de redução x 8 + x 4 + x 3 + x + 1.

Nwellnhof
fonte
13

Python 2, 11 + 45 = 56 bytes

Adição (11 bytes):

int.__xor__

Multiplicação (45 bytes):

m=lambda x,y:y and m(x*2^x/128*283,y/2)^y%2*x

Toma números de entrada no intervalo [0 ... 255]. A adição é apenas XOR bit a bit, multiplicação é multiplicação de polinômios com coeficientes em GF2 com camponeses russos .

E para verificar:

a=int.__xor__
m=lambda x,y:y and m(x*2^x/128*283,y/2)^y%2*x

for x in range(256):
    assert a(0,x) == a(x,0) == x
    assert m(1,x) == m(x,1) == x

    assert any(a(x,y) == 0 for y in range(256))

    if x != 0:
        assert any(m(x,y) == 1 for y in range(256))

    for y in range(256):
        assert 0 <= a(x,y) < 256
        assert 0 <= m(x,y) < 256
        assert a(x,y) == a(y,x)
        assert m(x,y) == m(y,x)

        for z in range(256):
            assert a(a(x,y),z) == a(x,a(y,z))
            assert m(m(x,y),z) == m(x,m(y,z))
            assert m(x,a(y,z)) == a(m(x,y), m(x,z))
Sp3000
fonte
Um de nós terá que mudar: P
Mego 14/06
@Mego Hah, bem ... Vou tentar ver se consigo encontrar outras abordagens. Pode ser difícil de vencer, no entanto.
Sp3000
1
Em que polinômio é baseado?
feersum
1
@LSpice Agora percebo que posso encontrar facilmente o polinômio executando o m(2,128)que resulta em 27 = 283 - 256, para que você esteja correto e o polinômio seja x^8 + x^4 + x^3 + x + 1.
feersum
1
@LSpice Na resposta de Neil, ele fornece uma página da Wikipedia como fonte do algoritmo, então talvez todo mundo tenha lido isso. Mas é de qualquer maneira a escolha mais óbvia para o código de golfe, já que é o menor polinômio irredutível de grau 8 nessa representação.
feersum
6

JavaScript (ES6), 10 + 49 = 59 bytes

a=(x,y)=>x^y
m=(x,y,p=0)=>x?m(x>>1,2*y^283*(y>>7),p^y*(x&1)):p

O domínio é 0 ... 255. Origem .

Neil
fonte
2
Você provavelmente deve especificar o intervalo que está usando.
Martin Ender
4

Hoon , 22 bytes

[dif pro]:(ga 8 283 3)

Hoon já tem uma função ++gaque cria Galois Fields, para uso na implementação do AES. Isso retorna uma tupla de duas funções, em vez de usar dois programas.

Opera no domínio [0...255]

Suíte de teste:

=+  f=(ga 8 283 3)
=+  n=(gulf 0 255)

=+  a=dif:f
=+  m=pro:f

=+  %+  turn  n
    |=  x/@
    ?>  =((a 0 x) x)
    ?>  =((m 1 x) x)
    ~&  outer+x

    %+  turn  n
      |=  y/@
      ?>  =((a x y) (a y x))
      ?>  &((lte 0 (a x y)) (lte (a x y) 255))
      ?>  &((lte 0 (m x y)) (lte (m x y) 255))

      %+  turn  n
        |=  z/@
        ?>  =((a (a x y) z) (a x (a y z)))
        ?>  =((m x (a y z)) (a (m x y) (m x z)))
        ~
"ok"

A publicação de uma tabela de multiplicação seria gigantesca, então, aqui estão alguns casos de teste aleatórios:

20x148=229
61x189=143
111x239=181
163x36=29
193x40=1
RenderSettings
fonte
1

Código de máquina IA-32, 22 bytes

"Multiplicação", 18 bytes:

33 c0 92 d1 e9 73 02 33 d0 d0 e0 73 02 34 1b 41
e2 f1

"Adição", 4 bytes:

92 33 c1 c3

Isso estende as regras um pouco: o código "multiplicação" não possui o código de saída da função; ele conta com o código de "adição" que está na memória logo depois, para que possa "cair". Fiz isso para diminuir o tamanho do código em 1 byte.

Código fonte (pode ser montado pelo mlMS Visual Studio):

    TITLE   x

PUBLIC @m@8
PUBLIC @a@8

_TEXT   SEGMENT USE32
@m@8    PROC
    xor eax, eax;
    xchg eax, edx;
myloop:
    shr ecx, 1
    jnc sk1
    xor edx, eax
sk1:
    shl al, 1
    jnc sk2
    xor al, 1bh
sk2:
    inc ecx
    loop myloop
@m@8 endp

@a@8 proc
    xchg eax, edx;
    xor eax, ecx
    ret
@a@8    ENDP
_text ENDS
END

O algoritmo é o padrão, envolvendo o polinômio usual x^8 + x^4 + x^3 + x + 1, representado pelo número hexadecimal 1b. O código "multiplicação" acumula o resultado em edx. Quando concluído, ele passa para o código de adição, que o move para eax(registro convencional para manter o valor de retorno); o xorwith ecxé um no-op, porque nesse ponto ecxestá limpo.

Uma característica peculiar é o loop. Em vez de verificar zero

cmp ecx, 0
jne myloop

Ele usa a loopinstrução dedicada . Mas esta instrução diminui o "contador" do loop antes de compará-lo a 0. Para compensar isso, o código aumenta antes de usar a loopinstrução.

anatolyg
fonte
0

Mathematica 155 bytes

f[y_]:=Total[x^Reverse@Range[0,Log[2,y]]*RealDigits[y,2][[1]]];o[q_,c_,d_]:=FromDigits[Reverse@Mod[CoefficientList[PolynomialMod[q[f@c,f@d],f@283],x],2],2]

Implementação

(*
  in: o[Times, 202, 83]    out: 1
  in: o[Plus, 202, 83]     out: 153
*)

verificação adicional:

(*
  in: BitXor[202, 83]      out: 153
*)

Mais:

(*
  in: o[Times, #, #2] & @@@ {{20, 148}, {61, 189}, {111, 239}, {163, 36}, {193, 40}}
  out: {229, 143, 181, 29, 1}
*)

NB Deve ser capaz de usar qualquer um dos {283, 285, 299, 301, 313, 319, 333, 351, 355, 357, 361, 369, 375, 379, 391, 395, 397, 415, 419, 425, 433, 445, 451, 463, 471, 477, 487, 499, 501, 505}em lugar de 283.

Martin
fonte
Bem, aqui está 13 bytes menos: ±y_:=Total[#&@@y~RealDigits~2x^Reverse@Range[0,2~Log~y]];p[q_,c_,d_]:=Fold[#+##&,Reverse@CoefficientList[q[±c,±d]~PolynomialMod~±283,x]~Mod~2](assume que a fonte é codificado em ISO 8859-1)
Martin Ender
@MartinEnder não tem certeza de como implementar sua sugestão
martin
@martin Você pode usá-lo exatamente como antes, eu apenas usei em ±vez de fe em pvez de o(é claro que você pode manter isso como o, eu apenas usei ppara testar os dois) e, em seguida, salvei mais alguns bytes com o padrão truques de açúcar sintáticos.
Martin Ender
@MartinEnder pode começar ±a trabalhar mesmo que f, mas não p... não sei para onde estou indo errado
martin
Se você copiá-lo diretamente do comentário, pode haver alguns caracteres não imprimíveis sempre que o navegador exibir a quebra de linha no comentário. Exclua os caracteres em torno dessa posição após copiar e digite-os novamente. Se isso não fazê-lo, não tenho a certeza onde está o problema ..
Martin Ender
-1

Brainfuck, 28 caracteres

Felizmente, o Brainfuck padrão faz tudo no módulo 256.

Adição [->+<]:, assume que as entradas estão nas duas primeiras posições da fita, coloca a saída na posição 0

Multiplicação:, [->[->+>+<<]>[-<+>]<<]assume que as entradas estão nas duas primeiras posições da fita, coloca a saída na posição 3

ymbirtt
fonte