Tính toán CRC32 Hash


14

Tín dụng

Thử thách này bắt nguồn từ @miles .


Tạo một hàm tính toán hàm băm CRC32 của chuỗi đầu vào. Đầu vào sẽ là một chuỗi ASCII có độ dài bất kỳ. Đầu ra sẽ là hàm băm CRC32 của chuỗi đầu vào đó.

Giải trình

Thuật toán của CRC32 và CRC khác về cơ bản là giống nhau, vì vậy chỉ CRC3 sẽ được trình bày ở đây.

Đầu tiên, bạn có đa thức trình tạo, thực sự là số nguyên 4 bit [n + 1] (sẽ là 33 bit trong CRC32).

Trong ví dụ này, đa thức máy phát là 1101.

Sau đó, bạn sẽ có chuỗi được băm, trong ví dụ này sẽ là 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^

Phần còn lại thu được tại (21), khi vùng 1 bằng 0, đó là 001kết quả của hàm băm CRC3.

Thông số kỹ thuật

  • Đa thức máy phát là 0x104C11DB7, hoặc 0b100000100110000010001110110110111, hoặc 4374732215.
  • Đầu vào có thể là một chuỗi hoặc một danh sách các số nguyên hoặc bất kỳ định dạng hợp lý nào khác.
  • Đầu ra là một chuỗi hex hoặc chỉ là một số nguyên hoặc bất kỳ định dạng hợp lý nào khác.
  • Không được phép tích hợp tính toán băm CRC32.

Mục tiêu

Quy tắc tiêu chuẩn cho áp dụng.

Mã ngắn nhất sẽ thắng.

Các trường hợp thử nghiệm

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

Nếu tôi hiểu đúng, đây là thực hiện phép chia đa thức modulo 2 và tìm phần dư, tức là tương tự của mod trong phép nhân XOR .
xnor

1
Vâng. Đây không phải là xnor modulo, đây là xor modulo.
Nữ tu bị rò rỉ

Đối với CRC32, lần đầu tiên bạn có nối thêm 31 0 không?
xnor

Có - - - - - - - - -
Leaky Nun

1
@KennyLau bạn có thể ping mọi người bằng tên của họ, giống như trò chuyện.
Rɪᴋᴇʀ

Câu trả lời:


12

Intel x86, 34 30 29 27 byte

Lấy địa chỉ của chuỗi kết thúc bằng 0 trong ESI và trả về CRC trong EBX:

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

Tháo gỡ (cú pháp 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

Kết hợp các đề xuất từ ​​Peter Cordes để tiết kiệm thêm bốn byte. Điều này giả định một quy ước gọi trong đó cờ chỉ đường cho hướng dẫn chuỗi bị xóa khi nhập.

Kết hợp đề xuất của Peter Ferrie để sử dụng đẩy theo nghĩa đen và pop để tải một hằng số, tiết kiệm một byte.

Kết hợp đề xuất của Peter Ferrie để chuyển sang byte thứ hai của một xorl %eax, %ebxlệnh là một retllệnh, kết hợp với việc thay đổi giao diện của thường trình để lấy một chuỗi kết thúc bằng 0 thay vì độ dài, tiết kiệm tổng cộng hai byte.


Sử dụng quy ước gọi yêu cầu xóa cờ chỉ đường khi nhập cảnh, do đó bạn có thể lưu nội clddung (giống như tôi đã làm trong câu trả lời adler32 của mình ). Có phải là thông lệ để cho phép các quy ước gọi hoàn toàn tùy ý cho câu trả lời asm?
Peter Cordes

Dù sao, có vẻ như mã của bạn sẽ hoạt động như mã máy x86-64 và bạn có thể sử dụng quy ước gọi x86-64 SysV x32 để đếm edivà nhập con trỏ esi(có thể không được mở rộng bằng 0, vì vậy có thể làm mờ mọi thứ và yêu cầu Con trỏ không mở rộng 64 bit). (x32 để bạn có thể sử dụng toán học con trỏ 32 bit một cách an toàn, nhưng vẫn có quy ước gọi đăng ký-args. Vì bạn không sử dụng inc, nên không có nhược điểm nào ở chế độ dài.)
Peter Cordes

Bạn đã xem xét việc giữ edxtheo thứ tự đảo ngược byte? bswap edxchỉ có 2B. shr %edxlà 2B, giống như dịch chuyển trái của bạn với add %edx,%edx. Điều này có lẽ không hữu ích; Trừ khi nó cho phép tối ưu hóa nhiều hơn, bạn tiết kiệm 3B cho shl $24, %eax, nhưng bạn dành 4B cho xor %eax,%eaxlúc bắt đầu và bswap %edxkhi kết thúc. Zeroing eax không cho phép bạn sử dụng cdqvề 0 %edx, vì vậy, tổng thể nó là một rửa. Mặc dù vậy, nó sẽ hoạt động tốt hơn: nó tránh được sự chậm trễ / chậm đăng ký một phần trên mỗi lần lặp từ khi viết alvà sau đó đọc eaxvới shl. : P
Peter Cordes

1
Đã nhầm lẫn với câu hỏi Adler-32, có giới hạn độ dài. Câu hỏi này không có giới hạn chiều dài rõ ràng.
Đánh dấu Adler

1
Có thể có một cách để làm cho điều này ngắn hơn với hướng dẫn PCLMULQDQ. Tuy nhiên việc sử dụng nó có xu hướng cần rất nhiều hằng số, vì vậy có thể không.
Đánh dấu Adler


4

Ruby, 142 byte

Chức năng ẩn danh; lấy một chuỗi làm đầu vào, trả về một số nguyên.

->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
Bạn có thể thay đổi tên của bạn để mọi người có thể phân biệt chúng tôi? XD
Nữ tu bị rò rỉ

2
@KennyLau bạn phải thật kén chọn ... Được thôi
Giá trị mực

Tôi chỉ đùa thôi xd
Leaky Nun

4

Thạch , 23 byte

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

Đầu vào ở dạng một danh sách các số nguyên. Hãy thử trực tuyến! hoặc xác minh tất cả các trường hợp thử nghiệm .

Làm thế nào nó hoạt động

Trong khi Jelly có XOR bitwise, việc đệm đầu vào bằng số 0 và căn chỉnh đa thức với chữ số nhị phân quan trọng nhất thực hiện phương pháp này, sử dụng danh sách các bit thay vào đó, ngắn hơn một chút.

ḅ⁹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 byte

q256b32m<{Yb4374732215Yb.^Yb_Yb32>}g

Kiểm tra nó ở đây.

Giải trình

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>.^}*Ybtiết kiệm một vài byte.
Dennis

@Dennis Điều đó thực sự thông minh, hãy thoải mái biến nó thành một câu trả lời riêng biệt. :)
Martin Ender

3

Bình thường, 28 byte

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

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Giải trình:

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 byte

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)

Việc thiếu toán tử XOR 33 bit, hoặc thậm chí là toán tử XOR 32 bit không dấu, là không có ích.


1

CJam, 33 byte

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

Đầu vào ở dạng chuỗi. Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.