คำนวณแฮช CRC32


14

เครดิต

ความท้าทายนี้มาจาก@miles


สร้างฟังก์ชันที่คำนวณแฮช CRC32 ของสตริงอินพุต อินพุตจะเป็นสตริง ASCII ของความยาวใด ๆ เอาต์พุตจะเป็นแฮช CRC32 ของสตริงอินพุตนั้น

คำอธิบาย

อัลกอริทึมของ CRC32 และ CRC อื่น ๆ นั้นมีความเหมือนกันดังนั้น CRC3 เท่านั้นที่จะแสดงที่นี่

ก่อนอื่นคุณมีพหุนามกำเนิดซึ่งจริงแล้วเป็นจำนวนเต็ม 4 บิต [n + 1] (จะเป็น 33 บิตใน CRC32)

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หรือหรือ0b1000001001100000100011101101101114374732215
  • อินพุตอาจเป็นสตริงหรือรายการจำนวนเต็มหรือรูปแบบที่เหมาะสมอื่น ๆ
  • เอาท์พุทเป็นสตริงฐานสิบหกหรือเพียงจำนวนเต็มหรือรูปแบบที่เหมาะสมอื่น ๆ
  • บิวด์อินที่คำนวณแฮช CRC32 ไม่ได้รับอนุญาต

เป้าหมาย

กฎระเบียบมาตรฐานสำหรับสมัคร

รหัสที่สั้นที่สุดชนะ

กรณีทดสอบ

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

ถ้าผมเข้าใจถูกต้องนี้จะทำพหุนามส่วนโมดูโล 2 และหาส่วนที่เหลือคืออะนาล็อกของ mod ในXOR คูณ
xnor

1
อ๋อ นี่ไม่ใช่xnor modulo แม้ว่านี่คือ xor modulo
Leun Nun

สำหรับ CRC32 คุณจะต่อท้าย 31 0 ก่อนหรือไม่
xnor

ใช่ - - - - - - - - -
แม่ชีที่รั่ว

1
@KennyLau คุณสามารถ ping คนที่มีชื่อเหมือนแชท
Rɪᴋᴇʀ

คำตอบ:


12

Intel x86, 34 30 29 27 ไบต์

ใช้ที่อยู่ของสตริงที่สิ้นสุดการเป็นศูนย์ใน ESI และส่งกลับ CRC ใน 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

การถอดชิ้นส่วน (ไวยากรณ์ของ 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

การรวมคำแนะนำจาก Peter Cordes เพื่อประหยัดอีกสี่ไบต์ สิ่งนี้ถือว่าเป็นหลักการเรียกที่ซึ่งทิศทางแฟล็กสำหรับคำสั่งสตริงถูกล้างเมื่อเข้า

การรวมคำแนะนำของ Peter Ferrie เพื่อใช้ push literal และ pop เพื่อโหลดค่าคงที่ช่วยประหยัดหนึ่งไบต์

คำแนะนำการผสมผสานของ Peter Ferrie เพื่อข้ามไปยังไบต์ที่สองของxorl %eax, %ebxคำสั่งซึ่งเป็นการretlรวมกับการเปลี่ยนอินเตอร์เฟสของรูทีนเพื่อใช้สตริงที่สิ้นสุดด้วยศูนย์แทนความยาวทำให้ประหยัดสองไบต์ทั้งหมด


ใช้แบบแผนการโทรที่ต้องการให้เคลียร์การตั้งค่าสถานะในรายการดังนั้นคุณสามารถบันทึกcldinsn (เหมือนกับที่ฉันทำในคำตอบ adler32 ของฉัน ) มันเป็นเรื่องปกติหรือไม่ที่จะอนุญาตให้อนุสัญญาการโทรโดยพลการสำหรับคำตอบ asm?
Peter Cordes

อย่างไรก็ตามดูเหมือนว่ารหัสของคุณจะทำงานเป็นรหัสเครื่อง x86-64 และคุณสามารถใช้การเรียกประชุม x86-64 SysV x32 เพื่อนับจำนวนediและตัวชี้ในesi(อาจจะไม่ขยายเป็นศูนย์ดังนั้นอาจทำให้เรื่องเหลวไหลและต้องมี ตัวชี้การขยายเป็นศูนย์ 64 บิต) (x32 เพื่อให้คุณสามารถใช้คณิตศาสตร์ตัวชี้ 32 บิตได้อย่างปลอดภัย แต่ยังมีการเรียกใช้การลงทะเบียนเนื่องจากคุณไม่ได้ใช้incไม่มีข้อเสียในโหมดยาว)
Peter Cordes

คุณคิดที่จะรักษาedxลำดับที่ตรงกันข้ามหรือไม่? bswap edxเป็นเพียง 2B shr %edxเป็น 2B, add %edx,%edxเช่นเดียวกับซ้ายกะของคุณด้วย สิ่งนี้อาจไม่เป็นประโยชน์ นอกจากจะช่วยให้การเพิ่มประสิทธิภาพมากขึ้นคุณประหยัด 3B สำหรับshl $24, %eaxแต่คุณใช้ 4B สำหรับxor %eax,%eaxตอนเริ่มต้นและbswap %edxตอนท้าย การ zeroing eax ทำให้คุณใช้งานได้cdqเป็นศูนย์%edx, โดยรวมดังนั้นมันจึงเป็นการล้าง มันจะทำงานได้ดีขึ้นแม้ว่ามันจะหลีกเลี่ยงแผงลงทะเบียนบางส่วน / การชะลอตัวของการทำซ้ำทุกครั้งจากการเขียนalแล้วอ่านeaxด้วย shl : P
Peter Cordes

1
สับสนกับคำถาม Adler-32 ซึ่งมีความยาวไม่เกิน คำถามนี้ไม่มีการจำกัดความยาวอย่างชัดเจน
Mark Adler

1
อาจมีวิธีทำให้คำสั่งนี้สั้นลงด้วยคำสั่ง PCLMULQDQ อย่างไรก็ตามการใช้มีแนวโน้มที่จะต้องมีค่าคงที่จำนวนมากดังนั้นอาจไม่
Mark Adler


4

ทับทิม 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
Leun Nun

2
@KennyLau คุณต้องจู้จี้จุกจิกมาก ... โอเคดี
หมึกมูลค่า

ฉันแค่ล้อเล่น xd
Leaky Nun

4

เยลลี่ 23 ไบต์

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

อินพุตอยู่ในรูปของรายการจำนวนเต็ม ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

มันทำงานอย่างไร

ในขณะที่เจลลี่มี bitor XOR การใส่อินพุตด้วย zeroes และการจัดตำแหน่งพหุนามกับเลขฐานสองที่สำคัญที่สุดทำให้วิธีนี้ซึ่งใช้รายการของบิตแทนซึ่งสั้นกว่าเล็กน้อย

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

@Dennis ที่ฉลาดจริง ๆ อย่าลังเลที่จะตอบคำถามแยกต่างหาก :)
Martin Ender

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)

การขาดตัวดำเนินการ XOR 33 บิตหรือแม้แต่ตัวดำเนินการ XOR ที่ไม่ได้ลงนาม 32 บิตนั้นไม่มีประโยชน์


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.