Adler-32 sağlama toplamını hesapla


32

Arka fon

Adler-32 , yaygın olarak kullanılan zlib kütüphanesinin (Adler tarafından da geliştirilen) bir parçası olan 1995 yılında Mark Adler tarafından icat edilen 32-bit bir sağlama toplamıdır. Adler-32, 32 bit döngüsel artıklık denetimi kadar güvenilir değildir , ancak - en azından yazılımda - uygulanması çok daha hızlı ve kolaydır.

Tanım

Let B = [b 1 , ⋯ b n ] bir bayt dizisi olabilir.

B'nin Adler-32 sağlama toplamı düşük + 65536 × yüksekliğin sonucu olarak tanımlanır , burada:

  • düşük: = ((1 + b 1 + ⋯ + b n ) mod 65521)

  • yüksek: = (((1 + b 1 ) + (1 + b 1 + b 2 ) + ⋯ (1 + b 1 + ⋯ + b n )) mod 65521)

Görev

Girdi olarak bir bayt dizisi verildiğinde, Adler-32 sağlama toplamını hesaplayın ve aşağıdakine uyun.

  • Girdiyi bir bayt veya tamsayı dizisi olarak veya bir dize olarak alabilirsiniz.

    Her iki durumda da, girişte yalnızca yazdırılabilir ASCII karakterlerine karşılık gelen baytlar ortaya çıkar.

    Girişin uzunluğunun 0 <uzunluk ≤ 4096 olduğunu kabul edersiniz .

  • Çıktıyı yazdırmayı seçerseniz, 256'yı da içeren herhangi bir pozitif tabanı kullanabilirsiniz.

    Tekli seçerseniz, tercümanın 16 GiB RAM'e sahip bir makinede 2 32 - 983056 baytlık çıktı işleyebildiğinden emin olun .

  • Adler-32 sağlama toplamını hesaplayan yerleşik ürünler yasaktır.

  • Standart kuralları geçerlidir.

Test durumları

String:     "Eagles are great!"
Byte array: [69, 97, 103, 108, 101, 115, 32, 97, 114, 101, 32, 103, 114, 101, 97, 116, 33]
Checksum:   918816254

String:     "Programming Puzzles & Code Golf"
Byte array: [80, 114, 111, 103, 114, 97, 109, 109, 105, 110, 103, 32, 80, 117, 122, 122, 108, 101, 115, 32, 38, 32, 67, 111, 100, 101, 32, 71, 111, 108, 102]
Checksum:   3133147946

String:     "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
Byte array: [126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126]
Checksum:   68095937

String:     <1040 question marks>
Byte array: <1040 copies of 63>
Checksum:   2181038080

7
Buradaki cevapların birçoğunun, toplamlar hesaplanıncaya kadar modulo işlemini ertelemesinden dolayı 32 veya 64-bit tam sayı toplamlarını aştıklarında büyük veya çok büyük giriş dizileriyle başarısız olacağını not edeceğim. Gerçekten uyumlu bir uygulama, toplamların taşmasını önlemek için modulo işlemini en azından periyodik olarak yapmak zorunda kalacaktır. 32-bit işaretli bir tamsayı sadece 4096 0xff'den sonra taşar. 64 bit işaretli bir tamsayı, 0xff'in 256 MiB değerinden sonra taşar.
Mark Adler

@MarkAdler Hm, adil nokta. Çözümlerin keyfi olarak uzun dizeler için çalışması gerektiğini belirtmediğim ve mevcut cevapları geçersiz kılmak istemediğim için, girişin uzunluğu için bir sınır belirleyeceğim.
Dennis,

@MarkAdler Önemli olduğunu sanmıyorum. Modül n * (n + 1) / 2 * 255 + n olduğundan önce en yüksek değerin yüksek olması nedeniyle, taşma işleminin (işaretli 32 bit tam sayılar) yalnızca 4104 veya daha fazla bayt ile olabileceğinden oldukça eminim . Bunun üzerine, meydan okuma girişi yazdırılabilir ASCII karakterlerine karşılık gelen baytlarla sınırlar.
Dennis,

Ayrıca, dillerin sayısal türlerini aşmasına izin verebiliriz ve yalnızca döndürülen sonucun, taşma için geçerli olan doğru sonuçla eşdeğer olmasını isteriz.
miller

1
@PeterCordes Evet, 32-bit ints dizileri mükemmel para cezası. En azından benim görüşüme göre, sunumlar algoritmayı golfe odaklamalı ve G / Ç'ye mümkün olduğunca az dikkat etmelidir.
Dennis,

Yanıtlar:


3

Jöle, 19 17 bayt

+\,S‘S€%65521ḅ⁹²¤

Çevrimiçi deneyin!

+\,S‘S€%65521ḅ⁹²¤    Main monadic chain. Takes array as only argument.

                     The array is shown here as [b1 b2 ... bn].
+\                   Reduce by addition (+) while returning immediate results.
                         yields [b1 b1+b2 ... b1+b2+...+bn].

  ,                  Concatenate with...
   S                 the sum of the argument.
                         yields [[b1 b1+b2 ... b1+b2+...+bn] b1+b2+...+bn].

    ‘                Increment [each].
                         yields [[1+b1 1+b1+b2 ... 1+b1+b2+...+bn] 1+b1+b2+...+bn].

     S€              Sum each list.
                         yields [[1+b1+1+b1+b2+...+1+b1+b2+...+bn] 1+b1+b2+...+bn].

       %65521        Modulo [each] by 65521.

             ḅ⁹²¤    Convert from base    65536    to integer.
              ⁹                        256
               ²                           squared

Daha da iyisi:⁹²¤
Dennis,

1
@Dennis O zaman 18-byte'ınızı aştım.
Sızdıran Rahibe,

1
Eh, sen outgolfed var ..
Çatlak Nun'ı

64

Mathematica, 46 bayt

{1,4^8}.Fold[##+{0,#&@@#}&,{1,0},#]~Mod~65521&

Bir tamsayı dizisi alan ve Adler-32'yi döndüren ve mil ve Martin'den bazı geliştirmelerle anonim bir işlev (açıklamalara bakın).

mil 'de 46 bayt , ancak daha hızlı:

{1,4^8}.{Tr@#+1,Tr[Accumulate@#+1]}~Mod~65521&

37
... Az önce kendi ünlü algoritmasını mı kullandın?
Mego

25
Biraz yıldız çarpması durumunda beni affet. Mütevazı küçük sitemizde yazılım mühendisliğinde bu kadar büyük bir isim görmeniz her gün değildir. Gemiye Hoşgeldiniz!
Mego

6
O kadar büyük değil.
Mark Adler,

3
Beni kastediyorsanız, bu ilk kez Adler-32'yi Mathematica'da uygulamayı düşündüm.
Mark Adler,

9
Belki de Code Golf'a katıldığınızdan beri bu çözümü hazır bulunduruyorsunuz, sorulmasını bekliyoruz. "En sonunda!" ;-)
Antti Haapala

13

Julia, 73 46 bayt

x->[sum(x)+1;sum(cumsum(x)+1)]%65521⋅[1;4^8]

Bu, bir diziyi kabul eden ve bir tamsayı döndüren adsız bir işlevdir. Aramak için değişkene atayın.

Bu birleştirme sum(x) + 1ve sum(cumsum(x) + 1)bir dizi halinde x, giriş dizidir ve Daha sonra 1 ve 4 ile nokta ürün hesaplamak her modulo 65521. almak 8 bize veren (sum(x) + 1) + 4^8 * sum(cumsum(x) + 1)tam olarak Adler-32 formülünün olan.

Çevrimiçi deneyin! (Tüm test durumlarını içerir)

Sp3000 ve Dennis sayesinde 27 bayt kurtarıldı!


Vay, bu çok zekice.
kedi,

@ cat'in zekâsı için teşekkür edecekleri Sp3000 ve Dennis'im var. :)
Alex A.

11

x86-64 makine kodu işlevi: 33 32 bayt (veya bunun yerine bir girişi olan 31 30 bayt )int[]char[]

x86-32 makine kodu işlevi: 31 bayt

GNU C satır içi kod parçası olarak: 2Bret 1B'yi (sadece insn) kaydeder .

Yorum yapan kaynak ve github'daki test sürücüsü

64bit sürümü, standart V (V86) 64 ABI sistemi ile doğrudan C'den çağrılabilir (istediğim reglarda hata elde etmek için 2 boş argüman kullanarak). Özel arama kuralları asm kodu için nadir değildir, bu yüzden bu bir bonus özelliktir.

32bit makine kodu 1B tasarruf sağlar, çünkü yüksek ve alçak yarımları birleştirmek push16/push16 => pop32sadece 32bit modunda çalışır. 32 bitlik bir işlevin özel bir çağrı kuralına ihtiyacı olacaktır. Buna karşı durmamalıyız, ancak C'den çağrı yapmak bir sarmalayıcı fonksiyonuna ihtiyaç duyuyor.

4096 ~(ASCII 126) bayt işlemden sonra high = 0x3f040000, low = 0x7e001. Yani highen anlamlı bit henüz belirlenmedi. Benim kod yararlanır, kayıt uzanan eaxiçine edx:eaxile cdqsıfırlama bir yolu olarak edx.

# See the NASM source below
0000000000401120 <golfed_adler32_amd64>:
  401120:       31 c0                   xor    eax,eax
  401122:       99                      cdq    
  401123:       8d 7a 01                lea    edi,[rdx+0x1]
0000000000401126 <golfed_adler32_amd64.byteloop>:
  401126:       ac                      lods   al,BYTE PTR ds:[rsi]
  401127:       01 c7                   add    edi,eax
  401129:       01 fa                   add    edx,edi
  40112b:       e2 f9                   loop   401126 <golfed_adler32_amd64.byteloop>
000000000040112d <golfed_adler32_amd64.end>:
  40112d:       66 b9 f1 ff             mov    cx,0xfff1
  401131:       92                      xchg   edx,eax
  401132:       99                      cdq    
  401133:       f7 f1                   div    ecx
  401135:       52                      push   rdx
  401136:       97                      xchg   edi,eax
  401137:       99                      cdq    
  401138:       f7 f1                   div    ecx
  40113a:       66 52                   push   dx      # this is the diff from last version: evil push/pop instead of shift/add
  40113c:       58                      pop    rax
  40113d:       66 5a                   pop    dx
  40113f:       c3                      ret    
0000000000401140 <golfed_adler32_amd64_end>:

0x40 - 0x20 = 32 bayt.


Yorum yapan NASM kaynağı:

püf nokta:

  • xchg eax, r32bir bayttır; mov'dan daha ucuz. 8086,> = 386'dan daha fazla şey için balta verisine ihtiyaç duyuyordu, bu yüzden nadiren kullanılanlara çok fazla opcode alanı harcamaya karar verdiler xchg ax, r16.

  • Push64 ve push16'nın yüksek ve düşük bir şekilde tek bir kayıt cihazında birleştirilmesi için karıştırılması, iki saniyelik bir sürede regre regle veri hareketi talimatlarını kaydeder div. Bu hilenin 32bit sürümü daha da iyi sonuç push16 / push16 / pop32veriyor: toplamda sadece 5B, 6 değil.

İtip / patlattığımızdan, bu SysV amd64 ABI'deki (kırmızı bölgeli) satır içi asm için güvenli değildir .

golfed_adler32_amd64_v3:   ; (int dummy, const char *buf, int dummy, uint64_t len)

    ;; args: len in rcx,  const char *buf in rsi
    ;; Without dummy args, (unsigned len, const char *buf),  mov ecx, edi is the obvious solution, costing 2 bytes

    xor     eax,eax         ; scratch reg for loading bytes
    cdq                     ; edx: high=0
    lea     edi, [rdx+1]    ; edi: low=1
    ;jrcxz  .end            ; We don't handle len=0.  unlike rep, loop only checks rcx after decrementing
.byteloop:
    lodsb                   ; upper 24b of eax stays zeroed (no partial-register stall on Intel P6/SnB-family CPUs, thanks to the xor-zeroing)
    add     edi, eax        ; low += zero_extend(buf[i])
    add     edx, edi        ; high += low
    loop   .byteloop
.end:
    ;; exit when ecx = 0, eax = last byte of buf
    ;; lodsb at this point would load the terminating 0 byte, conveniently leaving eax=0

    mov     cx, 65521       ; ecx = m = adler32 magic constant.  (upper 16b of ecx is zero from the loop exit condition.  This saves 1B over mov r32,imm32)
    ;sub    cx, (65536 - 65521) ; the immediate is small enough to use the imm8 encoding.  No saving over mov, though, since this needs a mod/rm byte

    xchg    eax, edx        ; eax = high,  edx = buf[last_byte]
    cdq                     ; could be removed if we could arrange things so the loop ended with a load of the 0 byte

    div     ecx             ; div instead of idiv to fault instead of returning wrong answers if high has overflowed to negative.  (-1234 % m is negative)
    push    rdx             ; push high%m and 6B of zero padding

    xchg    eax, edi        ; eax=low
    cdq
    div     ecx             ; edx = low%m

    ;; concatenate the two 16bit halves of the result by putting them in contiguous memory
    push    dx              ; push low%m with no padding
    pop     rax             ; pop  high%m << 16 | low%m   (x86 is little-endian)

    pop     dx              ; add rsp, 2 to restore the stack pointer

    ;; outside of 16bit code, we can't justify returning the result in the dx:ax register pair
    ret
golfed_adler32_amd64_end_v3:

Ayrıca rcxiki döngü sayacı kullanmak yerine dizi indeksi olarak kullanmayı düşünmüştüm, ancak adler32 (s)! = Adler32 (geri (ler)). Yani kullanamadık loop. -Len'den sıfıra kadar sayma ve movzx r32, [rsi+rcx]sadece çok fazla bayt kullanan yol kullanır.

İşaretçiyi kendimiz arttırmayı düşünmek istiyorsak, 32bit kod muhtemelen gitmenin yoludur. X32 ABI (32bit pointer) bile yeterli değildir, çünkü inc esiamd64'te 2B, i386'da 1B'dir. Sırasıyla her bir öğenin sıyrık haline getirilmesi için xor eax,eax/ lodsb/ loop: 4B toplamı geçmek zor görünüyor . inc esi/ movzx r32, byte [esi]/ loop5B'dir.

scas64bit modunda 1B komutu ile bir işaretçiyi artırmak için başka bir seçenektir. ( rdi/ ediyerine rsi, bu yüzden pointer argümanını alırız rdi). Bayrak sonucunu scasbir döngü koşulu olarak kullanamıyoruz , çünkü eax'i sıfırlamak istemiyoruz. Farklı kayıt tahsisi, döngüden sonra bir bayt kazandırabilir.


int[] giriş

Tam işlev alma uint8_t[]"ana" cevaptır, çünkü daha ilginç bir zorluktur. Paketi açmak int[], arayanımızdan bu dilde yapmasını istemek mantıksız bir şeydir, ancak 2B'yi kurtarır.

Girdilerimizi paketlenmemiş bir 32bit tam sayı dizisi olarak alırsak, bir byte'ı kolayca kaydedebiliriz ( sadece kullanın lodsdve kullanın ).xor eax,eax / cdqxor edx,edx

Edx'i lodsd/ ile sıfırlayarak cdqve döngüyü yeniden düzenleyerek başka bir baytı kurtarabiliriz , böylece çıkmadan önce sonlandırıcı 0 öğesini yükler. (Hala intbir dize değil bir dizi olmasına rağmen var olduğunu varsayıyoruz ).

; untested: I didn't modify the test driver to unpack strings for this
golfed_adler32_int_array:
    ; xor   edx,edx
    lodsd                   ; first element. only the low byte non-zero
    cdq                     ; edx: high=0
    lea     edi, [rdx+1]    ; edi: low=1
    ;jrcxz  .end            ; handle len=0?  unlike rep, loop only checks rcx after decrementing
.intloop:
    add     edi, eax        ; low += buf[i]
    add     edx, edi        ; high += low
    lodsd                   ; load buf[i+1] for next iteration
    loop   .intloop
.end:
    ;; exit when ecx = 0, eax = terminating 0

    xchg    eax, edx
    ;cdq               ; edx=0 already, ready for div
    ; same as the char version

Ayrıca scasd(1B sürümü add edi,4) kullanan ve add eax, [rdi]bunun yerine lodsd30 bayt olan denenmemiş bir sürüm yaptım . highDöngünün sonunda eax içerisindeki tasarruflar, başka yerlerde daha büyük kodlarla dengelenir. Girişteki sonlandırıcı bir 0elemana bağlı olmama avantajına sahiptir , bununla birlikte, bize açıkça uzunluk verilen paketlenmiş bir dizi için makul değildir.


C ++ 11 test sürücüsü

Github bağlantısına bakınız. Bu cevap çok büyüyordu ve test sürücüsü daha büyük kodlarla daha fazla özellik kazandı.


2
Bayt yerine tam sayılara izin verdim, çünkü çoğu dilde bayt türü yoktu. 32-bit tamsayılar montaj için doğal olmayan bir seçim olabilir, ancak kod golf kuralları içinde kalırken son baytı sıkmakla ilgilidir. "Doğal olmayan" bir seçim daha düşük bir bayt sayımına yol açarsa, bunun için gidin derim.
Dennis,

@Dennis: Kuralın bazı diller için gereğini anlıyorum. Kuralın, yalnızca int[]gerekliyse veya 4 bayttan fazla kod veya başka bir şey kaydettiğinizde kullanmanıza izin vermesinin bir yolu olmasını diliyorum . Soruna bir çözüm sunarken hiçbir sorunum yok adler32(int[]), ama adler32(char[])sorunun gerçek adler32 işlevi olduğu için sorunun daha ilginç olduğunu düşünüyorum. Asm olarak golf oynamak istediğim şey bu. (Ve bir kere daha bayttan tasarruf etmeyi çok isterim, çünkü bir sonraki fonksiyon kullanılırsa gerçek hayatta asm, 33 bayt = 48 bayt ALIGN 16). Sanırım ikisini de golf oynamaya devam edeceğim.
Peter Cordes

@Dennis: Ayrıca, len = 0 davasını ele almamız gerekiyor mu? 2B do{}while(--len)yerine bir döngü stilini kullanarak tasarruf ediyorum while(len--){}.
Peter Cordes

4
Açıklamalara gelince, daha ayrıntılı, daha iyi.
Dennis,

3
@ cat: Hayır, ben acı verici bulmuyorum. Stackoverflow cevaplarını asm / performance sorularına yazmakla ve x86 etiketini wiki'yi güncellemekle güncelleyerek zamanımı harcamam : P Bunu bir süre yaptıktan sonra, derleyicinin ne zaman daha hızlı kod yazabileceğini görmeye başlarsınız ... ve sonunda derleyicinin yazarken kodu nasıl derleyebileceğini düşünmeye başlarsınız. Performans yerine kod boyutunu optimize etmek bazen ilginç bir değişiklik.
Peter Cordes

8

MATL , 22 bayt

tsQwYsQsh16W15-\l8Mh*s

Giriş, bir sayı dizisi veya karşılık gelen ASCII dizesi olabilir.

Çevrimiçi deneyin!

açıklama

t       % Take array or string as input. Duplicate
sQ      % Sum all its values, and add 1
wYsQs   % Swap. Cumulative sum, add 1, sum
h       % Concatenate horizontally
16W     % 2^16: gives 65536
15-     % Subtract 15: gives 65521
\       % Element-wise modulo operation
l       % Push 1
8M      % Push 65536 again
h       % Concatenate horizontally: gives array [1, 65535]
*s      % Element-wise multiplication and sum. Display

7

Aslında, 36 bayt

;Σu@;╗lR`╜HΣu`MΣk`:65521@%`M1#84ⁿ@q*

Çevrimiçi deneyin!

Açıklama:

;Σu@;╗lR`╜HΣu`MΣk`:65521@%`M1#84ⁿ@q*
;Σu                                   sum(input)+1
   @;╗lR                              push a copy of input to reg0, push range(1, len(input)+1)
        `╜HΣu`M                       map over range: sum(head(reg0,n))+1
               Σk                     sum, combine lower and upper into a list
                 `:65521@%`M          modulo each by 65521
                            1#84ⁿ@q*  dot product with [1,4**8]

7

Java, 84 bayt

long a(int[]i){long a=1,b=0;for(int p:i)b=(b+(a=(a+p)%(p=65521)))%p;return b<<16|a;}

Java çözümlerinin her zaman tamamlanabilir bir kod olması gerekiyorsa lütfen bana bildirin.

Ungolfed

long a(int[] i) {
    long a = 1, b = 0;
    for (int p : i) b = (b + (a = (a + p) % (p = 65521))) % p;
    return b << 16 | a;
}

Not

Girişi dönüştürmeniz Stringgerekir int[]( veya int[]bir bayt daha kısabyte[]char[] ).

Çıktı

String:     "Eagles are great!"
Byte Array: [69, 97, 103, 108, 101, 115, 32, 97, 114, 101, 32, 103, 114, 101, 97, 116, 33]
Checksum:   918816254
Expected:   918816254

String:     "Programming Puzzles & Code Golf"
Byte Array: [80, 114, 111, 103, 114, 97, 109, 109, 105, 110, 103, 32, 80, 117, 122, 122, 108, 101, 115, 32, 38, 32, 67, 111, 100, 101, 32, 71, 111, 108, 102]
Checksum:   3133147946
Expected:   3133147946

String:     "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
Byte Array: [126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126]
Checksum:   68095937
Expected:   68095937

String:     "?????????...?"
Byte Array: [63, 63, 63, 63, 63, 63, 63, 63, 63, ...,63]
Checksum:   2181038080
Expected:   2181038080

1
Güzel cevap ve siteye hoş geldiniz! Ayrıca, tamamlanmayan ve derlenemeyen çözümler, zorluk tam bir program olması gerektiğini açıkça belirtmediği sürece iyidir. Bu tam bir fonksiyondur, yani sayılır.
DJMcMayhem

6

Piet, 120 Codels codelsize 1

Codelsize 20 ile:

codelsize 20

Notlar / Nasıl çalışır?

  • Girdi olarak bir dizi veya dize kullanmak mümkün olmadığından, bu program girdi olarak bir dizi tam sayı (ascii karakterini temsil eden) alarak çalışır. Önce karakter girdilerini kullanmayı düşündüm ama sonlandırma için güzel bir çözüm bulmakta zorlandım, bu yüzden şimdi 1'den küçük herhangi bir sayı girildiğinde sonlandırılıyor. Başlangıçta sonlandırma için yalnızca negatif değerlerdi, ancak programı yazdıktan sonra ilklendirmeyi değiştirmek zorunda kaldım, bu yüzden şimdi gerekli olanı yerine getiremiyorum 2, sadece bir 1(izleme görüntüsünde 26/45). Ancak bunun önemi yoktur, çünkü zorluk kurallarına göre, yalnızca yazdırılabilir ascii karakterlerine izin verilir.

  • Sonunda oldukça şık bir çözüm bulmama rağmen, döngüye yeniden girmekle uzun süre mücadele etti. Hayır pointerveya switchişlemler, yalnızca yorumlayıcı girişi okumak için yeşil koza geri dönene kadar duvarlara doğru koşar (iz görüntülerinde 43-> 44).

  • Döngü sonlandırma, önce girdiyi çoğaltmak, 1 eklemek ve ardından 1'den büyük olup olmadığını kontrol etmek suretiyle gerçekleştirilir. Öyleyse, kodlayıcı seçiciyi tetikler ve yürütme alt yolda devam eder. Değilse, program sola devam eder (izleme görüntülerinde parlak sarı kodeller, 31/50).

  • Desteklenen giriş boyutu, tercüman uygulamasına bağlıdır, ancak doğru tercüman ile isteğe bağlı olarak büyük bir girişi desteklemek mümkün olabilir (örneğin, BigIntegerdahili değerler olarak kullanan bir Java tercümanı söyleyin ).

  • Kurulum gereksiz bir hareket içermesi Hemen testere DUPve CC(iz görüntülerdeki 7-> 8-> 9). Nasıl olduğu hakkında hiçbir fikrim yok. Bu etkili bir şekilde bir noop, bu da codel chooser'ı 16 kez değiştirir ve bu da değişiklik yapmaz.

Npiet izleme görüntüleri

Kurulum ve ilk döngü:

starttrace

Döngü sonlandırma, çıktı ve çıkış:

endtrace

çıktılar

Sadece bir çıktı eklersem beni affedin, girmesi uzun zaman alıyor: ^)

String: "Eagles are great!"

PS B:\Marvin\Desktop\Piet> .\npiet.exe adler32.png
? 69
? 97
? 103
? 108
? 101
? 115
? 32
? 97
? 114
? 101
? 32
? 103
? 114
? 101
? 97
? 116
? 33
? -1
918816254

[65, -1] için Npiet izi

trace: step 0  (0,0/r,l nR -> 1,0/r,l dR):
action: push, value 4
trace: stack (1 values): 4

trace: step 1  (1,0/r,l dR -> 2,0/r,l dB):
action: duplicate
trace: stack (2 values): 4 4

trace: step 2  (2,0/r,l dB -> 3,0/r,l nM):
action: multiply
trace: stack (1 values): 16

trace: step 3  (3,0/r,l nM -> 4,0/r,l nC):
action: duplicate
trace: stack (2 values): 16 16

trace: step 4  (4,0/r,l nC -> 5,0/r,l nY):
action: duplicate
trace: stack (3 values): 16 16 16

trace: step 5  (5,0/r,l nY -> 6,0/r,l nM):
action: duplicate
trace: stack (4 values): 16 16 16 16

trace: step 6  (6,0/r,l nM -> 7,0/r,l nC):
action: duplicate
trace: stack (5 values): 16 16 16 16 16

trace: step 7  (7,0/r,l nC -> 8,0/r,l nY):
action: duplicate
trace: stack (6 values): 16 16 16 16 16 16

trace: step 8  (8,0/r,l nY -> 9,0/r,l lB):
action: switch
trace: stack (5 values): 16 16 16 16 16
trace: stack (5 values): 16 16 16 16 16

trace: step 9  (9,0/r,l lB -> 10,0/r,l dM):
action: multiply
trace: stack (4 values): 256 16 16 16

trace: step 10  (10,0/r,l dM -> 11,0/r,l nR):
action: multiply
trace: stack (3 values): 4096 16 16

trace: step 11  (11,0/r,l nR -> 12,0/r,l lY):
action: multiply
trace: stack (2 values): 65536 16

trace: step 12  (12,0/r,l lY -> 13,0/r,l lM):
action: duplicate
trace: stack (3 values): 65536 65536 16

trace: step 13  (13,0/r,l lM -> 14,0/r,l nM):
action: push, value 3
trace: stack (4 values): 3 65536 65536 16

trace: step 14  (14,0/r,l nM -> 15,0/r,l dM):
action: push, value 2
trace: stack (5 values): 2 3 65536 65536 16

trace: step 15  (15,0/r,l dM -> 16,0/r,l lC):
action: roll
trace: stack (3 values): 16 65536 65536

trace: step 16  (16,0/r,l lC -> 17,0/r,l nB):
action: sub
trace: stack (2 values): 65520 65536

trace: step 17  (17,0/r,l nB -> 18,0/r,l dB):
action: push, value 1
trace: stack (3 values): 1 65520 65536

trace: step 18  (18,0/r,l dB -> 19,0/r,l dM):
action: add
trace: stack (2 values): 65521 65536

trace: step 19  (19,0/r,l dM -> 19,1/d,r dC):
action: duplicate
trace: stack (3 values): 65521 65521 65536

trace: step 20  (19,1/d,r dC -> 18,1/l,l lC):
action: push, value 1
trace: stack (4 values): 1 65521 65521 65536

trace: step 21  (18,1/l,l lC -> 17,1/l,l nC):
action: push, value 1
trace: stack (5 values): 1 1 65521 65521 65536

trace: step 22  (17,1/l,l nC -> 16,1/l,l dB):
action: sub
trace: stack (4 values): 0 65521 65521 65536

trace: step 23  (16,1/l,l dB -> 15,1/l,l lB):
action: push, value 1
trace: stack (5 values): 1 0 65521 65521 65536

trace: step 24  (15,1/l,l lB -> 13,2/l,l dG):
action: in(number)
? 65
trace: stack (6 values): 65 1 0 65521 65521 65536

trace: step 25  (13,2/l,l dG -> 12,2/l,l dR):
action: duplicate
trace: stack (7 values): 65 65 1 0 65521 65521 65536

trace: step 26  (12,2/l,l dR -> 11,2/l,l lR):
action: push, value 1
trace: stack (8 values): 1 65 65 1 0 65521 65521 65536

trace: step 27  (11,2/l,l lR -> 10,2/l,l lY):
action: add
trace: stack (7 values): 66 65 1 0 65521 65521 65536

trace: step 28  (10,2/l,l lY -> 9,2/l,l nY):
action: push, value 1
trace: stack (8 values): 1 66 65 1 0 65521 65521 65536

trace: step 29  (9,2/l,l nY -> 8,1/l,r nB):
action: greater
trace: stack (7 values): 1 65 1 0 65521 65521 65536

trace: step 30  (8,1/l,r nB -> 7,1/l,r lY):
action: switch
trace: stack (6 values): 65 1 0 65521 65521 65536
trace: stack (6 values): 65 1 0 65521 65521 65536

trace: step 31  (7,1/l,l lY -> 6,2/l,l nY):
action: push, value 2
trace: stack (7 values): 2 65 1 0 65521 65521 65536

trace: step 32  (6,2/l,l nY -> 5,3/l,l dB):
action: pointer
trace: stack (6 values): 65 1 0 65521 65521 65536

trace: step 33  (5,3/r,l dB -> 7,4/r,l dM):
action: add
trace: stack (5 values): 66 0 65521 65521 65536

trace: step 34  (7,4/r,l dM -> 8,4/r,l dC):
action: duplicate
trace: stack (6 values): 66 66 0 65521 65521 65536

trace: step 35  (8,4/r,l dC -> 9,3/r,l lC):
action: push, value 3
trace: stack (7 values): 3 66 66 0 65521 65521 65536

trace: step 36  (9,3/r,l lC -> 10,3/r,l nC):
action: push, value 2
trace: stack (8 values): 2 3 66 66 0 65521 65521 65536

trace: step 37  (10,3/r,l nC -> 11,3/r,l dY):
action: roll
trace: stack (6 values): 0 66 66 65521 65521 65536

trace: step 38  (11,3/r,l dY -> 12,3/r,l dG):
action: add
trace: stack (5 values): 66 66 65521 65521 65536

trace: step 39  (12,3/r,l dG -> 13,3/r,l lG):
action: push, value 2
trace: stack (6 values): 2 66 66 65521 65521 65536

trace: step 40  (13,3/r,l lG -> 14,3/r,l nG):
action: push, value 1
trace: stack (7 values): 1 2 66 66 65521 65521 65536

trace: step 41  (14,3/r,l nG -> 15,3/r,l dR):
action: roll
trace: stack (5 values): 66 66 65521 65521 65536
trace: white cell(s) crossed - continuing with no command at 17,3...

trace: step 42  (15,3/r,l dR -> 17,3/r,l lB):

trace: step 43  (17,3/r,l lB -> 13,2/l,l dG):
action: in(number)
? -1
trace: stack (6 values): -1 66 66 65521 65521 65536

trace: step 44  (13,2/l,l dG -> 12,2/l,l dR):
action: duplicate
trace: stack (7 values): -1 -1 66 66 65521 65521 65536

trace: step 45  (12,2/l,l dR -> 11,2/l,l lR):
action: push, value 1
trace: stack (8 values): 1 -1 -1 66 66 65521 65521 65536

trace: step 46  (11,2/l,l lR -> 10,2/l,l lY):
action: add
trace: stack (7 values): 0 -1 66 66 65521 65521 65536

trace: step 47  (10,2/l,l lY -> 9,2/l,l nY):
action: push, value 1
trace: stack (8 values): 1 0 -1 66 66 65521 65521 65536

trace: step 48  (9,2/l,l nY -> 8,1/l,r nB):
action: greater
trace: stack (7 values): 0 -1 66 66 65521 65521 65536

trace: step 49  (8,1/l,r nB -> 7,1/l,r lY):
action: switch
trace: stack (6 values): -1 66 66 65521 65521 65536
trace: stack (6 values): -1 66 66 65521 65521 65536

trace: step 50  (7,1/l,r lY -> 6,1/l,r dY):
action: pop
trace: stack (5 values): 66 66 65521 65521 65536

trace: step 51  (6,1/l,r dY -> 4,1/l,r lY):
action: push, value 3
trace: stack (6 values): 3 66 66 65521 65521 65536

trace: step 52  (4,1/l,r lY -> 3,1/l,r nY):
action: push, value 2
trace: stack (7 values): 2 3 66 66 65521 65521 65536

trace: step 53  (3,1/l,r nY -> 2,1/l,r nM):
action: duplicate
trace: stack (8 values): 2 2 3 66 66 65521 65521 65536

trace: step 54  (2,1/l,r nM -> 1,1/l,r dG):
action: pointer
trace: stack (7 values): 2 3 66 66 65521 65521 65536

trace: step 55  (1,1/r,r dG -> 2,2/r,r lR):
action: roll
trace: stack (5 values): 65521 66 66 65521 65536

trace: step 56  (2,2/r,r lR -> 2,3/d,l nR):
action: push, value 1
trace: stack (6 values): 1 65521 66 66 65521 65536

trace: step 57  (2,3/d,l nR -> 2,4/d,l lC):
action: switch
trace: stack (5 values): 65521 66 66 65521 65536
trace: stack (5 values): 65521 66 66 65521 65536

trace: step 58  (2,4/d,r lC -> 2,5/d,r nM):
action: mod
trace: stack (4 values): 66 66 65521 65536

trace: step 59  (2,5/d,r nM -> 4,5/r,r dM):
action: push, value 3
trace: stack (5 values): 3 66 66 65521 65536

trace: step 60  (4,5/r,r dM -> 6,5/r,r lM):
action: push, value 2
trace: stack (6 values): 2 3 66 66 65521 65536

trace: step 61  (6,5/r,r lM -> 7,5/r,r nC):
action: roll
trace: stack (4 values): 65521 66 66 65536

trace: step 62  (7,5/r,r nC -> 8,5/r,r dM):
action: mod
trace: stack (3 values): 66 66 65536

trace: step 63  (8,5/r,r dM -> 11,5/r,r lM):
action: push, value 3
trace: stack (4 values): 3 66 66 65536

trace: step 64  (11,5/r,r lM -> 12,5/r,r nM):
action: push, value 1
trace: stack (5 values): 1 3 66 66 65536

trace: step 65  (12,5/r,r nM -> 13,5/r,r dC):
action: roll
trace: stack (3 values): 66 65536 66

trace: step 66  (13,5/r,r dC -> 14,5/r,r nB):
action: multiply
trace: stack (2 values): 4325376 66

trace: step 67  (14,5/r,r nB -> 15,5/r,r nM):
action: add
trace: stack (1 values): 4325442

trace: step 68  (15,5/r,r nM -> 16,5/r,r dB):
action: out(number)
4325442
trace: stack is empty
trace: white cell(s) crossed - continuing with no command at 19,5...

trace: step 69  (16,5/r,r dB -> 19,5/r,r nM):

5

C89, 70 bayt

h,l,m=65521;A(char*B){h=0;l=1;while(*B)h+=l+=*B++;return h%m<<16|l%m;}

Test etmek (derlemek gcc -std=c89 -lm golf.c):

#include <stdio.h>
int main(int argc, char** argv) {
    printf("%u\n", A("Eagles are great!"));
    printf("%u\n", A("Programming Puzzles & Code Golf"));
    printf("%u\n", A("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"));
    return 0;
}

zlibKaynak böyle mi görünüyor? Hm ...
kedi,

1
Bu uygulama benim x86 asm versiyonum için güzel bir başlangıç ​​noktası yaptı.
Peter Cordes

Kullanılarak 1 byte kurtarabilir foryerine while:for(h=0,l=1;*B;)h+=l+=*B++;
ninjalj

5

Labirent , 37 36 32 31 bayt

}?"{655:}21:}%=}){%{{36*+!
:++)

Çevrimiçi deneyin!

Bir tamsayı listesi olarak giriş yapın. Program bir hatayla sonlanıyor (hata mesajı STDERR'ye gidiyor).

açıklama

Labirent astar:

  • Labirentte, başlangıçta (örtük) sonsuz miktarda sıfır ile dolu , ana ve aux (iliary) olmak üzere iki rasgele hassas tam sayı yığını vardır .
  • Kaynak kod, bir labirenti andırır, burada talimat göstergesinin (IP) olabildiğince koridorları takip ettiği (hatta köşelerinde). Kod, okuma sırasındaki ilk geçerli karakterde, yani bu durumda sol üst köşede başlar. IP herhangi bir birleşme şekline geldiğinde (yani, geldiğine ek olarak birkaç bitişik hücre), ana yığının tepesine dayalı bir yön seçecektir. Temel kurallar şunlardır: negatifken sola dönün, sıfırda ilerlemeye devam edin, pozitifken sağa dönün. Ve bunlardan biri mümkün olmadığından, bir duvar olduğu için, IP ters yön alacaktır. IP ayrıca ölü uçlara çarptığında da döner.
  • Rakamlar ana yığının üst kısmı 10 ile çarpılarak ve sonra rakam eklenerek işlenir. Yeni bir numara başlatmak için ile bir sıfır basabilirsiniz _.

Her ne kadar kod 4x2 "oda" ile başlasa da, bu aslında ikie iki ayrı ilmekin birbirine sıkılmış halidir. IP, yığın değerleri nedeniyle bir seferde sadece bir döngüye yapışır.

Böylece kod, önek toplamlarını hesaplarken girişi okuyan 2x2 (saat yönünde) bir döngü ile başlar:

}   Move last prefix sum over to aux.
?   Read an integer from STDIN or push 0 on EOF, which exits the loop.
+   Add current value to prefix sum.
:   Duplicate this prefix sum.

Şimdi aux yığını üzerinde tüm önek toplamları, ayrıca tüm değerler ve ana0 EOF üzerinden toplamın bir kopyasına sahibiz . Bununla, hesaplamak için tüm önek toplamlarını toplayan 2x2 (saat yönünde) bir döngü daha giriyoruz .HIGH

"   No-op. Does nothing.
{   Pull one prefix sum over from aux. When we're done, this fetches a 0,
    which exits the loop.
)   Increment prefix sum.
+   Add it to HIGH.

Ana yığın şimdi LOW - 1ve HIGHve sıfırdı, ancak henüz modulo almadık. Kodun geri kalanı tamamen doğrusaldır:

655      Turn the zero into 655.
:}       Make a copy and shift it over to aux.
21       Turn the copy on main into 65521.
:}       Make a copy and shift it over to aux.
%        Take HIGH mod 65521.
=        Swap HIGH with the other copy of 65521 on aux.
}){      Move 65521 back to aux, increment LOW-1 to LOW, 
         move 65521 back to main.
%        Take LOW mod 65521.
{        Move HIGH back to main.
{        Move the other copy of 655 back to main.
36       Turn it into 65536.
*        Multiply HIGH by that.
+        Add it to LOW.
!        Print it.

IP şimdi çıkmaza giriyor ve dönüyor. +Ve *bağlı yığın altındaki sıfırlara, esas olarak herhangi bir-op vardır. 36Şimdi üst döner ana INTO 63, ancak iki {{çekme iki sıfır aux bunun üstüne. Sonra% programı sonlandıran sıfıra bölmeye çalışır.

Labyrinth'in keyfi tam sayılar kullandığını, bu nedenle toplamın sonuna kadar tamsayı taşmasıyla ilgili sorunlara neden olmayacak şekilde modülo ertelemeyi unutmayın.


5

Python 2, 60 58 bayt

H=h=65521
l=1
for n in input():l+=n;h+=l
print h%H<<16|l%H

Oldukça basit bir yaklaşım. Bu, STDIN, örneğin, tamsayıların listesini alan tam bir programdır [72, 105, 33].

(Inanılmaz takma / başlatma ipucu için @xnor'a teşekkürler)


2
Sen yapabilirsin H=h=65521başlatılamadı h65521. aliasing ederken
XNOR

4

J, 30 bayt

+/(+65536&*)&(65521|+/)&:>:+/\

Bu muhtemelen farklı bir trenle daha yoğunlaştırılabilir.

kullanım

İşte kopyalarını x $ yiçeren bir liste oluşturur .xy

   f =: +/(+65536&*)&(65521|+/)&:>:+/\
   f 69 97 103 108 101 115 32 97 114 101 32 103 114 101 97 116 33
918816254
   f 80 114 111 103 114 97 109 109 105 110 103 32 80 117 122 122 108 101 115 32 38 32 67 111 100 101 32 71 111 108 102
3133147946
   f (32 $ 126)
68095937
   f (1040 $ 63)
2181038080
   f (4096 $ 255)
2170679522

açıklama

+/(+65536&*)&(65521|+/)&:>:+/\
f (           g           ) h     Monad train (f g h) y = (f y) g (h y)
+/                                Sum the input list
                           +/\    Sum each prefix of the input, forms a list
x     f   &   g   &:   h    y     Composed verbs, makes (g (h x)) f (g (h y))
                         >:       Increment the sum and increment each prefix sum
               (m f g) y          Hook, makes m f (g y)
                    +/            Sum the prefix sums
              65521|              Take the sum and prefix total mod 65521
    (f g) y                       Hook again
    65536&*                       Multiply the prefix total by 65536
                                  This is a bonded verb, it will only multiply
                                  using a fixed value now
   +                              Add the sum and scaled prefix total

4

Octave, 52 50 bayt

@LuisMendo sayesinde 2 bayt kaydedildi

@(B)mod([sum(S=cumsum(B)+1),S(end)],65521)*[4^8;1]

Girdi olarak bir tamsayı dizisi alır.

Düşük son unsuru alınır yükseği ziyade ... bir genel toplamı tasarruf açıkça toplamını hesaplama (toplayarak önce) 1 byte !

İdeone üzerinde örnek çalışması .


@LuisMendo Ooh, unuttum +B. Sanırım girdi belirtimi tamsayıları alabileceğinizi söylüyor, belki de bunu yapacağım.
beher

3

CJam, 30 29 bayt

q~{1$+}*]:)_W>]1fb65521f%2G#b

Bir tamsayı listesi olarak giriş yapın.

Burada test et.

açıklama

q~       e# Read and evaluate input.
{        e# Fold this block over the list, computing prefix sums.
  1$+    e#   Copy the last prefix and add the current element.
}*
]        e# Wrap the prefix sums in an array.
:)       e# Increment each. This will sum to HIGH.
_W>      e# Copy the list and truncate to only the last element, i.e.
         e# the sum of the entire input plus 1. This is LOW.
]        e# Wrap both of those lists in an array.
1fb      e# Sum each, by treating it as base 1 digits.
65521f%  e# Take each modulo 65521.
2G#b     e# Treat the list as base 65536 digits, computing 65536*HIGH + LOW.

3

Perl 6 , 60 bayt

{(.sum+1)%65521+65536*((sum(1,*+.shift...->{!$_})-1)%65521)}

Açıklama:

{
  # $_ is the implicit parameter for this lambda because this block doesn't have
  # an explicit parameter, and @_ isn't seen inside of it.
  # ( @_ takes precedence over $_ when it is seen by the compiler )

  # .sum is short for $_.sum
  ( .sum + 1 ) % 65521 + 65536
  *
  (
    (
      sum(

        # generate a sequence:

        1,         # starting with 1
        * + .shift # lambda that adds previous result (*) with $_.shift
        ...        # generate until:
        -> { !$_ } # $_ is empty

        # ^ I used a pointy block with zero parameters
        # so that the block doesn't have an implicit parameter
        # like the surrounding block

        # this is so that $_ refers to the outer $_

      ) - 1        # remove starting value
    ) % 65521
  )
}

Ölçek:

#! /usr/bin/env perl6
use v6.c;
use Test;

# give the lambda a name
my &Adler32 = {(.sum+1)%65521+65536*((sum(1,*+.shift...->{!$_})-1)%65521)}

my @tests = (
  (  918816254,  'Eagles are great!'),
  ( 3133147946,  'Programming Puzzles & Code Golf'),
  (   68095937,  '~' x 32,     "'~' x 32"),
  ( 2181038080,  63 xx 1040,   "'?' x 1040"),
);

plan +@tests;

for @tests -> ($checksum, $input, $gist? ) {
  my @array := do given $input {
    when Str { .encode.Array }
    default { .Array }
  }

  is Adler32(@array), $checksum, $gist // $input.perl
}
1..4
ok 1 - "Eagles are great!"
ok 2 - "Programming Puzzles \& Code Golf"
ok 3 - '~' x 32
ok 4 - '?' x 1040

3

Python 3 (79 bayt)

R. Kap'ın çözümüne dayanıyor.

lambda w,E=65521:(1+sum(w))%E+(sum(1+sum(w[:i+1])for i in range(len(w)))%E<<16)

Çarpmayı bir vardiya ile değiştirdim ve bir çift braketi çıkardım.

Çünkü yorum gönderemiyorum yeni bir cevap verdim.



3

Haskell, 54 50 bayt

m=(`mod`65521).sum
g x=m(-1:scanl(+)1x)*4^8+m(1:x)

Kullanım örneği: g [69,97,103,108,101,115,32,97,114,101,32,103,114,101,97,116,33]->918816254 .

scanl(-> başlangıç değerini içerir 1) listede (-> [1,1+b1,1+b1+b2,..]), yani sumkapalıdır 1prepending ile sabitlendiği, -1toplanmasıyla önce listeye.

Düzenleme: 4 bayt için teşekkürler @xnor.


Eğer içine toplayarak dışarı çıkarabilir gibi görünüyor m: m=(`mod`65521).sum g x=m(-1:scanl(+)1x)*4^8+m(1:x). Tutarları düzeltmenin hazırlanmaktan daha iyi bir yolu olabilir.
xnor

3

JavaScript (ES7), 52 50 bayt

a=>a.map(b=>h+=l+=b,h=0,l=1)&&l%65521+h%65521*4**8

ES6 51 bayt alır (4 ** 8 ile 65536'yı değiştirin). Bir dize sürümü istiyorsanız, 69 bayt için:

s=>[...s].map(c=>h+=l+=c.charCodeAt(),h=0,l=1)&&l%65521+h%65521*65536

Düzenleme: @ user81655 sayesinde 2 bayt kaydedildi.


3

ARM Thumb-2 işlevini kabul etme uint8_t[]: 40 bayt (standart olmayan ABI ve için 36B int[])

Özellikler: ertelenmemiş modülo, bu nedenle isteğe bağlı boyutta girişler iyi. Bölme talimatını gerçekten kullanmıyor, bu yüzden yavaş değil. (err, en azından bu sebepten dolayı değil: P)

Daha az katı kurallara uymaktan tasarruf:

  • -2B kullanmadan önce kayıtları kaydetmek zorunda değilsek.
  • Arayanın baytları paketten çıkarmasını istemek için -2B uint32_t[] dizide .

Yani, en iyi durum 36B.

// uint8_t *buf in r0,  uint32_t len in r1
00000000 <adler32arm_golf2>:
   0:   b570            push    {r4, r5, r6, lr} //
   2:   2201            movs    r2, #1          // low
   4:   2300            movs    r3, #0          // high
   6:   f64f 75f1       movw    r5, #65521      ; 0xfff1 = m
0000000a <adler32arm_golf2.byteloop>:
   a:   f810 4b01       ldrb.w  r4, [r0], #1    // post-increment byte-load
   e:   4422            add     r2, r4          // low += *B
  10:   4413            add     r3, r2          // high += low
  12:   42aa            cmp     r2, r5          // subtract if needed instead of deferred modulo
  14:   bf28            it      cs
  16:   1b52            subcs   r2, r2, r5
  18:   42ab            cmp     r3, r5
  1a:   bf28            it      cs              // Predication in thumb mode is still possible, but takes a separate instruction
  1c:   1b5b            subcs   r3, r3, r5
  1e:   3901            subs    r1, #1          // while(--len)
  20:   d1f3            bne.n   a <.byteloop2>
  22:   eac2 4003       pkhbt   r0, r2, r3, lsl #16   // other options are the same size: ORR or ADD.
  26:   bd70            pop     {r4, r5, r6, pc}  // ARM can return by popping the return address (from lr) into the pc; nifty
00000028 <adler32arm_end_golf2>:

0x28 = 40 bayt


Notlar:

Yerine log%msonunda yaptığımız if(low>=m) low-=mdöngü içinde. Yüksek olmadan önce düşük yaparsak, ikisinin de muhtemelen aşmayacağını biliyoruz 2*m, bu yüzden modulo sadece çıkarma ya da değil meselesidir. A cmpve subbelirtilen Thumb2 modunda sadece 6B'dir. Thumb2 modunda standart deyim% 8B'dir:

UDIV R2, R0, R1         // R2 <- R0 / R1
MLS  R0, R1, R2, R0     // R0 <- R0 - (R1 * R2 )

Örtülü uzunluk adler(char *)sürümü, kesin uzunlukla aynı kod boyutundaadler(uint8_t[], uint32_t len) . Döngü-çıkış koşulu için bayrakları her iki şekilde de tek bir 2B komutu ile ayarlayabiliriz.

Örtülü uzunluk sürümü, 2 ^ 32 kez döngü oluşturmaya çalışmak yerine, boş dize ile doğru çalışma avantajına sahiptir.


montaj / derleme:

arm-linux-gnueabi-as --gen-debug -mimplicit-it=always -mfloat-abi=soft -mthumb adler32-arm.S

veya

arm-linux-gnueabi-g++ -Wa,-mimplicit-it=always -g -static -std=gnu++14 -Wall -Wextra -Os -march=armv6t2 -mthumb -mfloat-abi=soft test-adler32.cpp -fverbose-asm adler32-arm.S -o test-adler32
qemu-arm ./test-adler32

Bu olmadan -staticçalışan süreç qemu-armdinamik linker bulamadı. (Benim esas-çıkarma fikri temiz olduğunu düşündüm çünkü evet, ben sadece bu yanıt için bir ARM çapraz devel kurulumu yükleyin.) Ubuntu yüklemek amd64'tür günü gcc-arm-linux-gnueabi, g++-arm-linux-gnueabi. gdb-arm-none-eabiBağlanmak için zar zor çalıştığımı gördüm qemu-arm -g port.

Yorum yapılan kaynak:

// There's no directive to enable implicit-it=always

// gcc uses compiler uses these in its output
.syntax unified
.arch armv8-a
.fpu softvfp

.thumb      @ aka .code 16

.p2align 4
.globl adler32arm_golf    @ put this label on the one we want to test

.thumb_func
adler32arm_golf:
adler32arm_golf2:   @ (uint8_t buf[], uint32_t len)
        @ r0 = buf
        @ r1 = len
        push    {r4, r5, r6, lr}   @ even number of regs keeps the stack aligned.  Good style? since there's no code-size saving

        movs    r2, #1          @ r2: low
        movs    r3, #0          @ r3: high
                                @ r4 = tmp for loading bytes
        movw    r5, #65521      @ r5: modulo constant

adler32arm_golf2.byteloop2:
        ldrb    r4, [r0], #1    @ *(buf++) post-increment addressing.  4B encoding
        @ldrb    r4, [r0, r1]   @ 2B encoding, but unless we make the caller pass us buf+len and -len, it needs extra code somewhere else
        @ldmia   r0!, {r4}      @ int[] version:  r4 = [r0]; r0+=4;  post-increment addressing.  2B encoding.

        add     r2, r2, r4      @ low += tmp
        add     r3, r3, r2      @ high += low;   // I think it's safe to do this before the modulo range-reduction for low, but it would certainly work to put it after.

        cmp     r2, r5
        subhs   r2, r5          @ if(low>=m) low-=m;   @ 6B total for %.  predicated insns require an IT instruction in thumb2

        cmp     r3, r5
        subhs   r3, r5          @ if(high>=m) high-=m;  // equivalent to high %= m.

        @sub    r1, #1          @ 4B encoding: sub.w to not set flags with immediate
        subs    r1, #1          @ len-- and set flags.  2B encoding
        @cmp    r4, #0          @ null-termination check. 2B encoding
        bne     adler32arm_golf2.byteloop2

@        udiv    r0, r2, r5            @ normal way to do one of the modulos
@        mls     r2, r5, r0, r2         @ r2 = low % m.  8B total for %

        PKHBT   r0, r2, r3, lsl #16     @ 4B   r0 = [ high%m <<16  |   low%m  ]
        @orr     r0, r0, r4, lsl #16    @ 4B
        @orr     r0, r0, r4             @ 4B
        @add     r0, r2, r3, lsl #16    @ 4B
        @add     r0, r0, r4             @ 2B
        pop     {r4, r5, r6, pc}        @ ARM can return by popping the return address (saved from lr) into pc.  Nifty
adler32arm_end_golf2:

test-adler32.cppaynı test durumlarına sahip ve main()x86-64 yanıtımla ilgili olarak, ancak şu şekilde başlar:

#include <stdint.h>
uint32_t adler32_simple(const uint8_t *B) {
  const uint32_t m=65521;

  uint32_t h=0, l=1;
  do {
    l += *B++;        // Borrowed from orlp's answer, as a simple reference implementation
    h += l;
    l %= m; h %= m;   // with non-deferred modulo if this is uncommented
  } while(*B);

  return h%m<<16|l%m;
}


#include <stdio.h>
//#include <zlib.h>
#include <string.h>
#include <assert.h>
#include <string>   // useful for the memset-style constructors that repeat a character n times


extern "C" {
    unsigned golfed_adler32_amd64(int /*dummy1*/, const char *buf, int /*dummy2*/, unsigned len);
    unsigned adler32arm_golf(const char *buf, unsigned len);
}
#ifdef __amd64__
#define golfed_adler32(buf, len)   golfed_adler32_amd64(1234, buf, 1234, len)
#elif  __arm__
#define golfed_adler32(buf, len)   adler32arm_golf(buf, len)
#else
#error "no architecture"
#endif

static void test_adler(const char *str)
{
    unsigned len = strlen(str);
//    unsigned zlib = zlib_adler(len, str);
    unsigned reference = adler32_simple((const uint8_t*)str);
    unsigned golfed = golfed_adler32(str, len);

    printf("%s: c:%u asm:%u\n", str, reference, golfed);
    assert(reference == golfed);
}

// main() to call test_adler() unchanged from my amd64 answer, except that the comments about length limits don't apply

3

x86 16bit makine kodu işlevi: özel bir çağrı kuralı kullanarak 32 bayt

Kayıtlardaki hatalar ve bp (ve sp) dışındaki kayıtları korumayan.

16bit kodunda, dx:axkayıt çiftinde 32 bitlik bir değer döndürüyoruz. Bu, birleştirerek highveya birleştirerek herhangi bir talimat harcamak zorunda olmadığımız anlamına gelir low.eax . (Bu, baytları 32 ve 64 bit kodda da kaydeder, ancak bu çalışmayı arayana 16bit kodda boşaltırken haklı gösterebiliriz.)

Yorum yapan kaynak ve test sürücüsü github'da (x86 16, 32 ve 64bit ve ARM için).

### const char *buf in SI,  uint16_t len in CX
## returns in dx:ax
## also clobbers bx and di.
00000100 <adler32_x16_v6>:
 100:   31 c0                   xor    ax,ax         # set up for lods
 102:   99                      cwd                  # dx= high=0
 103:   bf 01 00                mov    di,0x1        # di= low=0
 106:   bb f1 ff                mov    bx,0xfff1     # bx= m
00000109 <adler32_x16_v6.byteloop>:
 109:   ac                      lods
 10a:   01 c7                   add    di,ax         # low+=buf[i]. modulo-reduce on carry, or on low>=m
 10c:   72 04                   jc     112 <adler32_x16_v6.carry_low>
 10e:   39 df                   cmp    di,bx
 110:   72 02                   jb     114 <adler32_x16_v6.low_mod_m_done>
00000112 <adler32_x16_v6.carry_low>:
 112:   29 df                   sub    di,bx
00000114 <adler32_x16_v6.low_mod_m_done>:
 114:   01 fa                   add    dx,di         # high+=low
 116:   0f 92 d0                setb   al            # store the carry to set up a 32bit dividend.
 119:   92                      xchg   dx,ax
 11a:   f7 f3                   div    bx            # high (including carry) %= m, in dx.  ax=0 or 1 (so we're set for lods next iteration)                                                         
 11c:   e2 eb                   loop   109 <adler32_x16_v6.byteloop>
 11e:   97                      xchg   di,ax         # 
 11f:   c3                      ret    
00000120 <adler32_x16_v6_end>:

0x120 - 0x100 = 32 bayt

Aynı kodun 32bit mod için birleştirilmesiyle test edilmiştir, bu nedenle derlenmiş C'den (bir sarmalayıcı işleviyle) çağırabilirim -m32. Benim için, 16bit modu biraz ilginç, DOS sistem çağrıları değil. Tüm komutların açık operandları vardır, loopve hariç lodsb, 32bit mod için montaj operand boyutunda önekler kullanır. Aynı talimat, farklı kodlamalar. Ancak lodsb32bit modunda kullanacak[esi] , bu yüzden bu deneme sürümü 32bit pointer ile çalışıyor (çünkü herhangi bir adres matematiği veya pointer artışı / karşılaştırması yapmıyoruz).

Uyumsuzluk yok. Test kablo demetim uyumsuzluk varsa bir mesaj basar.

$ yasm -felf32 -Worphan-labels -gdwarf2 adler32-x86-16.asm -o adler32-x86-16+32.o &&
   g++ -DTEST_16BIT -m32 -std=gnu++11 -O1 -g -Wall -Wextra -o test-adler32-x16  adler32-x86-16+32.o  test-adler32.cpp -lz &&
   ./test-adler32-x16
Eagles are great! (len=17): zlib:0x36c405fe  c:0x36c405fe golfed:0x36c405fe
Programming Puzzles & Code Golf (len=31): zlib:0xbac00b2a  c:0xbac00b2a golfed:0xbac00b2a
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (len=32): zlib:0x040f0fc1  c:0x040f0fc1 golfed:0x040f0fc1
?????????????????????????????????????????????????? (len=1040): zlib:0x82000000  c:0x82000000 golfed:0x82000000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (len=4096): zlib:0xb169e06a  c:0xb169e06a golfed:0xb169e06a
(0xFF repeating) (len=4096): zlib:0x8161f0e2  c:0x8161f0e2 golfed:0x8161f0e2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (len=5837): zlib:0x5d2a398c  c:0x5d2a398c golfed:0x5d2a398c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (len=5838): zlib:0x97343a0a  c:0x97343a0a golfed:0x97343a0a
(0xFF repeating) (len=9999): zlib:0xcae9ea2c  c:0xcae9ea2c golfed:0xcae9ea2c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (len=65535): zlib:0x33bc06e5  c:0x33bc06e5 golfed:0x33bc06e5

16bit yazmaçlarla, döngü sonrasına kadar modulo azalmasını erteleyemeyiz. : İlginç bir 16bit ve diğer işlenen-boyutları arasında fark vardır m = 65521( 0xFFF1) daha 65536 yarısından Subtracting olan mtaşıma üzerine bile 2 * m aşağıda değerini tutar high=0xFFF0 + 0xFFF0. Döngüden sonra, bir karşılaştır ve çıkar, hile yerine, bir hile yapacak div.

Ben ile geldi bir taşıma üretebilir bir eklenti sonra kayıt modülo azaltıcı için yeni teknikle . Girişin üst yarısını sıfırlamak yerine, kesilmemiş ekleme sonucunu tutan ( zaten sıfırlandı) 32 bit'lik bir temettü oluşturmak için divkullanın . ( 32b / 16b => 16bit bölme yapar.)setc dldhdiv

setcc(3 bayt) 386 ile tanıtıldı. Bunu 286 veya daha önceki bir sürümde çalıştırmak için, en iyi bulduğum en iyi belgelendirilmemiş salctalimatı kullanmak ( AL'yı taşımak için koymak) . Bu, bir baytlık bir opcodesbb al,al , bu yüzden salc/ kullanmadan neg alönce xchg ax, dx(ki ihtiyacımız olanı) kullanabiliriz. Olmadan salc, bir 4B dizisi var: sbb dx,dx/ neg dx. 3B sbb dx,dx/ 'yi kullanamayız inc dx, çünkü bu setncdeğil öykünmek olur setc.


Taşıma taşıma yerine 32bit işlemsel boyut kullanmayı denedim , ancak yalnızca addişlemsel boyutta bir önek gerektiren talimatlar değil . Sabitleri ve benzerlerini ayarlayan talimatlar aynı zamanda işlemsel boyut öneklerine de ihtiyaç duyar, bu nedenle en küçük olmadı.



2

Perl 5, 43 bayt

42 bayt, artı 1 -aEyerine-e

Giriş, boşlukla ayrılmış, ondalık tam sayılar gibidir.

map$h+=$.+=$_,@F;say$.%65521+$h%65521*4**8

Şapkamın bir ipucu olan Sp3000'e , ondan bu cevabı için fikirler aldım.

Nasıl çalışır:

  1. Yüzünden -a, $. 1 ile başlar ve @Fgiriş dizidir. $h0'dan başlar . Bir dizinin her elemanı için bir yer tutucu olarak $_kullanılır map.
  2. map$h+=$.+=$_,@Fher element için demekse @Fbiz bu öğesi ekleyin $.ve sonra eklemek $.için $h.
  3. Sonra modüler aritmetik $.%65521+$h%65521*4**8( sonuç , ($. % 65521) + ( ($h % 65521) * (4**8) )ve say(yazdır)) yaparız .

1

Faktör, 112 109 103 bayt

Şimdi , bu sorudaki algoritmanın hazırladığı bir çeviridir ... şimdi bunu gerçekten yaptım, biliyorsunuz, doğru.

[ [ sum 1 + ] [ [ dup length [1,b] reverse v. ] [ length ] bi + ] bi [ 65521 mod ] bi@ 16 shift bitor ]

Ungolfed:

: adler-32 ( seq -- n )
  [ sum 1 + ] 
  [ 
    [ dup length [1,b] reverse v. ] 
    [ length ] bi + 
  ] bi 
  [ 65521 mod ] bi@ 
  16 shift bitor 
  ;

Herhangi bir sayı sırasını veya bir dizeyi bekler (teknik olarak aynı olmasalar bile çok fazla fark yoktur).

Bunun, 32-bit word-size derlenmiş bir Factor versiyonunda verilmiş olan limit için nasıl bir performans göstereceğini bilmiyorum, fakat 6GB 64-bit 2.2GHz makinemde:

IN: scratchpad 1040 63 <array>

--- Data stack:
{ 63 63 63 63 63 63 63 63 63 63 63 63 63 63 ~1026 more~ }
IN: scratchpad [ adler-32 ] time
Running time: 7.326900000000001e-05 seconds

--- Data stack:
2181038080
IN: scratchpad 10,000 63 <array> 

--- Data stack:
2181038080
{ 63 63 63 63 63 63 63 63 63 63 63 63 63 63 ~9986 more~ }
IN: scratchpad [ adler-32 ] time
Running time: 0.000531669 seconds

1

Ruby, 91 bayt

->s{b=s.bytes;z=i=b.size
b.inject(1,:+)%65521+b.map{|e|e*(1+i-=1)}.inject(z,:+)%65521*4**8}

1

Clojure, 109 bayt

@Mark Adler'in çözümüne dayanır .

(fn f[s](->> s(reduce #(mapv + %(repeat %2)[0(first %)])[1 0])(map #(rem % 65521))(map *[1 65536])(apply +)))

Ungolfed

(fn f [s]
  (->> s
       (reduce #(mapv + % (repeat %2) [0 (first %)]) [1 0])
       (map #(rem % 65521))
       (map * [1 65536])
       (apply +)))

kullanım

=> (def f (fn f[s](->> s(reduce #(mapv + %(repeat %2)[0(first %)])[1 0])(map #(rem % 65521))(map *[1 65536])(apply +))))
=> (f [69 97 103 108 101 115 32 97 114 101 32 103 114 101 97 116 33])
918816254
=> (f [80 114 111 103 114 97 109 109 105 110 103 32 80 117 122 122 108 101 115 32 38 32 67 111 100 101 32 71 111 108 102])
3133147946
=> (f (repeat 32 126))
68095937
=> (f (repeat 1040 63))
2181038080
=> (f (repeat 4096 255))
2170679522

1

Javascript (130 Karakter Golf)

Ungolfed

function a(b)
{
    c=1
    for(i=0;i<b.length;i++)
    {
        c+=b[i]
    }
    d=c%65521
    f=""
    e=0
    k=""
    for(j=0;j<b.length;j++)
    {
        k+= "+"+b[j]
        f+= "(1"+k+")"
        e= ((eval(f)))
        if(j!=b.length-1){f+="+"}
    }
    g=e%65521
    h=d+65536*g
    console.log(h)
}

golfed

a=b=>{for(c=1,k=f="",y=b.length,i=0;i<y;i++)c+=x=b[i],f+="(1"+(k+="+"+x)+")",i<y-1&&(f+="+");return z=65521,c%z+65536*(eval(f)%z)}

Geliştiriciler Konsoluna yapıştırın ve ardından bir Bayt EG Dizisi verin:

[69, 97, 103, 108, 101, 115, 32, 97, 114, 101, 32, 103, 114, 101, 97, 116, 33]

Ve sağlama toplamını konsola döndürür


1

TMP, 55 bayt

3a1.3b0.1;4+a>T8%a>xFFF14+b>a8%b>xFFF11~5<b>164|b>a2$b$

Lua'da uygulama burada bulunabilir: http://preview.ccode.gq/projects/TMP.lua


1
Programlama Bulmacaları ve Code Golf'a Hoş Geldiniz! Bu dil programlama dilleri tanımımızı yerine getiriyor mu?
kedi,

@ cat inanıyorum ama gerçekten "tuples" ı desteklediğinden emin değilim.
brianush1

BrainFuck da öyle değil, muhtemelen iyisindir. Eğer turing tamamlandıysa, asal sayıları bulabilir ve başka bir dilin yapabileceği temel şeyleri yapabilir (ve yapabilir), işe yarar :) :) CSS kendi başına bir programlama dili değildir ve HTML de değil de CSS3 + HTML'dir. turing-tamamlandı ve astarları bulabilir.
kedi,

Demek CodeGolf’ta kullanmak sorun değil mi?
brianush1

Ben öyle düşünüyorum - ne TMP'yi ne de Lua'yı tanımıyorum, bu nedenle bu kodun açıklaması büyük bir yardım olacaktır (ve bunu büyük bir cevap haline getirecektir). : D
kedi

1

Python 3.5, 82 bayt:

( -1 bayt sayesinde Neil ! )

( -1 mathmandan sayesinde bayt ! )

( Dennis sayesinde -4 bayt ! )

lambda w:((1+sum(w))%65521)+4**8*(sum(1+sum(w[:i+1])for i in range(len(w)))%65521)

Anonim bir lambdaişlev. Bir bayt dizisi kabul eder, tüm algoritmayı diziye uygular ve sonucu verir. Tüm test durumlarında başarıyla çalıştı. Buna bir değişken atayarak ve sonra da normal bir işlev dediğiniz gibi bu değişkeni arayarak çağırırsınız. Kabuğu kullanıyorsanız, bunun bir yazdırma işlevi olmadan çıkması gerekir. Ancak, değilseniz print(), çıktıyı görmek için işlev çağrısını işlev içine sarmanız gerekir .

Çevrimiçi deneyin! (Ideone)


(E+15)aslında ondan daha uzun bir bayttır 65536.
Neil,

@Neil Tahmininiz için teşekkürler. Şimdi düzeltildi.
R. Kap,

@ Sp3000 Yani? Bazı baytlar eklerlerse sorun olur, ancak hiçbir bayt eklemedikleri gerçeği bana bağlı.
R. Kap,

4**8ondan daha kısa bir bayttır 65536.
mathmandan

Braketleri jeneratörün etrafına bırakarak ve 0'dan len (w) ' ye kadar yineleyerek 4 byte tasarruf edebilirsiniz . Operatör önceliğinden yararlanılarak 6 bayt daha saklanabilir.
Dennis,

1

Fisyon , 324 bayt

          /   M
       R_MZ  |S
      D ]    |S
 /?V?\} {}/  |S /    \
R{/A  Z$[/   |S/     {\
  } J{\      |S      ;_
 \^  /       |S   R'~++Y++~'L
 /    /      |S       }Y;
 \  \        ;^/
 /  /         +\+ R'~++A++~'L
 \  <Z________________/
    ;\X       //
              \Y/
               *

Adil uyarı, bunu test ettiğim tek uygulama, F # diline ait dil portumdur. Golf oynamıyor, çünkü asıl sabiti en alta soğuduğumda birkaç uzun koşu yapmayı daha kolay buldum, bu yüzden geri dönüp çimdikleyebilirim.

O nasıl çalışır?

  • R'~++Y++~'LBlok doğrudan altındaki reaktör kütle çarpan ayarı, aşağı doğru bir 256 sabit ve başlatma sigortalar.
  • R'~++A++~'ABlok yukarıda reaktörüne doğru bir 256 ve başlatma o kadar sigortalar olan iki kütle birçok içine fissions parçacık65536 (sağ parçacık hemen sonlandırıcı ile yok edilmektedir) kütle her başlattıktan sol ve sağ.
  • Sol partikül başka bir reaktöre çarpar ve yukarı ve aşağı doğru eşit kütleli iki partiküle bölünerek bölünmeye uğrar.
  • İki parçacığın yukarı hareket gücü net-sıfır kütle manipülasyonundan geçer, sola yansıtır, sonra füzyon reaktörünün kütle çarpanını ayarlar. Bu reaktör, H bloğunu nasıl çarptığımız olacaktır.
  • Aşağı doğru hareket eden parçacık sola doğru yansır ve uzun vadede kütleyi tutar, sonuçta kütlesine ulaşır. 65521 (büyük asalımız).
  • İşlemin Zsonunda dönme aynası ( ), partikülün asal kopyalanmasına neden olur ve bir tanesinin fisyon reaktörünün depolanan kütlesini en sonunda ayarladığı sağa geri göndermesini sağlar (^ ) . Modulus işlecini H bloğuna bu şekilde uygulayacağız.
  • İkinci kopya, <L bloğu için kullanacağımız fisyon reaktörü ( ) için benzer bir işlev yaptığı yerde geri yansıtılır .
  • Artık sabitlerimiz yerinde olduğuna göre, girişimizi okumak ve iki listemizi oluşturmak için sol üst kısımdaki Şenanyalılarla ilgileniyoruz. Dürüst olmak gerekirse, bunların nasıl yürüdüğünü unutuyorum, ama boş dize için |S"soğutma kulesini" açıklayan H blok toplama partikülünü yavaşlatmak zorunda kaldım .
  • \Y/ L bloğu (sol kanaldan gelen) ve H bloğunu (sağ kanaldan gelen) sigortalar, sonra onları çıkış kodunu kaynaşık kütleye ayarlayan bir sonlandırıcıya çarptırır.

Bir yerde hata yapmazsam, bu resmi tercümanla ( link ) çalışmıyor gibi görünüyor . Limanı F # ile nereden bulabilirim?
Dennis,

@Dennis Hata benim tarafımda olup olmadığını anlamaya çalışıyorum, ama tercümanın da çalışmasını sağlayamıyorum. Çalışabilir miyim bakalım sonra gerekirse cevapımı güncelleyin.
Andrew Coonce,

@Dennis Görünüşe göre, çevrimiçi yorumlayıcının hata kodu iptallerini işlemediği *, bu şekilde çıktıyı geri döndürüyorum. Yarın çıktıyı doğrulamak için başka bir tercüman bulabilir miyim bakalım.
Andrew Coonce,
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.