Berechne CRC32 Hash


14

Credits

Diese Herausforderung ging von @miles aus .


Erstellen Sie eine Funktion, die den CRC32-Hash einer Eingabezeichenfolge berechnet. Die Eingabe ist eine ASCII-Zeichenfolge beliebiger Länge. Die Ausgabe ist der CRC32-Hash dieser Eingabezeichenfolge.

Erläuterung

Der Algorithmus von CRC32 und anderen CRCs ist im Wesentlichen derselbe, sodass hier nur CRC3 gezeigt wird.

Erstens haben Sie das Generatorpolynom, das eigentlich eine 4-Bit-Ganzzahl [n + 1] ist (würde in CRC32 33-Bit betragen).

In diesem Beispiel ist das Generatorpolynom 1101.

Dann haben Sie die Zeichenfolge, die gehasht werden soll, was in diesem Beispiel der Fall wäre 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^

Der Rest, der erhalten wird (21), wenn der Bereich 1 Null ist 001, was das Ergebnis des CRC3-Hash ist.

Technische Daten

  • Das Generatorpolynom ist 0x104C11DB7oder 0b100000100110000010001110110110111oder 4374732215.
  • Die Eingabe kann eine Zeichenfolge oder eine Liste von Ganzzahlen oder ein anderes vernünftiges Format sein.
  • Die Ausgabe kann eine hexadezimale Zeichenfolge, eine Ganzzahl oder ein anderes vernünftiges Format sein.
  • Built-Ins, die den CRC32-Hash berechnen, sind nicht zulässig.

Tor

Es gelten die Standardregeln für .

Der kürzeste Code gewinnt.

Testfälle

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

Wenn ich das richtig verstehe, macht dies Polynomdivision Modulo 2 und findet den Rest, dh das Analogon von Mod in der XOR-Multiplikation .
xnor

1
Ja. Dies ist jedoch nicht xor modulo, sondern xor modulo.
Undichte Nonne

Fügen Sie für CRC32 zuerst 31 0 hinzu?
xnor

Ja - - - - - - - - -
Undichte Nonne

1
@KennyLau Du kannst Leute mit ihrem Namen anpingen, genau wie im Chat.
1.

Antworten:


12

Intel x86, 34 30 29 27 Bytes

Nimmt die Adresse des nullterminierten Strings in ESI und gibt den CRC in EBX zurück:

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

Demontage (AT & T-Syntax):

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

Vorschläge von Peter Cordes einfließen lassen, um weitere vier Bytes einzusparen. Dies setzt eine Aufrufkonvention voraus, bei der das Richtungsflag für Zeichenfolgenbefehle bei der Eingabe gelöscht wird.

Vorschlag von Peter Ferrie, Push-Literal und Pop zu verwenden, um eine Konstante zu laden und ein Byte zu sparen.

Einbeziehung des Vorschlags von Peter Ferrie, zum zweiten Byte eines xorl %eax, %ebxBefehls zu springen, der ein Befehl ist retl, kombiniert mit dem Ändern der Schnittstelle der Routine, um einen nullterminierten String anstelle der Länge zu verwenden, wodurch insgesamt zwei Bytes eingespart werden.


Verwenden Sie eine Aufrufkonvention, bei der das Richtungsflag bei der Eingabe gelöscht werden muss, damit Sie das cldInsn speichern können (wie ich es in meiner adler32-Antwort getan habe ). Ist es üblich, völlig willkürliche Anrufkonventionen für asm-Antworten zuzulassen?
Peter Cordes

Wie auch immer, es sieht so aus, als würde Ihr Code als x86-64-Maschinencode funktionieren, und Sie könnten die x86-64-SysV-x32-Aufrufkonvention verwenden, um die Anzahl ediund den Zeiger aufzunehmen esi(möglicherweise nicht null-erweitert, also möglicherweise Fudge-Dinge und erfordern Sie eine 64bit zero-extended pointer). (x32, damit Sie sicher 32-Bit-Zeiger-Mathematik verwenden können, aber immer noch die Aufrufkonvention register-args haben. Da Sie diese nicht verwenden inc, gibt es keinen Nachteil für den Long-Modus.)
Peter Cordes

Haben Sie darüber nachgedacht, edxdie Reihenfolge der Bytes umzukehren? bswap edxist nur 2B. shr %edxist 2B, genau wie Ihre Linksverschiebung mit add %edx,%edx. Das ist wahrscheinlich nicht hilfreich; Sofern es keine weitere Optimierung ermöglicht, sparen Sie 3B für die shl $24, %eax, aber Sie geben 4B für xor %eax,%eaxam Anfang und bswap %edxam Ende aus. Beim Nullstellen von eax können Sie den Wert cdqauf Null setzen %edx. Insgesamt handelt es sich also um eine Wäsche. Es würde jedoch eine bessere Leistung erbringen : Es vermeidet, dass das Teilregister bei jeder Iteration blockiert oder verlangsamt wird, wenn mit shl geschrieben alund dann gelesen eaxwird. : P
Peter Cordes

1
Wurde mit der Adler-32-Frage verwechselt, die eine Längenbeschränkung hat. Diese Frage hat keine explizite Längenbeschränkung.
Mark Adler

1
Es gibt möglicherweise eine Möglichkeit, dies mit der Anweisung PCLMULQDQ zu verkürzen. Seine Verwendung benötigt jedoch tendenziell viele Konstanten, möglicherweise auch nicht.
Mark Adler


4

Rubin, 142 Bytes

Anonyme Funktion; Nimmt einen String als Eingabe, gibt eine Ganzzahl zurück.

->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
Können Sie Ihren Namen ändern, damit die Leute uns unterscheiden können? XD
Leaky Nun

2
@KennyLau müssen Sie so wählerisch sein ... OK gut
Value Ink

Ich war nur ein Scherz xd
Leaky Nun

4

Jelly , 23 Bytes

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

Die Eingabe erfolgt in Form einer Liste von ganzen Zahlen. Probieren Sie es online! oder überprüfen Sie alle Testfälle .

Wie es funktioniert

Während Jelly bitweises XOR hat, macht das Auffüllen der Eingabe mit Nullen und das Ausrichten des Polynoms mit der höchstwertigen Binärziffer diesen Ansatz, der stattdessen Bitlisten verwendet, ein bisschen kürzer.

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

q256b32m<{Yb4374732215Yb.^Yb_Yb32>}g

Teste es hier.

Erläuterung

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>.^}*Ybspart ein paar Bytes.
Dennis

@ Tennis Das ist wirklich klug, zögern Sie nicht, es eine separate Antwort zu machen. :)
Martin Ender

3

Pyth, 28 Bytes

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

Probieren Sie es online aus: Demo oder Test Suite

Erläuterung:

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)

Das Fehlen eines 33-Bit-XOR-Operators oder sogar eines vorzeichenlosen 32-Bit-XOR-Operators ist nicht hilfreich.


1

CJam, 33 Bytes

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

Die Eingabe erfolgt in Form einer Zeichenfolge. Probieren Sie es online!

Wie es funktioniert

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.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.