CRC32ハッシュの計算


14

クレジット

このチャレンジは@milesから始まりました


入力文字列のCRC32ハッシュを計算する関数を作成します。入力は、任意の長さのASCII文字列です。出力は、その入力文字列のCRC32ハッシュになります。

説明

CRC32と他のCRCのアルゴリズムは基本的に同じであるため、ここではCRC3のみを示します。

まず、生成多項式があります。これは実際には4ビットの[n + 1]整数です(CRC32では33ビットになります)。

この例では、生成多項式は1101です。

次に、ハッシュされる文字列があります00010010111100101011001101。この例ではになります。

00010010111100101011001101|000 (1)    append three [n] "0"s
   1101                        (2)    align with highest bit
00001000111100101011001101|000 (3)    XOR (1) and (2)
    1101                       (4)    align with highest bit
00000101111100101011001101|000 (5)    XOR (3) and (4)
     1101                      (6)    align with highest bit
00000011011100101011001101|000 (7)    XOR (5) and (6)
      1101                     (8)    align with highest bit
00000000001100101011001101|000 (9)    XOR (7) and (8)
          1101                 (10)   align with highest bit
00000000000001101011001101|000 (11)   XOR (9) and (10)
             1101              (12)   align with highest bit
00000000000000000011001101|000 (13)   XOR (11) and (12)
                  1101         (14)   align with highest bit
00000000000000000000011101|000 (15)   XOR (13) and (14)
                     1101      (16)   align with highest bit
00000000000000000000000111|000 (17)   XOR (15) and (16)
                       110 1   (18)   align with highest bit
00000000000000000000000001|100 (19)   XOR (17) and (18)
                         1 101 (20)   align with highest bit
00000000000000000000000000|001 (21)   XOR (19) and (20)
^--------REGION 1--------^ ^2^

(21)領域1がゼロの場合、で得られた剰余001は、CRC3ハッシュの結果になります。

スペック

  • 生成多項式は0x104C11DB7、または0b100000100110000010001110110110111、または4374732215です。
  • 入力は、文字列または整数のリスト、またはその他の適切な形式にすることができます。
  • 出力は、16進文字列または整数のみ、またはその他の適切な形式です。
  • CRC32ハッシュを計算するビルトインは許可されていません。

ゴール

標準ルールが適用されます。

最短のコードが優先されます。

テストケース

input         output      (hex)
"code-golf"   147743960   08CE64D8
"jelly"       1699969158  65537886
""            0           00000000

私が正しく理解している場合、これは2を法とする多項式除算を行い、剰余、つまりXOR乗算のmodの類似物を見つけています。
xnor

1
うん。ただし、これはxnorモジュロではなく、xorモジュロです。
漏れの修道女

CRC32の場合、最初に31個の0を追加しますか?
-xnor

はい– – – – – – – – –
Leaky Nun

1
@KennyLauチャットのように、名前で人々にpingを送信できます。
Rɪᴋᴇʀ

回答:


12

インテルx86の、34 30 29 27バイト

ESIでゼロで終了する文字列のアドレスを取得し、ECXでCRCを返します。

31 db ac c1 e0 18 74 01 31 c3 6a 08 59 01 db 73 
06 81 f3 b7 1d c1 04 e2 f4 eb e7

逆アセンブリ(AT&T構文):

00000000    xorl    %ebx, %ebx
00000002    lodsb   (%esi), %al
00000003    shll    $24, %eax
00000006    je      0x9
00000008    xorl    %eax, %ebx
0000000a    pushl   $8
0000000c    popl    %ecx
0000000d    addl    %ebx, %ebx
0000000f    jae     0x17
00000011    xorl    $0x4c11db7, %ebx
00000017    loop    0xd
00000019    jmp     0x2
0000001b

さらに4バイトを節約するために、Peter Cordesからの提案を取り入れます。これは、文字列命令の方向フラ​​グがエントリでクリアされる呼び出し規約を前提としています。

プッシュリテラルとポップを使用して定数をロードし、1バイトを節約するというピーターフェリーの提案を取り入れています。

xorl %eax, %ebx命令である命令の2番目のバイトにジャンプするためのPeter Ferrieの提案を組み込みretl、長さの代わりにゼロで終了する文字列を取るようにルーチンのインターフェイスを変更し、合計2バイトを節約します。


入力時に方向フラグをクリアする必要がある呼び出し規則を使用して、cldinsn を保存できるようにします(adler32 answerで行っように)。asm回答に対して完全に任意の呼び出し規約を許可するのは通常の慣行ですか?
ピーターコルド

とにかく、コードはx86-64マシンコードとして機能するように見えます。x86-64SysV x32呼び出し規約を使用して、カウントを取得ediし、ポインターを入力esiできます(ゼロ拡張ではない可能性があります。 64ビットのゼロ拡張ポインター)。(x32なので、32ビットポインター数学を安全に使用できますが、register-args呼び出し規約は引き続き使用できます。使用しないのでinc、ロングモードにマイナス面はありません。)
Peter Cordes

edxバイトを逆順にすることを検討しましたか? bswap edx2Bのみです。 shr %edxは2Bで、左シフトと同じadd %edx,%edxです。これはおそらく役に立たないでしょう。より多くの最適化を有効にしない限り、のために3Bを節約しますshl $24, %eaxxor %eax,%eax、最初とbswap %edx最後に4Bを費やします。eax cdqをゼロ%edxにすることでzero を使用できるようになるため、全体としては洗浄になります。ただし、パフォーマンスは向上します。shlを使用して書き込みalと読み取りeaxを繰り返すたびに、部分レジスタのストール/スローダウンが回避されます。:P
ピーターコーデス

1
長さの制限があるAdler-32の質問と混同してしまいました。この質問には、明示的な長さの制限はありません。
マークアドラー

1
PCLMULQDQ命令でこれを短くする方法があるかもしれません。ただし、その使用には多くの定数が必要になる傾向があるため、おそらく必要ではありません。
マークアドラー


4

Ruby、142バイト

無名関数; 入力として文字列を受け取り、整数を返します。

->s{z=8*i=s.size;r=0;h=4374732215<<z
l=->n{j=0;j+=1 while 0<n/=2;j}
s.bytes.map{|e|r+=e*256**(i-=1)};r<<=32
z.times{h/=2;r^=l[h]==l[r]?h:0}
r}

2
人々が私たちを区別できるように名前を変更できますか?XD
漏れ修道女

2
@KennyLauあなたはとてもうるさくなければなりません... OK罰金
バリューインク

私はちょうどxdを冗談でした
リーキー修道女

4

ゼリー、23バイト

ḅ⁹Bµ4374732215B×ḢḊ^µL¡Ḅ

入力は整数のリストの形式です。オンラインでお試しください!またはすべてのテストケースを確認します

使い方

Jellyにはビット単位のXORがありますが、入力にゼロをパディングし、多項式を最上位の2進数字に揃えることで、ビットのリストを使用するこのアプローチが少し短くなります。

ḅ⁹Bµ4374732215B×ḢḊ^µL¡Ḅ  Main link. Argument: A (list of bytes)

ḅ⁹                       Convert A from base 256 to integer.
  B                      Convert the result to binary, yielding a list.
   µ                     Begin a new, monadic chain. Argument: B (list of bits)
    4374732215B          Convert the integer to binary, yielding a list.
                Ḣ        Pop and yield the first, most significant bit of B.
               ×         Multiply each bit in the polynomial by the popped bit.
                 ^       Compute the element-wise XOR of both lists.
                         If one of the lists is shorter, the elements of the other
                         lists do not get modified, thus avoiding the necessity
                         of right-padding B with zeroes.
                  µ      Convert the previous chain into a link.
                   L¡    Execute the chain L times, where L is the number of bits
                         in the original bit list.
                     Ḅ   Convert from binary to integer.


3

CJam、37 36バイト

q256b32m<{Yb4374732215Yb.^Yb_Yb32>}g

ここでテストしてください。

説明

q               e# Read input.
256b            e# Convert to single number by treating the character codes
                e# as base-256 digits.
32m<            e# Left-shift the number by 32 bits, effectively appending 32
                e# zeros to the binary representation.
{               e# While the condition on top of the stack is truthy...
  Yb            e#   Convert the number to base 2.
  4374732215Yb  e#   Convert the polynomial to base 2.
  .^            e#   Take the bitwise XOR. If the number is longer than the
                e#   polynomial, the remaining bits will be left unchanged.
  Yb            e#   Convert the list back from base 2, effectively stripping
                e#   leading zeros for the next iteration.
  _             e#   Duplicate the result.
  Yb            e#   Convert back to base 2.
  32>           e#   Remove the first 32 bits. If any are left, continue the loop.
}g

q256bYb_,{(4374732215Ybf*1>.^}*Yb数バイト節約します。
デニス

@Dennisそれは本当に賢いので、自由に答えてください。:)
マーティンエンダー

3

Pyth、28バイト

uhS+GmxG.<C"Á·"dlhG.<Cz32

オンラインで試す:デモンストレーションまたはテストスイート

説明:

uhS+GmxG.<C"..."dlhG.<Cz32   implicit: z = input string
                      Cz     convert to number
                    .<  32   shift it by 32 bits
u                            apply the following expression to G = ^,
                             until it get stuck in a loop:
     m           lhG            map each d in range(0, log2(G+1)) to:
          C"..."                   convert this string to a number (4374732215)
        .<      d                  shift it by d bits
      xG                           xor with G
   +G                           add G to this list
 hS                             take the minimum as new G

2

JavaScript(ES6)、180バイト

f=(s,t=(s+`\0\0\0\0`).replace(/[^]/g,(c,i)=>(c.charCodeAt()+256*!!i).toString(2).slice(!!i)))=>t[32]?f(s,t.replace(/.(.{32})/,(_,m)=>(('0b'+m^79764919)>>>0).toString(2))):+('0b'+t)

33ビットXOR演算子、または署名されていない32ビットXOR演算子さえ欠けていると、役に立ちません。


1

CJam、33バイト

q256bYb_,{(4374732215Ybf*1>.^}*Yb

入力は文字列の形式です。オンラインでお試しください!

使い方

q                                  Read all input from STDIN.
 256bYb                            Convert it from base 256 to base 2.
       _,{                   }*    Compute the length and repeat that many times:
          (                          Shift out the first bit.
           4374732215Yb              Convert the integer to base 2.
                       f*            Multiply each bit by the shifted out bit.
                         1>          Remove the first bit.
                           .^        Compute the element-wise XOR of both lists.
                                     If one of the lists is shorter, the elements
                                     of the other lists do not get modified, thus
                                     avoiding the necessity of right-padding B with
                                     zeroes.
                               Yb  Convert the final result from base 2 to integer.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.