Определить поле с 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
  • Inverse: для любого 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=×?
Адам

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
Мего

@ Мего Ха, хорошо ... Я попробую и посмотрю, смогу ли я найти другие подходы. Хотя это может быть трудно победить.
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]

Тестирование:

=+  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(обычный регистр для хранения возвращаемого значения); xorс ecxявляется не-оп, потому что в этот момент ecxочищается.

Одна особенность - это петля. Вместо проверки на ноль

cmp ecx, 0
jne myloop

он использует специальную loopинструкцию. Но эта инструкция уменьшает «счетчик» цикла перед сравнением его с 0. Чтобы компенсировать это, код увеличивает его перед использованием loopинструкции.


0

Mathematica 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}
*)

NB Должен быть в состоянии использовать любой {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 Вы можете использовать его точно так же, как раньше, я просто использовал ±вместо 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.