Définissez un champ avec 256 éléments

15

Un champ en mathématiques est un ensemble de nombres, avec des opérations d'addition et de multiplication définies dessus, de sorte qu'ils satisfont certains axiomes (décrits dans Wikipedia; voir aussi ci-dessous).

Un champ fini peut avoir p n éléments, où pest un nombre premier et nun nombre naturel. Dans ce défi, prenons p = 2et n = 8, créons donc un champ avec 256 éléments.

Les éléments du champ doivent être des entiers consécutifs dans une plage qui contient 0et 1:

  • -128 ... 127
  • 0 ... 255
  • ou toute autre plage de ce type

Définissez deux fonctions (ou programmes, si c'est plus facile), a(x,y)pour "l'addition" m(x,y)abstraite , et pour la "multiplication" abstraite, de telle sorte qu'elles satisfassent les axiomes de champ:

  • Cohérence: a(x,y)et m(x,y)produit le même résultat lorsqu'il est appelé avec les mêmes arguments
  • Fermeture: Le résultat de aet mest un entier dans la plage pertinente
  • Associativité: pour tout x, yet zdans la plage, a(a(x,y),z)est égal à a(x,a(y,z)); pareil pourm
  • Commutativité: pour tout xet ydans la plage, a(x,y)est égal à a(y,x); pareil pourm
  • Distributivité: pour tout x, yet zdans la plage, m(x,a(y,z))est égal àa(m(x,y),m(x,z))
  • Éléments neutres: pour tout élément xde la plage, a(0,x)est égal à xet m(1,x)est égal àx
  • Négation: pour toute xla gamme, il existe ce yqui a(x,y)est0
  • Inverse: pour toute x≠0la gamme, il existe ce yqui m(x,y)est1

Les noms aet ne msont que des exemples; vous pouvez utiliser d'autres noms ou fonctions sans nom. Le score de votre réponse est la somme des longueurs d'octets pour aet m.

Si vous utilisez une fonction intégrée, veuillez également décrire en mots le résultat qu'elle produit (par exemple, fournir une table de multiplication).

anatolyg
la source
3
@LeakyNun "addition" n'est ici qu'une opération abstraite qui satisfait les propriétés ci-dessus. Ce n'est pas nécessaire a(2,1) = 3, vous pourriez en avoir a(2,1) = 5tant que les axiomes ci-dessus sont satisfaits. an'a rien à faire avec l'ajout habituel auquel vous êtes habitué, par exemple dans le domaine des nombres rationnels.
Martin Ender
2
Un anneau commutatif est trivial. Un champ ... pas si facile.
Neil
Y a-t-il quelque chose qui ne va pas a=+ m=×?
Adám
4
@ Adám Oui - 2 n'aurait pas d'inverse sim=×
Sp3000
2
En relation
Peter Taylor

Réponses:

4

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

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

Utilise la nouvelle GF2P8MULBinstruction sur les processeurs Ice Lake.

L'instruction multiplie les éléments dans le champ fini GF (2 8 ), fonctionnant sur un octet (élément de champ) dans le premier opérande source et l'octet correspondant dans un second opérande source. Le champ GF (2 8 ) est représenté en représentation polynomiale avec le polynôme de réduction x 8 + x 4 + x 3 + x + 1.

nwellnhof
la source
13

Python 2, 11 + 45 = 56 octets

Addition (11 octets):

int.__xor__

Multiplication (45 octets):

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

Prend les numéros d'entrée dans la plage [0 ... 255]. L'addition est juste XOR au niveau du bit, la multiplication est la multiplication des polynômes avec des coefficients dans GF2 avec le paysan russe .

Et pour vérifier:

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
la source
L'un de nous va devoir changer: P
Mego
@Mego Hah, eh bien ... je vais essayer de voir si je peux trouver d'autres approches. Cela pourrait être difficile à battre.
Sp3000
1
Sur quel polynôme est-il basé?
feersum
1
@LSpice Maintenant, je me rends compte que je peux facilement trouver le polynôme en exécutant m(2,128)ce qui donne 27 = 283 - 256, donc vous avez raison et le polynôme l'est x^8 + x^4 + x^3 + x + 1.
feersum
1
@LSpice Dans la réponse de Neil, il donne une page Wikipedia comme source pour l'algorithme, alors peut-être que tout le monde l'a lu. Mais c'est de toute façon le choix le plus évident pour le golf à code puisqu'il s'agit du plus petit polynôme irréductible de degré 8 dans cette représentation.
feersum
6

JavaScript (ES6), 10 + 49 = 59 octets

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

Le domaine est compris entre 0 et 255. Source .

Neil
la source
2
Vous devez probablement spécifier la plage que vous utilisez.
Martin Ender
4

Hoon , 22 octets

[dif pro]:(ga 8 283 3)

Hoon a déjà une fonction ++gaqui crée des champs de Galois, à utiliser dans l'implémentation AES. Cela renvoie un tuple de deux fonctions, au lieu d'utiliser deux programmes.

Fonctionne dans le domaine [0...255]

Suite de tests:

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

Publier une table de multiplication serait gigantesque, voici donc quelques tests aléatoires:

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

Code machine IA-32, 22 octets

"Multiplication", 18 octets:

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

"Addition", 4 octets:

92 33 c1 c3

Cela étire un peu les règles: le code de "multiplication" manque de code de sortie de fonction; il repose sur le code "addition" qui est en mémoire juste après, afin qu'il puisse "tomber". Je l'ai fait pour diminuer la taille du code d'un octet.

Code source (peut être assemblé par 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'algorithme est le standard, impliquant le polynôme habituel x^8 + x^4 + x^3 + x + 1, représenté par le nombre hexadécimal 1b. Le code "multiplication" accumule le résultat dans edx. Une fois terminé, il passe au code d'addition, qui le déplace vers eax(registre conventionnel pour conserver la valeur de retour); le xoravec ecxest un no-op, car à ce point ecxest effacé.

Une caractéristique particulière est la boucle. Au lieu de vérifier zéro

cmp ecx, 0
jne myloop

il utilise l' loopinstruction dédiée . Mais cette instruction diminue le "compteur" de boucle avant de le comparer à 0. Pour compenser cela, le code l'augmente avant d'utiliser l' loopinstruction.

anatolyg
la source
0

Mathematica 155 octets

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]

la mise en oeuvre

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

vérification d'addition:

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

Plus:

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

NB Doit être capable d'utiliser n'importe lequel {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}à la place de 283.

Martin
la source
Eh bien, voici 13 octets de moins: ±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](suppose que la source est encodée en ISO 8859-1)
Martin Ender
@MartinEnder ne sait pas trop comment mettre en œuvre votre suggestion
martin
@martin Vous pouvez l'utiliser exactement comme avant, je l'ai juste utilisé à la ±place de fet pau lieu de o(bien sûr, vous pouvez le garder comme o, je viens de l'utiliser ppour pouvoir les tester tous les deux), puis j'ai enregistré quelques octets supplémentaires avec la norme astuces de sucre syntaxique.
Martin Ender
@MartinEnder peut se mettre ±au travail de la même manière f, mais pas p... je ne sais pas où je me trompe
martin
Si vous le copiez directement à partir du commentaire, il peut y avoir des caractères non imprimables partout où votre navigateur affiche le saut de ligne dans le commentaire. Supprimez les caractères autour de cette position après la copie et retapez-les. Si cela ne le fait pas, je ne sais pas où est le problème ..
Martin Ender
-1

Brainfuck, 28 personnages

Heureusement, Brainfuck standard fait tout le module 256.

Addition [->+<]:, suppose que les entrées sont dans les deux premières positions de la bande, place la sortie en position 0

Multiplication:, [->[->+>+<<]>[-<+>]<<]suppose que les entrées sont dans les deux premières positions de la bande, place la sortie en position 3

ymbirtt
la source