Adler-32チェックサムを計算する


32

バックグラウンド

Adler-32は1995年にMark Adlerによって発明された32ビットチェックサムで、広く使用されているzlibライブラリ(Adlerによって開発された)の一部です。Adler-32は、32ビットの巡回冗長検査ほど信頼性は高くありませんが、少なくともソフトウェアでは、実装がはるかに高速で簡単です。

定義

LET B = [B 1、⋯、BのN ]バイト配列です。

BのAdler-32チェックサムは、low + 65536×highの結果として定義されます。ここで、

  • 低:=((1 + b 1 +⋯+ b n)mod 65521)

  • high:=(((1 + b 1)+(1 + b 1 + b 2)+⋯(1 + b 1 +⋯+ b n))mod 65521)

仕事

バイト配列を入力として指定し、Adler-32チェックサムを計算して返します。次の条件に従います。

  • 入力は、バイトまたは整数の配列、または文字列として取得できます。

    どちらの場合も、印刷可能なASCII文字に対応するバイトのみが入力に含まれます。

    入力の長さは、0 <length≤4096を満たすと仮定できます。

  • 出力を印刷する場合は、256までの任意の正のベースを使用できます。

    あなたは単項選択した場合は、必ず通訳がまで対応することができ作る2 32 983056 - RAMの16ジブを持つマシン上で出力のバイト。

  • Adler-32チェックサムを計算するビルトインは禁止されています。

  • 標準の規則が適用されます。

テストケース

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
ここでの答えの多くは、32ビットまたは64ビット整数の合計をオーバーフローすると、合計が計算されるまでモジュロ演算を延期するため、大きいまたは非常に大きい入力シーケンスで失敗します。真に準拠した実装では、合計がオーバーフローしないように、少なくとも定期的にモジュロ演算を実行する必要があります。32ビットの符号付き整数は、4096個の0xffだけでオーバーフローします。64 MiBの0xffの後、64ビットの符号付き整数がオーバーフローします。
マークアドラー

@MarkAdler Hm、フェアポイント。ソリューションが任意の長い文字列に対して機能する必要があることを指定しておらず、既存の回答を無効にしたくないため、入力の長さに制限を設定します。
デニス

@MarkAdlerそれは重要ではないと思います。moduloの前のhighの最大値はn *(n + 1)/ 2 * 255 + nであるため、オーバーフロー(符号付き32ビット整数)は4104バイト以上の入力でのみ発生する可能性がかなりあります。さらに、チャレンジは入力を印刷可能なASCII文字に対応するバイトに制限します。
デニス

また、言語で数値型をオーバーフローさせ、返された結果が正しい結果と同等であり、オーバーフローを考慮してのみ必要な場合もあります。
マイル

1
@PeterCordesはい、32ビット整数の配列はまったく問題ありません。少なくとも私の意見では、提出物はアルゴリズムのゴルフに焦点を合わせ、I / Oにできるだけ注意を払うべきではありません。
デニス

回答:


3

ゼリー、19 17バイト

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

オンラインでお試しください!

+\,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

さらに良い:⁹²¤
デニス

1
@Dennisその時、あなたの18バイトを超えました。
リーキー修道女

1
さて、あなたは ... outgolfedている
漏れ修道女

64

Mathematica、46バイト

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

整数配列を受け取り、Adler-32を返す無名関数。マイルとマーティンからのいくつかの改善があります(コメントを参照)。

miles 'も46バイトですが、より高速です:

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

37
...あなた自身の有名なアルゴリズムをゴルフしただけですか?
メゴ

25
ちょっとスターに打たれても許してくれ。私たちの謙虚な小さなサイトで、ソフトウェア工学のこのような大きな名前を目にするのは、毎日ではありません。ようこそ!
メゴ

6
それほど大きくない。
マークアドラー

3
あなたが私を意味するなら、これは私がMathematicaでAdler-32を実装することを考えたのは初めてです。
マークアドラー

9
あるいは、Code Golfに入社してからこのソリューションを準備し、質問されるのを待っているだけかもしれません。"最後に!" ;-)
アンティハパラ1​​6

13

ジュリア、73 46バイト

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

これは、配列を受け入れて整数を返す匿名関数です。呼び出すには、変数に割り当てます。

我々は、組み合わせsum(x) + 1及びsum(cumsum(x) + 1)配列に、ここでx入力された配列であり、そして我々は、次に1と4との内積計算毎モジュロ65521.を取る8私たちを与える、(sum(x) + 1) + 4^8 * sum(cumsum(x) + 1)正確アドラー-32式です。

オンラインでお試しください!(すべてのテストケースを含む)

Sp3000とDennisのおかげで27バイト節約されました!


うわー、それは本当に賢いです。

@cat私はSp3000とDennisを使って、ほとんどの巧妙さに感謝しています。:)
アレックスA.

11

x86-64マシンコード関数:33 32バイト(または、入力ではなく31 30バイト)int[]char[]

x86-32マシンコード関数:31バイト

GNU Cインラインasmコードフラグメントとして:2B 1B(retinsnのみ)を保存します。

githubのコメント化されたソースおよびテストドライバー

64ビットバージョンは、標準のSystem V x86-64 ABIを使用してCから直接呼び出すことができます(2つのダミー引数を使用して、必要なregの引数を取得します)。カスタム呼び出し規約はasmコードでは珍しいことではないため、これはボーナス機能です。

32ビットマシンコードはpush16/push16 => pop32、32ビットモードでのみ上半分と下半分をマージするため、1Bを節約します。32ビット関数には、カスタム呼び出し規約が必要です。それを保持するべきではありませんが、Cからの呼び出しにはラッパー関数が必要です。

4096 ~(ASCII 126)バイトの処理後、high = 0x3f040000, low = 0x7e001。したがって、highの最上位ビットはまだ設定されていません。私のコードはこれを利用し、ゼロ化の方法としてwithにサイン拡張eaxします。edx:eaxcdqedx

# 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バイト。


コメントされたNASMソース:

トリック:

  • xchg eax, r321バイトです。movよりも安い。8086は386よりもはるかに多くのもののためにaxのデータを必要としていたため、今ではほとんど使用されないに多くのopcodeスペースを費やすことにしましたxchg ax, r16

  • 高と低を1つのレジスタにマージするためにpush64とpush16を混合すると、reg-regデータ移動命令を約2 div秒節約できます。このトリックの32ビット版はさらに機能します:push16 / push16 / pop32合計は5Bで、6ではありません。

プッシュ/ポップするため、これはSysV amd64 ABI(レッドゾーン付き)のインラインasmに対して安全ではありません

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:

またrcx、2つのループカウンターを使用する代わりに、配列インデックスとして使用することも検討しましたが、adler32(s)!= adler32(reverse(s))です。したがって、使用できませんでしたloop。-lenからゼロに向かってカウントし、使用movzx r32, [rsi+rcx]するバイト数が多すぎます。

ポインターを自分でインクリメントすることを検討する場合は、おそらく32ビットコードが最適です。x32 ABI(32ビットポインター)でも十分ではありませんinc esi。amd64では2Bですが、i386では1Bです。各要素を順番にゼロ拡張してeaxにするために、xor eax,eax/ lodsb/ loop:合計4B を打つのは難しいようです。 inc esi/ movzx r32, byte [esi]/ loopは5Bです。

scas64ビットモードで1B命令を使用してポインタをインクリメントする別のオプションです。(の代わりにrdi/ なので、ポインタargを取ります)。ただし、eaxをゼロのままにしたくないため、フラグの結果をループ条件として使用することはできません。異なるレジスタ割り当てにより、ループ後のバイトを節約できる場合があります。edirsirdiscas


int[] 入力

フル機能の撮影ではuint8_t[]、それがもっと面白い挑戦だから、「メイン」の答えです。開梱int[]は、この言語で行うように呼び出し元に依頼するのは不合理なことですが、2Bを節約します。

入力を32ビット整数のアンパックされた配列として取得する場合、1バイトを簡単に保存できます(使用lodsdしてxor eax,eax / cdq、単にに置き換えますxor edx,edx)。

lodsd/ cdqでedxをゼロにし、終了する前に終端の0要素をロードするようにループを再配置することにより、別のバイトを保存できます。(これはint文字列ではなくの配列ですが、まだ存在すると仮定しています)。

; 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

また、の代わりにscasd(の1Bバージョンadd edi,4)とを使用する未テストバージョンを作成しましたが、これも30バイトです。ループの終わりでeaxを使用することによる節約は、他の場所でより大きなコードによって相殺されます。ただし、入力の終端要素に依存しないという利点があります。これは、長さも明示的に指定されているアンパックされた配列には不合理な場合があります。add eax, [rdi]lodsdhigh0


C ++ 11テストドライバー

githubリンクを参照してください。この答えは大きくなりすぎており、テストドライバーはより大きなコードでより多くの機能を取得しました。


2
多くの言語にはバイト型さえないため、主にバイトではなく整数を許可しました。32ビット整数はアセンブリにとって不自然な選択かもしれませんが、コードゴルフはルール内にとどまりながら最後のバイトを絞り出すことです。「不自然な」選択がバイトカウントの低下につながる場合は、それを選択することをお勧めします。
デニス

@Dennis:一部の言語ではルールの必要性を理解しています。ルールint[]が必要な場合にのみ使用できるようにしたり、4バイト以上のコードなどを保存したりする方法があればいいのにと思います。問題の解決策を提示するのに問題はありませんadler32(int[])adler32(char[])、実際のadler32関数なので、問題はより興味深いと感じています。それは私が本当にasmでゴルフをしたいものです。(そして実際のasmでは、次の関数がを使用する場合、33バイト= 48バイトであるため、どうにかしてもう1バイトを節約したいALIGN 16です。)私は両方をゴルフし続けると思います。
ピーターコーデス

@Dennis:また、len = 0のケースを処理する必要がありますか?のdo{}while(--len)代わりにスタイルのループを使用して2Bを保存しwhile(len--){}ます。
ピーターコーデス

4
説明に関しては、詳細であるほど良いです。
デニス

3
@cat:いいえ、私は苦痛を感じていません。asm /パフォーマンスの質問に対するStackoverflowの回答を書き、x86タグwikiを更新した場合は時間を費やしません:Pコードの実行速度が遅いまたは速い理由を知りたい場合は、asmを見て理解する必要があります。しばらくそれを行うと、コンパイラーがコードを高速化できる時期が見え始め、最終的には、コンパイラーがコードを記述するときにどのようにコンパイルするかについて考え始めます。パフォーマンスの代わりにコードサイズを最適化することは、時々興味深い変更です。
ピーターコーデス

8

MATL、22バイト

tsQwYsQsh16W15-\l8Mh*s

入力は、数値の配列または対応するASCII文字列にすることができます。

オンラインでお試しください!

説明

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

実際には、36バイト

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

オンラインでお試しください!

説明:

;Σ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バイト

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ソリューションが常に完全なコンパイル可能なコードであることになっている場合は、お知らせください。

非ゴルフ

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;
}

注意

入力Stringint[]int[]に1バイト短くするbyte[]か、またはchar[])。

出力

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
いい答えです。サイトへようこそ!また、完全でコンパイル可能でないソリューションは、チャレンジが完全なプログラムであると明示的に述べていない限り問題ありません。これは完全な機能であるため、重要です。
DJMcMayhem

6

Piet、120コーデル コーデルサイズ1

codelsize 20の場合:

コーデルサイズ20

注/どのように機能しますか?

  • 配列または文字列を入力として使用することはできないため、このプログラムは一連の整数(ASCII文字を表す)を入力として使用して機能します。最初は文字入力を使用することを考えましたが、終了のための良い解決策を見つけるのに苦労しました。そのため、1より小さい数値が入力されると終了します。元々は終了に対して負の値のみでしたが、プログラムを書き込んだ後に初期化を変更する必要があったため、必要な(トレースイメージで26/45 2)だけを適合させることができません1。ただし、チャレンジルールに従って、印刷可能なASCII文字のみが許可されているため、これは重要ではありません。

  • ループに入るのに長い間苦労しましたが、最終的には非常にエレガントな解決策を見つけました。いいえ、pointerまたはswitch操作、入力を読み取るために緑色のコーデルに戻るまでインタープリターのみが壁に走ります(トレース画像で43-> 44)。

  • ループの終了は、最初に入力を複製し、1を追加してから1より大きいかどうかをチェックすることで達成されます。1より大きい場合、コーダーセレクターがトリガーされ、実行はより低いパスで続行されます。そうでない場合、プログラムは左に続きます(明るい黄色のコーデル、トレース画像で31/50)。

  • サポートされる入力サイズはインタープリターの実装に依存しますが、適切なインタープリターで任意の大きな入力をサポートすることは可能です(たとえば、BigInteger内部値として使用するJavaインタープリター)

  • セットアップが不要な方含まれていることだけでのこぎりDUPCC(トレース画像で7> 8> 9)。それがどのように起こったのか分かりません。これは事実上何もしませんが、codel chooserを16回切り替えますが、変更はありません。

Npietトレース画像

セットアップと最初のループ:

スタートトレース

ループの終了、出力、および終了:

エンドトレース

出力

出力を1つだけ含める場合はご容赦ください。入力に時間がかかるだけです:^)

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]のnpietトレース

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バイト

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

テストするには(でコンパイル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;
}

zlibソースはどのように見えますか?うーん...-

1
この実装は、私のx86 asmバージョンの良い出発点となりました。
ピーターコーデス

使用して1つのバイトを保存することができますforのではなく、whilefor(h=0,l=1;*B;)h+=l+=*B++;
ninjalj

5

ラビリンス37 36 32 31バイト

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

オンラインでお試しください!

整数のリストとして入力します。プログラムはエラーで終了します(エラーメッセージはSTDERRに送られます)。

説明

ラビリンスプライマー:

  • Labyrinthには、任意精度整数の2つのスタック、mainauxがあります(iliary)あり、最初は(暗黙の)無限量のゼロで埋められます。
  • ソースコードは迷路に似ており、指示ポインター(IP)が可能な場合(コーナーの周りであっても)通路をたどります。コードは、読み取り順序の最初の有効な文字、つまりこの場合は左上隅から始まります。IPが任意の形式のジャンクション(つまり、元のセルに加えていくつかの隣接セル)に到達すると、メインスタックの最上部に基づいて方向を選択します。基本的なルールは次のとおりです。負の場合は左に曲がり、ゼロの場合は先に進み、正の場合は右に曲がります。そして、壁があるためにこれらのいずれかが不可能な場合、IPは反対方向を取ります。IPは、行き止まりに到達したときにも向きを変えます。
  • 数字は、メインスタックの最上部に10を掛けてから数字を追加することで処理されます。新しい番号を開始するには、でゼロをプッシュできます_

コードは4x2の「ルーム」で始まりますが、実際には2つの個別の2×2ループが一緒に圧縮されています。スタック値が原因で、IPは一度に1つのループに固執するだけです。

そのため、コードは2x2(時計回り)ループで始まり、プレフィックスの合計を計算しながら入力を読み取ります。

}   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.

これで、補助スタックにすべてのプレフィックス合計があり、すべての値の合計のコピーとmainの0 from EOFがあります。それで、すべてのプレフィックスの合計を計算する別の2x2(時計回り)ループに入ります。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.

モジュロをまだ取得していないことを除いてLOW - 1、メインスタックにはand HIGHとzero があります。コードの残りは完全に線形です:

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は行き止まりになり、向きを変えます。+そして*本質的にスタックの底部でゼロによるノーオペレーション、ではありません。36今のトップターンメインにし63たが、2 {{からプル二つのゼロAUX、その上に。それから%、プログラムを終了するゼロで除算しようとします。

Labyrinthは任意精度の整数を使用するため、合計の終わりまでモジュロを延期しても整数オーバーフローの問題が発生しないことに注意してください。


5

Pythonの2、60の 58バイト

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

非常に簡単なアプローチ。これは、STDINを介して整数のリストを取得する完全なプログラム[72, 105, 33]です。

(素晴らしいエイリアシング/初期化のヒントをありがとう@xnorに感謝)


2
あなたは行うことができますH=h=65521初期化するh65521.エイリアシングながら
XNOR

4

J、30バイト

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

これはおそらく、異なる列車でさらに凝縮される可能性があります。

使用法

ここでx $ y、のxコピーを含むリストを作成しますy

   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

説明

+/(+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

オクターブ、52 50バイト

@LuisMendoのおかげで2バイト節約

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

整数の配列を入力として受け取ります。

低はの最後の要素から取られているではなく、の...総計節約、明示的に合計を計算(合計する前に)を1つのバイトを

ideoneでのサンプル実行。


@LuisMendoおお、私は忘れていた+B。入力仕様では整数を取ることができると書かれていると思うので、たぶんそれをやるだけでしょう。
ビーカー

3

CJam、30 29バイト

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

整数のリストとして入力します。

ここでテストしてください。

説明

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バイト

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

説明:

{
  # $_ 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
  )
}

テスト:

#! /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バイト)

R. Kapのソリューションに基づきます。

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

乗算をシフトに置き換え、ブラケットのペアを削除しました。

コメントを投稿できないため、新しい回答をしました。


3

スキーム、195バイト

(define(a b)(+(let L((b b)(s 1))(if(=(length b)0)s(L(cdr b)(modulo(+ s(car b))65521))))(* 65536(let H((b b)(s 1)(t 0))(if(=(length b)0)t(let((S(+ s(car b))))(H(cdr b)S(modulo(+ t S)65521))))))))

それらの括弧がすべてではない場合...


3

Haskell、54 50バイト

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

使用例:g [69,97,103,108,101,115,32,97,114,101,32,103,114,101,97,116,33]-> 918816254

scanl( - >開始値を含む1( - >リストで)[1,1+b1,1+b1+b2,..])、そうsumではオフになってい1-1になります。

編集:4バイトありがとう@xnor。


合計をm以下に抽出できるようですm=(`mod`65521).sum g x=m(-1:scanl(+)1x)*4^8+m(1:x)。おそらく、先頭に追加するよりも合計を修正するより良い方法があります。
xnor

3

JavaScript(ES7)、52 50バイト

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

ES6は51バイトを使用します(4 ** 8を65536に置き換えます)。文字列バージョンが必要な場合、69バイトの場合:

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

編集:@ user81655のおかげで2バイトを保存しました。


3

ARM Thumb-2関数の受け入れuint8_t[]:40バイト(非標準のABIおよびint[]

機能:非遅延モジュロなので、任意のサイズの入力で問題ありません。実際には除算命令を使用しないため、遅くありません。(エラー、少なくともそのため:P)

次のそれほど厳格でない規則からの節約:

  • -2Bレジスタを使用する前に保存する必要がない場合。
  • -2Bは、呼び出し元にバイトをuint32_t[]配列にアンパックすることを要求します。

したがって、ベストケースは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バイト


ノート:

代わりのlog%m終わりに、我々はやるif(low>=m) low-=mループ内。高の前に低を行うと、どちらもを超えることはできないことがわかっている2*mため、モジュロは単に減算するかどうかの問題です。A cmpおよびpredicated subは、Thumb2モードでは6Bのみです。 Thumb2モードの標準的なイディオム%は8Bです。

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

暗黙の長さのadler(char *)バージョンは、明示的な長さと同じコードサイズですadler(uint8_t[], uint32_t len)です。どちらの方法でも、単一の2B命令でループ終了条件のフラグを設定できます。

暗黙の長さのバージョンには、2 ^ 32回ループするのではなく、空の文字列で正しく動作するという利点があります。


アセンブル/コンパイル:

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

または

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

なし-staticでは、実行中のプロセスqemu-armは動的リンカーを見つけられませんでした。(そして、はい、この答えのためだけにARMクロス開発セットアップをインストールします。これは、述部付き減算のアイデアがきれいだと思ったからです。)amd64 Ubuntuで、をインストールgcc-arm-linux-gnueabig++-arm-linux-gnueabiます。私が見つかりました。gdb-arm-none-eabiかろうじてへの接続に働いたのソートqemu-arm -g port

コメントされたソース:

// 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.cppmain()私のx86-64の答えと同じテストケースがありますが、この方法で始まります:

#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 16ビットマシンコード関数:カスタム呼び出し規約を使用した32バイト

レジスタ内で引数を取り、bp(およびsp)以外のregを保持しません。

16ビットコードでは、dx:axレジスタペアで32ビット値を返します。この手段は、私たちは、合併の任意の指示を費やす必要はありませんhighloweax。(これにより、32ビットおよび64ビットコードのバイト数も節約されますが、この作業を16ビットコードで呼び出し元にオフロードすることのみを正当化できます。)

githubのソースおよびテストドライバーのコメント(x86 16、32、64ビット、およびARM)。

### 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バイト

32ビットモード用に同じコードをアセンブルしてテストしたため、でコンパイルされたCから(ラッパー関数を使用して)呼び出すことができます-m32。私にとって、16ビットモードはやや興味深いですが、DOSシステムコールはそうではありません。すべての命令には明示的なオペランドがありますが、loopおよびlodsbため、32ビットモードのアセンブルではオペランドサイズのプレフィックスが使用されます。同じ命令、異なるエンコーディング。しかしlodsb、32ビットモードでは[esi]、このテスト用バージョンは32ビットポインターで機能します(アドレス計算やポインターのインクリメント/比較は行わないため)。

不一致はありません。不一致がある場合、テストハーネスはメッセージを出力します。

$ 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

16ビットレジスタでは、モジュロリダクションをループの後まで延期することはできません。:あり16ビットおよびその他のオペランド・サイズ間の興味深い違いがあります m = 655210xFFF1)半分以上65536引いていますmキャリーオンがあっても、2 *メートル以下の値を保持しますがhigh=0xFFF0 + 0xFFF0。ループの後、の代わりに比較と減算がトリックを行いdivます。

キャリーを生成できる加算後にレジスタをモジュロ削減するための新しい手法を思い付きました。の入力の上半分をゼロにする代わりに、切り捨てられていない加算結果を保持する32ビットの配当を作成するためdivに使用setc dlします(dh既にゼロになっています)。(div 32b / 16b => 16ビット除算を行います。)

setcc(3バイト)は386で導入されました。これを286以前で実行するには、文書化されていないsalc命令(ALをキャリーから設定)を使用しました。これはの1バイトのオペコードであるためsbb al,alsalc/ neg alを実行する前に/ を使用できますxchg ax, dx(とにかく必要です)。なしsalcでは、4Bシーケンスがあります:sbb dx,dx/ neg dx。3B sbb dx,dx/ は使用できません。inc dxそれはエミュレートするからですsetncではなくsetc


キャリーを処理する代わりに32ビットのオペランドサイズを使用しようとしましaddたが、オペランドサイズのプレフィックスが必要なのは命令だけではありません。定数などを設定する命令にもオペランドサイズのプレフィックスが必要なので、最小ではありませんでした。



2

Perl 5、43バイト

42バイト、プラスの-aE代わりに1-e

入力は、スペースで区切られた10進整数です。

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

Sp3000への私の帽子の先端

使い方:

  1. 以下のため-a$. 1から始まり、@F入力配列です。$h0から始まりますが$_で使用されていますmapます。配列の各要素のプレースホルダーとしてれます。
  2. map$h+=$.+=$_,@F内の各要素のことを意味し@F、私たちにその要素を追加$.し、次に追加$.します$h
  3. 次に、モジュラー演算を実行します$.%65521+$h%65521*4**8(つまり、結果($. % 65521) + ( ($h % 65521) * (4**8) )say(印刷)します)。

1

ファクター、112 109 103バイト

さて、これは質問のアルゴリズムの文字通りの翻訳です...今、私は実際にそれを修正しました。

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

ゴルフをしていない:

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

数字または文字列のシーケンスを期待します(技術的には同じではありませんが、大きな違いはありません)。

32ビットワードサイズでコンパイルされたFactorのバージョンで、指定された制限に対してこれがどのように機能するかわかりませんが、6GB 64ビット2.2GHzマシンでは:

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

Clojure、109バイト

@Mark Adlerのソリューションに基づいています

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

非ゴルフ

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

使用法

=> (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文字のゴルフ)

非ゴルフ

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)
}

ゴルフ

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)}

Developers Consoleに貼り付けてから、Bytes EGの配列を指定します。

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

そして、チェックサムをコンソールに返します


1

TMP、55バイト

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

Luaでの実装については、http//preview.ccode.gq/projects/TMP.luaをご覧ください。


1
プログラミングパズルとコードゴルフへようこそ!この言語はプログラミング言語の定義を満たしていますか?

@cat私はそれを信じていますが、それが本当に「タプル」をサポートするかどうかわかりません。
brianush1

BrainFuckも同様ですので、おそらく大丈夫です。チューリングが完了し、素数を見つけることができ、他の言語ができる基本的なことを行うことができます(そしてできる)、それは動作します:)CSSはそれ自体ではプログラミング言語ではなく、HTMLではなくCSS3 + HTMLですチューリング完全であり、素数を見つけることができます。

だから、CodeGolfで使用しても大丈夫ですか?
brianush1

私はそう思う-私はTMPもLuaも知らないので、このコードの説明は大きな助けになるでしょう(そしてこれは素晴らしい答えになるでしょう)。:D

1

Python 3.5、82バイト:

ニールのおかげで-1バイト!

mathmandanのおかげで-1バイト!

デニスのおかげで-4バイト!

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

匿名lambda関数。バイト配列を受け入れ、アルゴリズム全体を配列に適用し、結果を出力します。すべてのテストケースで正常に機能しました。これを呼び出すには、変数に変数を割り当ててから、通常の関数を呼び出すのと同じようにその変数を呼び出します。シェルを使用している場合は、印刷機能なしで出力する必要があります。ただし、そうでない場合は、関数呼び出しをprint()実際に出力を確認する必要があります。

オンラインでお試しください!(イデオン)


(E+15)は実際にはより大きいバイトです65536
ニール

@Neilヒントをありがとう。現在修正されています。
R. Kap

@ Sp3000だから?バイトを追加したかどうかは問題になりますが、バイトを追加しないという事実は私には問題ありません。
R. Kap

4**8は、より短いバイトです65536
-mathmandan

ジェネレーターの周りに角かっこをドロップし、0からlen(w)まで反復することで4バイトを節約できます。演算子の優先順位を活用することで、さらに6バイトを節約できます。
デニス

1

核分裂、324バイト

          /   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/
               *

公正な警告、私がこれをテストした唯一の実装は、F#への言語の私自身の移植です。主に定数が底に沿って冷えている間に数回のロングランを行う方が簡単だとわかったため、ゴルフではありません。

どのように機能しますか?

  • R'~++Y++~'Lブロックは、直接その下の反応器の質量乗数を設定し、その下方に256定数と起動を融合します。
  • R'~++A++~'Aブロックは、2つの質量倍に粒子を核分裂上記反応器に向かって別の256及び起動それをヒューズ65536、それらを(右粒子が直ちにターミネーターによって破壊される)左右起動、質量をそれぞれ。
  • 左の粒子は別の原子炉に衝突し、核分裂を起こし、上下に等しい質量の2つの粒子に分裂します。
  • 上方に移動する2のべき乗の粒子は、正味ゼロの質量操作を通過し、左に反射してから、核融合炉の質量乗数を設定します。このリアクターは、Hブロックを乗算する方法になります。
  • 下方に移動する粒子は左に反射し、長期にわたって質量を放出し、最終的に 65521(私たちの大きな素数)にます。
  • Z実行終了時の回転ミラー()により、粒子は素数を複製し、1つを右に戻し、最終的に核分裂炉の蓄積質量(^)のます。これは、モジュラス演算子をHブロックに適用する方法です。
  • 2番目のコピーは反映さ<れ、Lブロックに使用する核分裂炉()の類似の機能を実行します。
  • 定数が設定されたので、左上のシェナンガンに取り組み、入力を読み取り、2つのリストを生成します。正直に言うと、私はそれらがどのように機能するかを忘れていますが、空の文字列のために、|S「冷却塔」を説明するHブロック加算粒子を遅くする必要がありました。
  • \Y/ Lブロック(左チャネルから入る)とHブロック(右チャネルから入る)を融合し、それらを終了コードに設定して、終了コードを融合質量に設定します。

どこかで間違いを犯していない限り、これは公式の通訳(link)では機能しないようです。F#へのポートはどこで入手できますか?
デニス

@Dennisバグが自分の側にあるかどうかを把握しようとしていますが、インタープリターを動作させることもできません。動作するかどうか確認し、必要に応じて回答を更新します。
アンドリュークーンス16年

@Dennisオンラインインタープリターはエラーコードabortsを処理していない*ようです。これが出力を返す方法です。明日、出力を確認するために別のインタープリターを見つけることができるかどうかを確認します。
アンドリュークーンス16年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.