Визначте поле з 256 елементами


15

Поле в математиці є набором чисел, з операціями додавання і множення , визначених на ній, таким чином, що вони задовольняють певні аксіоми (описані в Вікіпедії, див також нижче).

Кінцеве поле може мати p n елементів, де pє простим числом і nє натуральним числом. У цьому виклику візьмемо p = 2і n = 8, тому зробимо поле з 256 елементами.

Елементи поля повинні бути послідовними цілими числами в діапазоні, що містить 0і 1:

  • -128 ... 127
  • 0 ... 255
  • або будь-який інший подібний діапазон

Визначте дві функції (або програми, якщо це простіше), a(x,y)для абстрактного "додавання" та m(x,y)для абстрактного "множення", щоб вони задовольняли аксіоми поля:

  • Послідовність: a(x,y)і m(x,y)дають однаковий результат, коли викликаються з однаковими аргументами
  • Закритість: Результат aі mє цілим числом у відповідному діапазоні
  • Асоціативність: для будь-якого x, yі zв діапазоні, a(a(x,y),z)дорівнює a(x,a(y,z)); те саме дляm
  • Комутативність: для будь-якого xі yв діапазоні a(x,y)дорівнює a(y,x); те саме дляm
  • Дистрибутивність: для будь-якого x, yі zв межах, m(x,a(y,z))так самоa(m(x,y),m(x,z))
  • Нейтральні елементи: для будь-якого xв діапазоні a(0,x)дорівнює xі m(1,x)дорівнюєx
  • Заперечення: для будь-якого xв діапазоні існує такий, yякий a(x,y)є0
  • Зворотне: для будь-якого x≠0в діапазоні існує таке, yщо m(x,y)є1

Назви aта mлише приклади; ви можете використовувати інші імена або неназвані функції. Оцінка вашої відповіді - це сума байтів для aта і m.

Якщо ви використовуєте вбудовану функцію, будь-ласка, також опишіть словами, результат яких вона створює (наприклад, надайте таблицю множення).


3
@LeakyNun "додавання" - це лише абстрактна операція, яка задовольняє наведеним вище властивостям. У цьому немає необхідності a(2,1) = 3, ви могли б мати a(2,1) = 5, доки зазначені вище аксіоми будуть задоволені. aне має нічого спільного із звичайним доповненням, до якого ви звикли, наприклад, із поля раціональних чисел.
Мартін Ендер

2
Комутативне кільце тривіальне. Поле ... не так просто.
Ніл

Чи щось не так a=+ m=×?
Adám

4
@ Adám Так - 2 не мав би зворотного, якщоm=×
Sp3000

Відповіді:


4

Intel x86-64 + AVX-512 + GFNI, 11 байт

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

Використовується нова GF2P8MULBінструкція щодо процесорів Ice Lake.

Інструкція множує елементи у кінцевому полі GF (2 8 ), що працює на байті (елемент поля) у першому операнді джерела та відповідному байті у другому операнді джерела. Поле GF (2 8 ) представлене в многочленному репрезентації з поліномом відновлення x 8 + x 4 + x 3 + x + 1.


13

Python 2, 11 + 45 = 56 байт

Додавання (11 байт):

int.__xor__

Множення (45 байт):

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

Приймає вхідні числа в діапазоні [0 ... 255]. Додавання просто порозрядне XOR, множення - це множення многочленів з коефіцієнтами в GF2 з російським селянином .

А для перевірки:

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

Одному з нас доведеться змінитись: P
Мего

@Mego Hah, ну ... я спробую подивитися, чи зможу я знайти інші підходи. Можливо, важко перемогти.
Sp3000

1
На якому многочлені він заснований?
feersum

1
@LSpice Тепер я усвідомлюю, що я можу легко знайти поліном, запустивши, m(2,128)що призводить до 27 = 283 - 256, тож ви правильні, а поліном є x^8 + x^4 + x^3 + x + 1.
feersum

1
@LSpice У відповіді Ніла він дає сторінку Вікіпедії як джерело алгоритму, тому, можливо, всі читають це. Але це все одно є найбільш очевидним вибором для кодового гольфу, оскільки це найменший невідводимий поліном ступеня 8 у цьому поданні.
feersum


4

Хун , 22 байти

[dif pro]:(ga 8 283 3)

У Hoon вже є функція, ++gaяка створює поля Галуа, для використання в реалізації AES. Це повертає кортеж з двох функцій замість використання двох програм.

Діє в домені [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"

Опублікувати таблицю множення було б гігантським, тому ось кілька випадкових тестів:

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

1

Машинний код IA-32, 22 байти

"Множення", 18 байт:

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

"Додавання", 4 байти:

92 33 c1 c3

Це трохи розтягує правила: у коді "множення" відсутній код виходу функції; він покладається на те, що код "додавання" знаходиться в пам'яті відразу після цього, тому він може "пропустити" Я зробив це, щоб зменшити розмір коду на 1 байт.

Вихідний код (може бути зібраний 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

Алгоритм є стандартним, що включає звичайний многочлен x^8 + x^4 + x^3 + x + 1, представлений шістнадцятковим числом 1b. Код "множення" акумулює результат у edx. Закінчивши, він потрапляє до коду додавання, який переміщує його до eax(звичайний регістр, щоб утримувати значення повернення); the xorз ecx- це не-оп, тому що в цей момент ecxочищається.

Одна особлива особливість - це петля. Замість перевірки нуля

cmp ecx, 0
jne myloop

в ньому використовується спеціальна loopінструкція. Але ця інструкція зменшує "лічильник" циклу, перш ніж порівнювати його з 0. Щоб компенсувати це, код збільшує його перед використанням loopінструкції.


0

Математика 155 байт

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]

Впровадження

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

додаткова перевірка:

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

Більше:

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

Примітка. Потрібно мати можливість використовувати будь-яке {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}місце замість 283.


Ну, ось на 13 байт менше: ±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](припускає, що джерело закодовано в ISO 8859-1)
Мартін Ендер

@MartinEnder не зовсім впевнений, як реалізувати вашу пропозицію
martin

@martin Ви можете використовувати його точно так само, як і раніше, я просто використовував ±замість цього fі pзамість цього o(звичайно, ви можете зберегти це як o, я просто використав, pщоб я міг перевірити їх обох), а потім зберег ще кілька байтів зі стандартним синтаксичні цукрові хитрощі.
Мартін Ендер

@MartinEnder може ±працювати так само f, як , але не p... не впевнений, де я помиляюся
март

Якщо ви скопіюєте його прямо з коментаря, там, де ваш браузер відображатиме розрив рядка в коментарі, можуть бути недруковані символи. Видаліть символи навколо цієї позиції після копіювання та повторно введіть їх. Якщо це не зробити, я не впевнений, де проблема ..
Мартін Ендер

-1

Brainfuck, 28 символів

На щастя, стандартний Brainfuck робить все за модулем 256.

Додавання:, [->+<]передбачає, що входи знаходяться в перших двох положеннях стрічки, розміщує вихід у позиції 0

Множення:, [->[->+>+<<]>[-<+>]<<]передбачає, що входи знаходяться у перших двох положеннях стрічки, розміщує вихід у позиції 3

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.