Zdefiniuj pole z 256 elementami


15

Pola w matematyce zbiór cyfr, z dodatkiem i namnażanie operacji zdefiniowanych na niego, tak że spełniają one pewne axioms (opisane w Wikipedia; patrz poniżej).

Skończony pole może mieć s n elementów, gdzie pjest liczbą pierwszą, a njest liczbą naturalną. W tym wyzwaniu weźmy, p = 2a n = 8więc stwórzmy pole z 256 elementami.

Elementami pola powinny być kolejne liczby całkowite w zakresie, który zawiera 0i 1:

  • -128 ... 127
  • 0 ... 255
  • lub jakikolwiek inny taki zakres

Zdefiniuj dwie funkcje (lub programy, jeśli jest to łatwiejsze), a(x,y)dla abstrakcyjnego „dodawania” i m(x,y)dla abstrakcyjnego „mnożenia”, tak aby spełniały aksjomaty pola:

  • Spójność: a(x,y)i m(x,y)dają ten sam wynik, gdy wywoływany z tymi samymi argumentami
  • Zamknięcie: Wynikiem ai mjest liczbą całkowitą w odpowiednim zakresie
  • Łączność: Dla każdego x, ya zw tym zakresie, a(a(x,y),z)wynosi a(x,a(y,z)); to samo dlam
  • Przemienność: dla dowolnego xi yw zakresie a(x,y)jest równa a(y,x); to samo dlam
  • Rozdzielność: dla każdego x, yi zw zakresie, m(x,a(y,z))jest równaa(m(x,y),m(x,z))
  • Elementy neutralne: dla dowolnego xz zakresu a(0,x)jest równe xi m(1,x)równex
  • Negacja: dla każdego xz tego zakresu istnieje taki, yktóry a(x,y)jest0
  • Odwrotny: dla każdego x≠0z tego zakresu istnieje taki, yktóry m(x,y)jest1

Nazwy ai msą tylko przykładami; możesz użyć innych nazw lub funkcji bez nazw. Wynik Twojej odpowiedzi to suma długości bajtów dla ai m.

Jeśli korzystasz z wbudowanej funkcji, opisz ją również słowami, które z niej wynikają (np. Podaj tabliczkę mnożenia).


3
„Dodawanie” @LeakyNun jest tutaj tylko abstrakcyjną operacją, która spełnia powyższe właściwości. Nie ma takiej potrzeby a(2,1) = 3, możesz mieć a(2,1) = 5tyle czasu, ile powyższe aksjomaty są spełnione. anie musi nic robić ze zwykłym dodatkiem, do którego jesteś przyzwyczajony, np. z zakresu liczb wymiernych.
Martin Ender

2
Pierścień przemienny jest trywialny. Pole ... nie takie łatwe.
Neil

Czy coś jest nie tak a=+ m=×?
Adám

4
@ Adám Tak - 2 nie miałoby odwrotności, gdybym=×
Sp3000

Odpowiedzi:


4

Intel x86-64 + AVX-512 + GFNI, 11 bajtów

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

Wykorzystuje nową GF2P8MULBinstrukcję dotyczącą procesorów Ice Lake.

Instrukcja zwielokrotnia elementy w polu skończonym GF ( 28 ), operując na bajcie (elemencie pola) w pierwszym operandzie źródłowym i odpowiednim bajcie w drugim operandzie źródłowym. Pole GF ( 28 ) jest reprezentowane w postaci wielomianu z wielomianem redukcyjnym x 8 + x 4 + x 3 + x + 1.


13

Python 2, 11 + 45 = 56 bajtów

Dodawanie (11 bajtów):

int.__xor__

Mnożenie (45 bajtów):

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

Przyjmuje liczby wejściowe z zakresu [0 ... 255]. Dodawanie jest tylko bitowe XOR, mnożenie to mnożenie wielomianów o współczynnikach w GF2 z chłopem rosyjskim .

I do sprawdzenia:

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

Jedno z nas będzie musiało się zmienić: P
Mego

@Mego Hah, cóż ... Spróbuję sprawdzić, czy mogę znaleźć inne podejścia. Może być jednak trudny do pokonania.
Sp3000,

1
Na którym wielomianu jest oparty?
feersum

1
@LSpice Teraz zdaję sobie sprawę, że mogę łatwo znaleźć wielomian, uruchamiając, m(2,128)co daje wynik 27 = 283 - 256, więc masz rację, a wielomian jest x^8 + x^4 + x^3 + x + 1.
feersum

1
@LSpice W odpowiedzi Neila podaje stronę Wikipedii jako źródło algorytmu, więc może wszyscy to przeczytają. Ale i tak jest to najbardziej oczywisty wybór dla golfa kodowego, ponieważ jest to najmniejszy nieredukowalny wielomian stopnia 8 w tej reprezentacji.
feersum

6

JavaScript (ES6), 10 + 49 = 59 bajtów

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

Domena to 0 ... 255. Źródło .


2
Prawdopodobnie powinieneś określić zakres, którego używasz.
Martin Ender

4

Hoon , 22 bajtów

[dif pro]:(ga 8 283 3)

Hoon ma już funkcję, ++gaktóra tworzy Pola Galois, do wykorzystania w implementacji AES. Zwraca krotkę dwóch funkcji zamiast używania dwóch programów.

Działa w domenie [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"

Zamieszczanie tabeli mnożenia byłoby gigantyczne, więc oto kilka przypadkowych przypadków testowych:

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

1

Kod maszynowy IA-32, 22 bajty

„Mnożenie”, 18 bajtów:

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

„Dodawanie”, 4 bajty:

92 33 c1 c3

Rozciąga to nieco reguły: w kodzie „mnożenia” brakuje kodu wyjścia funkcji; polega na tym, że kod „dodatkowy” jest w pamięci natychmiast, więc może „przewrócić się”. Zrobiłem to, aby zmniejszyć rozmiar kodu o 1 bajt.

Kod źródłowy (może być złożony przez 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

Algorytm jest standardowy, obejmujący zwykły wielomian x^8 + x^4 + x^3 + x + 1reprezentowany przez liczbę szesnastkową 1b. Kod „mnożenia” akumuluje wynik edx. Po zakończeniu przechodzi do kodu dodatkowego, który przenosi go do eax(rejestr konwencjonalny do przechowywania wartości zwracanej); xorz ecxoznacza brak operacji , ponieważ w tym momencie ecxjest wyczyszczone.

Jedną ze szczególnych cech jest pętla. Zamiast sprawdzać zero

cmp ecx, 0
jne myloop

korzysta z dedykowanej loopinstrukcji. Ale ta instrukcja zmniejsza „licznik” pętli przed porównaniem jej do 0. Aby to zrekompensować, kod zwiększa ją przed użyciem loopinstrukcji.


0

Mathematica 155 bajtów

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]

Realizacja

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

kontrola dodania:

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

Więcej:

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

NB Powinny być w stanie korzystać z dowolnego {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}zamiast 283.


Oto 13 bajtów mniej: ±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](zakłada, że ​​źródło jest zakodowane w ISO 8859-1)
Martin Ender

@MartinEnder nie do końca pewny, jak wdrożyć swoją sugestię
martin

@martin Możesz go używać dokładnie tak, jak wcześniej, właśnie użyłem ±zamiast fi pzamiast o(oczywiście możesz to zachować, ponieważ owłaśnie użyłem, paby móc przetestować oba), a następnie zapisałem kilka dodatkowych bajtów ze standardowym cukry syntaktyczne.
Martin Ender,

@MartinEnder może zacząć ±pracować tak samo jak f, ale nie p... nie jestem pewien, gdzie się mylę
martin

Jeśli skopiujesz go bezpośrednio z komentarza, mogą istnieć pewne niedrukowalne znaki wszędzie tam, gdzie przeglądarka wyświetla podział wiersza w komentarzu. Po skopiowaniu usuń znaki wokół tej pozycji i wpisz je ponownie. Jeśli to nie pomoże, nie jestem pewien, gdzie jest problem…
Martin Ender

-1

Brainfuck, 28 znaków

Na szczęście standardowy Brainfuck robi wszystko modulo 256.

Dodanie: [->+<]zakłada, że ​​wejścia znajdują się w pierwszych dwóch pozycjach taśmy, umieszcza wyjście w pozycji 0

Mnożenie: [->[->+>+<<]>[-<+>]<<]zakłada, że ​​wejścia znajdują się w pierwszych dwóch pozycjach taśmy, umieszcza wyjście w pozycji 3

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.