256要素のフィールドを定義する


14

数学の分野とは、特定の公理(Wikipediaで説明。以下も参照)を満たすように、加算および乗算演算が定義された一連の数値です。

有限体はp n個の要素を持つことができます。ここでpは、素数でありn、自然数です。この課題では、p = 2とを使用してn = 8、256個の要素を持つフィールドを作成しましょう。

フィールドの要素は、0およびを含む範囲内の連続した整数でなければなりません1

  • -128 ... 127
  • 0 ... 255
  • または他のそのような範囲

フィールドの公理を満たすように、抽象「加算」および抽象「乗算」のために、2つの関数(またはそれがより簡単な場合はプログラム)を定義します。a(x,y)m(x,y)

  • 一貫性:同じ引数で呼び出されたときに同じ結果a(x,y)m(x,y)生成します
  • 閉鎖性:aおよびの結果はm、関連する範囲の整数です
  • 連想は:いずれかのためにxyおよびz範囲内、a(a(x,y),z)に等しいですa(x,a(y,z))。同じm
  • 可換性:任意用x及びy範囲内には、a(x,y)に等しいですa(y,x)。同じm
  • 分配性:いずれかのためにxyおよび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

名前amは単なる例です。他の名前または名前のない関数を使用できます。あなたの答えのスコアはのためのバイトの長さの和であるam

組み込み関数を使用する場合は、その関数が生成する結果を言葉で説明してください(たとえば、乗算表を提供する)。


3
@LeakyNun "addition"は、上記の特性を満たす単なる抽象操作です。上記の公理が満たされa(2,1) = 3a(2,1) = 5いる限り、の必要はありません。a有理数の分野などで慣れ親しんでいる通常の加算で何もする必要はありません。
マーティンエンダー

2
可換環は簡単です。フィールド...それほど簡単ではありません。
ニール

何か問題はありa=+ m=×ますか?
アダム

4
@Adámはい-2の場合、逆数はありませんm=×
-Sp3000

回答:


4

Hoon、22バイト

[dif pro]:(ga 8 283 3)

Hoonに++gaは、AES実装で使用するガロア体を作成する関数が既にあります。これは、2つのプログラムを使用する代わりに、2つの関数のタプルを返します。

ドメインで動作します [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

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

私たちの1人は変更する必要があります:P
Mego

@Mego Hah、まあ...他のアプローチを見つけることができるかどうか試してみます。しかし、打つのは難しいかもしれません。
Sp3000

1
どの多項式に基づいていますか?
feersum

1
@LSpice実行するm(2,128)と、27 = 283-256になる多項式を簡単に見つけることができるので、多項式はであることがわかりますx^8 + x^4 + x^3 + x + 1
feersum

1
@LSpice Neilの答えでは、彼はアルゴリズムのソースとしてWikipediaページを提供しているので、おそらく誰もがそれを読んだでしょう。しかし、この表現では8次の最小の既約多項式であるため、とにかくコードゴルフの最も明白な選択です。
feersum

6

JavaScript(ES6)、10 + 49 = 59バイト

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

ドメインは0〜255です。ソース


2
おそらく、使用している範囲を指定する必要があります。
マーティンエンダー

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

GF2P8MULBIce Lake CPUで新しい命令を使用します。

この命令は、有限フィールドGF(2 8)の要素を乗算し、最初のソースオペランドのバイト(フィールド要素)と2番目のソースオペランドの対応するバイトを操作します。体GF(2 8)は、多項式x 8 + x 4 + x 3 + x + 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、16進数で表される通常の多項式を含む標準アルゴリズムです1b。「乗算」コードは、結果をに蓄積しedxます。完了すると、それはeax(戻り値を保持する従来のレジスタ)に移動する追加コードにフォールスルーします。その時点でクリアされるため、xorwith ecxはノーオペレーションecxです。

特有の機能の1つはループです。ゼロをチェックする代わりに

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を法としてすべてを行います。

追加:[->+<]、入力がテープの最初の2つの位置にあると想定し、出力を位置0に配置します。

乗算:[->[->+>+<<]>[-<+>]<<]は、入力がテープの最初の2つの位置にあると想定し、出力を位置3に配置します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.