CRC32 Karma değerini hesaplama


14

Kredi

Bu meydan okuma miles kaynaklıdır .


Bir giriş dizesinin CRC32 karmasını hesaplayan bir işlev oluşturun. Giriş, herhangi bir uzunlukta bir ASCII dizesi olacaktır. Çıktı, o giriş dizesinin CRC32 karması olacaktır.

açıklama

CRC32 ve diğer CRC'nin algoritmaları esasen aynıdır, bu nedenle burada sadece CRC3 gösterilecektir.

İlk olarak, aslında bir 4-bit [n + 1] tamsayı olan jeneratör polinomuna sahipsiniz (CRC32'de 33-bit olacaktır).

Bu örnekte, jeneratör polinomu 1101.

Sonra, bu örnekte, karma olacak dizeye sahip olacaksınız 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^

Elde edilen geri kalan (21)bölgesi 1 olan, sıfır olduğu zaman, 001, CRC3 karma sonucu olacaktır.

gözlük

  • Jeneratör polinomu 0x104C11DB7, veya 0b100000100110000010001110110110111, veya 4374732215.
  • Giriş, bir dize veya bir tamsayı listesi veya başka bir makul biçim olabilir.
  • Çıktı bir onaltılık dize veya yalnızca bir tam sayı veya başka bir makul biçim olabilir.
  • CRC32 karmasını hesaplayan yerleşik öğelere izin verilmez.

Hedef

golfü için standart kurallar geçerlidir.

En kısa kod kazanır.

Test senaryoları

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

Doğru anlıyorsam, bu polinom bölünme modulo 2 yapıyor ve geri kalanını, yani XOR çarpımında modun analoğunu buluyor .
xnor

1
Evet. Bu xnor modulo değil , bu xor modulo.
Leaky Nun

CRC32 için önce 31 0 ekler misiniz?
xnor

Evet - - - - - - - - -
Sızan Rahibe

1
@KennyLau tıpkı sohbet gibi insanlara isimleriyle ping atabilirsiniz.
Rɪᴋᴇʀ

Yanıtlar:


12

Intel x86, 34 30 29 27 bayt

ESI'de sıfır sonlandırılmış dizenin adresini alır ve EBX'te CRC'yi döndürür:

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

Sökme (AT&T sözdizimi):

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

Dört bayt daha tasarruf etmek için Peter Cordes'dan öneriler içeriyor. Bu, dize talimatları için yön bayrağının girişte silindiği bir çağrı kuralı olduğunu varsayar.

Peter Ferrie'nin sabit bir yük yüklemek için itme değişmezi ve pop kullanma önerisini ekleyerek bir bayt tasarrufu sağlar.

Peter Ferrie'nin xorl %eax, %ebxtalimat olan bir komutun ikinci baytına atlamasını önermek, retluzunluk yerine sıfır sonlu bir dize almak için rutin arayüzünü değiştirmek ve toplamda iki bayt tasarruf etmek.


Eğer kaydedebilirsiniz böylece, girişteki temizlenecek yön bayrağı gerektiren bir çağrı kuralı kullanın cld(Ben gibi insn benim Adler32 cevap ). Asm cevapları için tamamen keyfi çağrı kurallarına izin vermek normal bir uygulama mıdır?
Peter Cordes

Her neyse, kodunuz x86-64 makine kodu olarak çalışacak gibi görünüyor ve saymak edive işaretçi almak için x86-64 SysV x32 çağrı kuralını kullanabilirsiniz esi(belki sıfır genişletilmiş değil, belki bir şeyleri yumuşatmak ve bir 64bit sıfır genişletilmiş işaretçi). (x32 böylece 32bit işaretçi matematiğini güvenle kullanabilirsiniz, ancak yine de register-args çağırma kuralına sahipsiniz. incKullanmadığınız için uzun modun dezavantajı yoktur.)
Peter Cordes

edxBayt-ters sırayla saklamayı düşündünüz mü ? bswap edxsadece 2B'dir. shr %edx2B, sol kaydırma ile aynı add %edx,%edx. Bu muhtemelen yardımcı olmaz; Daha fazla optimizasyon sağlamadığı sürece, için 3B tasarruf edersiniz shl $24, %eax, ancak xor %eax,%eaxbaşlangıçta ve bswap %edxsonunda 4B harcarsınız . Sıfırlama eax cdqsıfıra kullanmanıza izin verir %edx, bu yüzden genel olarak bir yıkama. Yine de daha iyi performans gösterecektir: her yinelemede kısmi-kayıt duraklama / yavaşlamasının yazıdan alsonra eaxshl ile okunmasını önler . : P
Peter Cordes

1
Uzunluk sınırı olan Adler-32 sorusuyla karıştırıldım. Bu sorunun açık bir uzunluk sınırı yok.
Mark Adler

1
PCLMULQDQ komutuyla bunu kısaltmanın bir yolu olabilir. Bununla birlikte, kullanımı çok sabitlere ihtiyaç duyma eğilimindedir, bu yüzden muhtemelen değil.
Mark Adler


4

Ruby, 142 bayt

Anonim işlev; bir dizeyi girdi olarak alır, bir tamsayı döndürür.

->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
İnsanların bizi ayırt edebilmesi için adınızı değiştirebilir misiniz? XD
Sızdıran Rahibe

2
@KennyLau çok seçici olmalısın ... Tamam iyi
Değer Mürekkep

Sadece şaka yapıyordum xd
Leaky Nun

4

Jöle , 23 bayt

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

Girdi, tamsayıların bir listesi biçimindedir. Çevrimiçi deneyin! veya tüm test senaryolarını doğrulayın .

Nasıl çalışır

Jelly, bitsel XOR'a sahipken, girişi sıfırlarla doldurmak ve polinomu en önemli ikili basamakla hizalamak, bunun yerine bit listelerini kullanan bu yaklaşımı biraz daha kısa hale getirir.

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

q256b32m<{Yb4374732215Yb.^Yb_Yb32>}g

Burada test edin.

açıklama

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>.^}*Ybbirkaç bayt kaydeder.
Dennis

@Dennis Bu gerçekten akıllı, ayrı bir cevap yapmaktan çekinmeyin. :)
Martin Ender

3

Pyth, 28 bayt

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

Çevrimiçi deneyin: Gösteri veya Test Paketi

Açıklama:

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 bayt

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 bit XOR operatörünün, hatta imzasız 32 bit XOR operatörünün olmaması yararsızdır.


1

CJam, 33 bayt

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

Girdi bir dize biçimindedir. Çevrimiçi deneyin!

Nasıl çalışır

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.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.