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.