Definire un campo con 256 elementi


15

Un campo in matematica è un insieme di numeri, con operazioni di addizione e moltiplicazione definite su di esso, in modo tale da soddisfare determinati assiomi (descritti in Wikipedia; vedi anche sotto).

Un campo finito può avere p n elementi, dove pè un numero primo ed nè un numero naturale. In questa sfida, prendiamo p = 2e n = 8, quindi, creiamo un campo con 256 elementi.

Gli elementi del campo devono essere numeri interi consecutivi in ​​un intervallo che contiene 0e 1:

  • -128 ... 127
  • 0 ... 255
  • o qualsiasi altro intervallo del genere

Definire due funzioni (o programmi, se è più semplice), a(x,y)per "addizione" m(x,y)astratta e per "moltiplicazione" astratta, in modo tale da soddisfare gli assiomi di campo:

  • Coerenza: a(x,y)e m(x,y)produce lo stesso risultato quando viene chiamato con gli stessi argomenti
  • Chiusura: il risultato di aed mè un numero intero nell'intervallo pertinente
  • Associatività: per qualsiasi x, ye znell'intervallo, a(a(x,y),z)è uguale a a(x,a(y,z)); lo stesso perm
  • Commutatività: per qualsiasi xe ynell'intervallo, a(x,y)è uguale a a(y,x); lo stesso perm
  • Distributività: per qualsiasi x, ye znella gamma, m(x,a(y,z))è uguale aa(m(x,y),m(x,z))
  • Elementi neutri: per qualsiasi valore xcompreso nell'intervallo, a(0,x)è uguale a xed m(1,x)è uguale ax
  • Negazione: per ogni xnell'intervallo, esiste tale yche a(x,y)sia0
  • Inversa: per ogni x≠0nell'intervallo, esiste tale yche m(x,y)sia1

I nomi ae msono solo esempi; puoi usare altri nomi o funzioni senza nome. Il punteggio della risposta è la somma delle lunghezze di byte per ae m.

Se si utilizza una funzione integrata, descrivere anche a parole il risultato che produce (ad es. Fornire una tabella di moltiplicazione).


3
La "aggiunta" di @LeakyNun è solo un'operazione astratta che soddisfa le proprietà di cui sopra. Non è necessario a(2,1) = 3, si potrebbe avere a(2,1) = 5fino a quando gli assiomi sopra sono soddisfatti. anon deve fare nulla con la solita aggiunta a cui sei abituato, ad esempio, dal campo dei numeri razionali.
Martin Ender,

2
Un anello commutativo è banale. Un campo ... non così facile.
Neil,

C'è qualcosa che non va a=+ m=×?
Adám,

4
@Adám Sì - 2 non avrebbe un contrario sem=×
Sp3000,

Risposte:


4

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

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

Utilizza le nuove GF2P8MULBistruzioni sulle CPU Ice Lake.

L'istruzione moltiplica gli elementi nel campo finito GF (2 8 ), operando su un byte (elemento di campo) nel primo operando di origine e il byte corrispondente in un secondo operando di sorgente. Il campo GF (2 8 ) è rappresentato nella rappresentazione polinomiale con il polinomio di riduzione x 8 + x 4 + x 3 + x + 1.


13

Python 2, 11 + 45 = 56 byte

Aggiunta (11 byte):

int.__xor__

Moltiplicazione (45 byte):

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

Accetta i numeri di input nell'intervallo [0 ... 255]. L'aggiunta è semplicemente XOR bit a bit, la moltiplicazione è la moltiplicazione di polinomi con coefficienti in GF2 con contadino russo .

E per controllare:

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

Uno di noi dovrà cambiare: P
Mego

@Mego Hah, beh ... proverò a vedere se riesco a trovare altri approcci. Potrebbe essere difficile da battere però.
Sp3000,

1
Su quale polinomio si basa?
feersum

1
@LSpice Ora mi rendo conto che posso facilmente trovare il polinomio eseguendo il m(2,128)risultato che risulta in 27 = 283 - 256, quindi hai ragione e il polinomio lo è x^8 + x^4 + x^3 + x + 1.
feersum,

1
@LSpice Nella risposta di Neil fornisce una pagina di Wikipedia come fonte dell'algoritmo, quindi forse tutti lo leggono. Ma è comunque la scelta più ovvia per il golf del codice poiché è il più piccolo polinomio irriducibile di grado 8 in questa rappresentazione.
feersum,

6

JavaScript (ES6), 10 + 49 = 59 byte

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

Il dominio è 0 ... 255. Sorgente .


2
Probabilmente dovresti specificare l'intervallo che stai usando.
Martin Ender,

4

Hoon , 22 byte

[dif pro]:(ga 8 283 3)

Hoon ha già una funzione ++gache crea Galois Fields, da utilizzare nell'implementazione AES. Ciò restituisce una tupla di due funzioni, invece di utilizzare due programmi.

Funziona nel dominio [0...255]

testsuite:

=+  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"

Pubblicare una tabella di moltiplicazione sarebbe gigantesco, quindi ecco alcune prove casuali:

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

1

Codice macchina IA-32, 22 byte

"Moltiplicazione", 18 byte:

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

"Aggiunta", 4 byte:

92 33 c1 c3

Questo allunga un po 'le regole: il codice "moltiplicazione" manca del codice di uscita della funzione; si basa sul fatto che il codice "addizione" sia in memoria subito dopo, quindi può "fallire". L'ho fatto per ridurre la dimensione del codice di 1 byte.

Codice sorgente (può essere assemblato da 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

L'algoritmo è quello standard, che coinvolge il solito polinomio x^8 + x^4 + x^3 + x + 1, rappresentato dal numero esadecimale 1b. Il codice "moltiplicazione" accumula il risultato in edx. Al termine, passa al codice addizionale, che lo sposta su eax(registro convenzionale per contenere il valore restituito); il xorwith ecxè un no-op, perché a quel punto ecxviene cancellato.

Una caratteristica peculiare è il loop. Invece di verificare lo zero

cmp ecx, 0
jne myloop

utilizza l' loopistruzione dedicata . Ma questa istruzione riduce il "contatore" del loop prima di confrontarlo con 0. Per compensare ciò, il codice lo aumenta prima di utilizzare l' loopistruzione.


0

Mathematica 155 byte

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]

Implementazione

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

controllo addizionale:

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

Di Più:

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

NB Dovrebbe essere in grado di utilizzare qualsiasi {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}al posto di 283.


Bene, ecco 13 byte in meno: ±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](presuppone che la sorgente sia codificata in ISO 8859-1)
Martin Ender

@MartinEnder non è del tutto sicuro di come attuare il tuo suggerimento
martin,

@martin Puoi usarlo esattamente come prima, l'ho appena usato ±invece di fe pinvece di o(ovviamente puoi tenerlo come o, l'ho usato solo pper poterli testare entrambi), e poi ho salvato qualche altro byte con lo standard trucchi di zucchero sintattico.
Martin Ender,

@MartinEnder può ±funzionare allo stesso modo f, ma non p... non sono sicuro di dove sbaglio
martin

Se lo copi direttamente dal commento, potrebbero esserci dei caratteri non stampabili ovunque il browser visualizzi l'interruzione di riga nel commento. Elimina i caratteri in quella posizione dopo averli copiati e riscrivili. Se ciò non lo fa, non sono sicuro di dove sia il problema ...
Martin Ender,

-1

Brainfuck, 28 personaggi

Fortunatamente, lo standard Brainfuck fa tutto il modulo 256.

Aggiunta: [->+<]presuppone che gli ingressi siano nelle prime due posizioni del nastro e posiziona l'uscita in posizione 0

Moltiplicazione: [->[->+>+<<]>[-<+>]<<]presuppone che gli ingressi si trovino nelle prime due posizioni del nastro e posiziona l'uscita in posizione 3

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.