Adler-32 체크섬 계산


32

배경

Adler-32 는 1995 년 Mark Adler가 발명 한 32 비트 체크섬으로 널리 사용되는 zlib 라이브러리 (Adler도 개발)의 일부입니다. Adler-32는 32 비트 순환 중복 검사 만큼 안정적이지는 않지만 적어도 소프트웨어에서는 훨씬 빠르고 구현하기 쉽습니다.

정의

하자 B가 = [B 1 , ⋯, B의 n은 ] 바이트 배열.

B 의 Adler-32 체크섬 은 low + 65536 × high 의 결과로 정의됩니다 .

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

  • 높음 : = ((((1 + b 1 ) + (1 + b 1 + b 2 ) + ⋯ (1 + b 1 + ⋯ + b n )) 모드 65521)

태스크

바이트 배열을 입력으로 받으면 Adler-32 체크섬을 계산하여 다음을 준수하십시오.

  • 입력을 바이트 또는 정수 배열 또는 문자열로 사용할 수 있습니다.

    두 경우 모두 인쇄 가능한 ASCII 문자에 해당하는 바이트 만 입력에 발생합니다.

    입력 길이가 0 <length ≤ 4096을 만족한다고 가정 할 수 있습니다 .

  • 출력을 인쇄하기로 선택한 경우 최대 256까지의 양수를 사용할 수 있습니다.

    당신이 단항 선택하는 경우, 반드시 통역까지 처리 할 수 있도록 2 32 983,056 - 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 비트 부호있는 정수는 256 MiB의 0xff 후에 오버플로됩니다.
Mark Adler

@MarkAdler Hm, 페어 포인트. 솔루션이 임의로 긴 문자열에 대해 작동해야한다고 지정하지 않았고 기존 답변을 무효화하고 싶지 않기 때문에 입력 길이에 제한을 설정합니다.
Dennis

@ MarkAdler 나는 그것이 중요하지 않다고 생각합니다. 최대 값으로 I는, 플로우 (32 비트 부호있는 정수)의 입력 만의 4104 바이트 이상 발생할 수 있다는 것을 확신한다 높은 모듈러스 전에이 * (N + 1) / 2 * 255 + N N . 또한, 문제는 입력 가능한 인쇄 가능한 ASCII 문자에 해당하는 바이트로 입력을 제한합니다.
Dennis

또한 언어가 숫자 유형을 오버플로하도록 허용 할 수 있으며 반환 된 결과는 오버플로를 고려하여 올바른 결과와 동일해야합니다.
마일

1
@PeterCordes 예. 32 비트 정수 배열은 완벽하게 좋습니다. 적어도 제 의견으로는 제출물은 알고리즘을 골프화하는 데 중점을 두어야하며 가능한 한 I / O에주의를 기울여야합니다.
Dennis

답변:


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 바이트를 능가했습니다.
Leaky Nun

1
글쎄, 당신 은 outgolfed ..
Leaky Nun

64

매스 매 티카, 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
... 나만의 유명한 알고리즘을 골랐나요?
Mego

25
별이 맞으면 저를 용서해주세요. 우리가 겸손한 작은 사이트에서 소프트웨어 엔지니어링에서 큰 이름을 보는 것은 일상이 아닙니다. 탑승을 환영합니다!
Mego

6
그렇게 큰 것은 아닙니다.
Mark Adler

3
제 말은 Mathematica에서 Adler-32를 구현할 생각이었습니다.
Mark Adler

9
또는 코드 골프에 합류 한 이후에이 솔루션을 준비했을 수도 있습니다. "마침내!" ;-)
Antti Haapala

13

줄리아, 73 46 바이트

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

이것은 배열을 받아들이고 정수를 반환하는 익명 함수입니다. 호출하려면 변수에 지정하십시오.

우리 조합 sum(x) + 1sum(cumsum(x) + 1)배열에 x입력 배열이며, 우리는 다음 (1) 및 (4)에 내적을 계산하는 각 모듈 65521.을 8 우리에게 제공하는 (sum(x) + 1) + 4^8 * sum(cumsum(x) + 1)정확히 애들러 -32 식이다.

온라인으로 사용해보십시오! (모든 테스트 케이스 포함)

Sp3000과 Dennis 덕분에 27 바이트를 절약했습니다!


와우, 정말 영리 해요.
cat

@cat Sp3000과 Dennis가 영리의 대부분을 고맙게 생각합니다. :)
Alex A.

11

x86-64 기계 코드 기능 : 33 32 바이트 (또는 입력 대신 31 30 바이트 )int[]char[]

x86-32 기계 코드 기능 : 31 바이트

GNU C 인라인 -asm 코드 단편으로서 : 2B 1B를 저장합니다 (단지 기능 ret).

github에서 주석이 달린 소스 및 테스트 드라이버

64 비트 버전은 표준 System V x86-64 ABI를 사용하여 C에서 직접 호출 할 수 있습니다 (원하는 regs에서 args를 얻기 위해 2 개의 더미 args 사용). 사용자 정의 호출 규칙은 asm 코드에서 일반적이지 않으므로 보너스 기능입니다.

32 비트 머신 코드는 1B를 절약 push16/push16 => pop32합니다. 상하 반을 병합하면 32 비트 모드에서만 작동합니다. 32 비트 함수에는 사용자 지정 호출 규칙이 필요합니다. 우리는 그것을 반대해서는 안되지만 C에서 호출하면 래퍼 함수가 필요합니다.

4096 ~(ASCII 126) 바이트를 처리 한 후 high = 0x3f040000, low = 0x7e001. 따라서 high'가장 중요한 비트는 아직 설정되지 않았습니다. 내 코드는 다음과 활용, 로그인 확장 eaxedx:eaxcdq영점 조정하는 방법으로 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 바이트


댓글이 달린 NASM 소스 :

트릭 :

  • xchg eax, r321 바이트입니다. mov보다 저렴합니다. 8086은> = 386보다 훨씬 많은 데이터를 얻기 위해 도끼로 데이터를 필요로했기 때문에 현재 거의 사용되지 않는 많은 opcode 공간을 사용하기로 결정했습니다 xchg ax, r16.

  • high와 low를 단일 레지스터에 병합하기 위해 push64와 push16을 혼합하면 reg-reg 데이터 이동 명령이 2 div초 정도 절약 됩니다. 이 트릭의 32 비트 버전은 훨씬 더 효과적입니다. push16 / push16 / pop326 개가 아닌 총 5B입니다.

푸시 / 팝 때문에 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두 개의 루프 카운터 대신 배열 인덱스로 사용 하는 것을 고려 했지만 adler32 (s)! = adler32 (reverse (s)). 그래서 우리는 사용할 수 없었습니다 loop. -len에서 0까지 계산하고 movzx r32, [rsi+rcx]사용하면 너무 많은 바이트가 사용됩니다.

포인터를 스스로 늘리는 것을 고려하고 싶다면 32 비트 코드가 좋습니다. inc esiamd64에서는 2B이지만 i386에서는 1B 이므로 x32 ABI (32 비트 포인터)도 충분하지 않습니다 . xor eax,eax/ lodsb/ loop: 총 4B 를이기는 것이 어려워서 각 요소가 차례로 0으로 확장됩니다. inc esi/ movzx r32, byte [esi]/ loop는 5B입니다.

scas64 비트 모드에서 1B 명령어로 포인터를 증가시키는 또 다른 옵션입니다. ( rdi/ edi대신 / rsi에 포인터 arg를 사용합니다 rdi). 우리는 scaseax를 0으로 유지하고 싶지 않기 때문에 플래그 결과를 루프 조건으로 사용할 수 없습니다 . 다른 레지스터 할당은 루프 후 바이트를 절약 할 수 있습니다.


int[] 입력

전체 기능을 수행하는 uint8_t[]것이 "주된"답변입니다. 더 흥미로운 도전이되기 때문입니다. 포장을 풀면 int[]발신자에게이 언어로 요청하는 것은 부당한 일이지만 2B를 절약합니다.

입력을 32 비트 정수의 압축되지 않은 배열로 가져 가면 1 바이트를 쉽게 절약 할 수 있습니다 (사용 lodsd하고 xor eax,eax / cdqjust로 대체하십시오 xor edx,edx).

lodsd/로 edx를 0으로 cdq만들고 루프를 다시 정렬하여 다른 바이트를 저장할 수 있으므로 종료하기 전에 종료 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 기능이기 때문에 문제가 더 재미 adler32(int[])있다고 생각 adler32(char[])합니다. 내가 정말로 asm에서 골프하고 싶어하는 것입니다. (실제로 asm에서 다음 함수가을 사용하면 33 바이트 = 48 바이트이기 때문에 어떻게 든 하나 이상의 바이트를 절약하고 싶습니다 ALIGN 16.) 둘 다 계속 골프를 칠 것 같아요.
Peter Cordes

@Dennis : 또한 len = 0 사례를 처리해야합니까? do{}while(--len)루프 대신 스타일을 사용하여 2B를 절약 합니다 while(len--){}.
Peter Cordes

4
설명에 관해서는 더 자세할수록 좋습니다.
Dennis

3
@cat : 아니요, 고통스럽지 않습니다. 나는 asm / performance 질문에 대한 Stackoverflow 답변을 작성하고 내가 한 경우 x86 태그 위키를 업데이트하는 데 시간을 소비하지 않을 것입니다 .P 코드가 느리게 실행되는 이유를 알고 싶다면 asm을보고 이해해야합니다. 일단 그렇게하면 컴파일러가 더 빠른 코드를 만들 수있는 시점을보기 시작하고 결국 컴파일러가 코드를 작성할 때 코드를 컴파일하는 방법에 대해 생각하기 시작합니다. 성능 대신 코드 크기를 최적화하는 것은 때때로 흥미로운 변화입니다.
Peter Cordes

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

자바, 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;
}

노트

입력을로 변환해야 String합니다 int[]( 또는 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

피에트, 120 코덱 코덱 크기 1

codelsize 20의 경우 :

코덱 크기 20

참고 / 어떻게 작동합니까?

  • 배열 또는 문자열을 입력으로 사용할 수 없으므로이 프로그램은 일련의 정수 (아스키 문자를 나타냄)를 입력으로 사용하여 작동합니다. 처음에는 문자 입력을 사용하는 것에 대해 생각했지만 종료를위한 멋진 솔루션을 찾기 위해 고심 했으므로 이제 1보다 작은 숫자가 입력되면 종료됩니다. 그래서 지금은 필요에 맞지 않을 수 있습니다, 그것은 해지 원래 부정적인 값이었다, 그러나 나는 프로그램을 작성 후 초기화를 변경했다 2만, 1(추적 이미지에 45분의 26). 챌린지 규칙에 따라 인쇄 가능한 ASCII 문자 만 허용되므로 문제가되지 않습니다.

  • 루프를 다시 입력하는 데 오랜 시간 동안 어려움을 겪었지만 결국에는 우아한 솔루션을 찾았습니다. 입력 pointer또는 switch판독을 읽기 위해 녹색 코덱으로 다시 전환 될 때까지 통역사 만 벽으로 실행됩니다 (추적 이미지에서 43-> 44).

  • 먼저 입력을 복제하고 1을 추가 한 다음 입력이 1보다 큰지 확인하여 루프 종료가 발생합니다.이 경우 코덱 선택기가 트리거되고 하위 경로에서 실행이 계속됩니다. 그렇지 않은 경우 프로그램은 왼쪽으로 계속 진행됩니다 (추적 이미지의 밝은 노란색 코덱, 31/50).

  • 지원되는 입력 크기는 인터프리터 구현에 따라 다르지만 올바른 인터프리터를 사용하여 임의로 큰 입력을 지원할 수 있습니다 (예 BigInteger: 내부 값으로 사용되는 Java 인터프리터 )

  • 설정에 불필요한 것이 하나 DUP있고 CC(트레이스 이미지에 7-> 8-> 9) 있음을 보았습니다 . 어떻게 된건 지 모르겠습니다. 이것은 사실상 noop입니다. 코덱 선택기를 16 번 토글하여 아무런 변화가 없습니다.

니 피트 추적 이미지

설정 및 첫 번째 루프 :

출발 선

루프 종료, 출력 및 종료 :

끝점

출력

하나의 출력 만 포함하면 용서하십시오. 입력하는 데 시간이 오래 걸립니다 : ^)

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 버전을위한 좋은 출발점이되었습니다.
Peter Cordes

사용하여 1 바이트를 저장할 수 for대신 while:for(h=0,l=1;*B;)h+=l+=*B++;
ninjalj

5

미로 , 37 36 32 31 바이트

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

온라인으로 사용해보십시오!

정수 목록으로 입력하십시오. 프로그램은 오류와 함께 종료됩니다 (오류 메시지는 STDERR로갑니다).

설명

미로 프라이머 :

  • Labyrinth에는 mainaux (iliary) 라는 두 개의 임의 정밀도 정수 스택 이 있으며 처음에는 (암시 적) 무한한 양의 0으로 채워집니다.
  • 소스 코드는 미로와 유사하며, 명령 포인터 (IP)는 가능할 때 (모퉁이를 돌 때) 복도를 따라갑니다. 코드는 첫 번째 유효한 문자에서 읽기 순서로 시작합니다 (예 :이 경우 왼쪽 상단). IP가 어떤 형태의 접합 (즉, 여러 개의 인접 셀에서 나온 것)에 도달하면 메인 스택의 상단을 기준으로 방향을 선택합니다. 기본 규칙은 다음과 같습니다. 음수이면 왼쪽으로 돌리고 0이면 계속 진행하고 양수이면 오른쪽으로 돌리십시오. 벽이있어이 중 하나를 사용할 수없는 경우 IP는 반대 방향으로 진행됩니다. 데드 엔드를 칠 때 IP도 돌아갑니다.
  • 숫자는 메인 스택의 상단에 10을 곱한 다음 숫자를 추가하여 처리됩니다. 새 숫자를 시작하려면을 사용하여 0을 누를 수 있습니다 _.

코드는 4x2 "룸"으로 시작하지만 실제로는 두 개의 개별 2x2 루프가 함께 압착됩니다. 스택 값으로 인해 IP는 한 번에 하나의 루프에 고정됩니다.

따라서 코드는 접두사 합계를 계산하는 동안 입력을 읽는 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.

이제 aux 스택 의 모든 접두사 합계 와 모든 값에 대한 합계 사본과 main의0 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 - 1HIGH우리가 아직 모듈을 촬영하지 않은 것을 제외하고, 제로. 코드의 나머지 부분은 완전히 선형입니다.

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가 막 다른 골목에 닿아 돌아섰습니다. +*인해 스택 하단 0으로, 본질적 작전 없다. 는 36지금의 상단집니다 에를 63하지만,이 개 {{풀에서 두 개의 제로 보조 그 위에. 그런 다음 %프로그램을 종료하는 0으로 나누려고합니다.

Labyrinth는 임의 정밀도 정수를 사용하므로 합계가 끝날 때까지 모듈로를 지연해도 정수 오버플로에 문제가 발생하지 않습니다.


5

파이썬 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
앨리어싱 65521 동안 H=h=65521초기화 할 수 있습니다.h
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]

정수 배열을 입력으로받습니다.

low 는 합계를 명시 적으로 계산하지 않고 high (합산 전) 의 마지막 요소에서 가져 옵니다 .

ideone에서 샘플 실행 .


@LuisMendo Ooh, 나는 잊어 버렸습니다 +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

펄 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

파이썬 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

하스켈, 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,..]) 때문에이 sumoff이다 1붙이는 고정되고, -1합산 전에 목록.

편집 : 4 바이트에 대한 @xnor 감사합니다.


당신이에 합산을 추출 할 수있는 것 같습니다 m: m=(`mod`65521).sum g x=m(-1:scanl(+)1x)*4^8+m(1:x). 합계보다 합계를 수정하는 것이 더 좋은 방법 일 것입니다.
xnor

3

자바 스크립트 (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 및 36B int[])

특징 : 지연되지 않은 모듈로, 임의의 크기의 입력이 좋습니다. 실제로 나누기 명령을 사용하지 않으므로 느리지 않습니다. (오류, 적어도 그 이유는 아닙니다 : P)

덜 엄격한 규칙을 따름으로써 절약되는 비용 :

  • 레지스터를 사용하기 전에 저장할 필요가없는 경우 -2B
  • 호출자가 바이트를 uint32_t[]배열 로 압축 해제하도록 요구하는 경우 -2B

가장 좋은 경우는 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, 둘 다 초과 할 수 없다는 것을 알고 있으므로 모듈로는 빼기의 문제 일뿐입니다. Thumb2 모드에서 A cmp및 술어 sub는 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 크로스 (STABLE) 설치를 설치합니다.) 우분투 설치, AMD64에서 gcc-arm-linux-gnueabi, g++-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를 유지하지 않고 레지스터에서 Args.

16 비트 코드에서 dx:ax레지스터 쌍 으로 32 비트 값을 반환합니다 . 즉, 병합 highlow에 대한 지침을 사용할 필요가 없습니다 eax. (이것은 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 비트 모드에서 사용하는 피연산자 크기의 접두사 조립. 동일한 명령, 다른 인코딩. 그러나 lodsb32 비트 모드에서는을 사용 하므로이 [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 = 65521( 0xFFF1)는 65536의 절반 이상입니다. mcarry를 빼면 값이 2 * m 미만으로 유지됩니다 high=0xFFF0 + 0xFFF0. 루프 후에는 비교 및 ​​빼기가 대신 트릭을 수행합니다 div.

캐리를 생성 할 수있는 추가 후 레지스터를 모듈로 감소시키는 새로운 기술을 생각해 냈습니다 . 에 대한 입력의 절반을 제로화하는 대신 잘리지 않은 추가 결과를 보유하는 32 비트 배당을 만드는 데 div사용 setc dl합니다 ( dh이미 제로화 됨). ( div32b / 16b => 16bit 나누기를 수행합니다.)

setcc(3 바이트)는 386으로 도입되었습니다. 286 또는 이전 버전에서 이것을 실행하기 위해 내가 기록한 최선은 문서화되지 않은 salc명령어 를 사용합니다 (AL을 carry에서 설정) . 에 대한 1 바이트 opcode sbb al,al이므로 (어쨌든 필요한) 수행하기 전에 salc/ neg al를 사용할 수 있습니다 xchg ax, dx. 이 없으면 salc4B 시퀀스가 ​​있습니다 : sbb dx,dx/ neg dx. 우리는 3B sbb dx,dx/를 사용할 수 없습니다 inc dx. 왜냐하면 그것은 setnc오히려 모방 하기 때문 setc입니다.


나는 시도 32 비트 피연산자 크기를 사용 하는 대신 캐리 처리를하지만, 그냥 아니라 add피연산자 크기의 접두사를 필요로 지침을 제공합니다. 상수 등을 설정하는 명령에는 피연산자 크기 접두사가 필요하므로 가장 작지 않습니다.



2

펄 5, 43 바이트

42 바이트 + -aE대신 1-e

입력은 공백으로 구분 된 십진 정수입니다.

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

Sp3000에 대한 내 모자 끝 .이 답변에서 아이디어를 얻었습니다.

작동 방식 :

  1. 로 인해 1 -a에서 $.시작 @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 비트 워드 크기로 컴파일 된 팩터 버전의 6 버전 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

루비, 91 바이트

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

클로저, 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

자바 스크립트 (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)}

개발자 콘솔에 붙여 넣은 다음 바이트 배열 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

파이썬 3.5, 82 바이트 :

( Neil 덕분에 -1 바이트 ! )

( mathmandan 덕분에 -1 바이트 ! )

( Dennis 덕분에 -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)실제로는 1보다 긴 바이트 65536입니다.
Neil

@ 닐 팁을 주셔서 감사합니다. 이제 수정되었습니다.
R. Kap

@ Sp3000 그래서? 그들이 바이트를 추가했는지 여부는 중요하지만 바이트를 추가 하지 않는다는 사실은 나와 잘 어울립니다.
R. Kap

4**8보다 짧은 바이트 65536입니다.
mathmandan

생성기 주변에 괄호를 놓고 0 에서 len (w) 까지 반복하여 4 바이트를 절약 할 수 있습니다 . 연산자 우선 순위를 활용하여 다른 6 바이트를 저장할 수 있습니다.
Dennis

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블록은 두 질량 배수에 입자되는 fissions 상기 반응기 향해 서로 256 발사 그것을 퓨즈 65536(오른쪽 입자 즉시 종결 파괴된다) 질량 각 그들을 시작 바로 왼쪽.
  • 왼쪽 입자는 다른 원자로에 충돌하여 핵분열을 겪고 동일한 질량의 위아래로 두 개의 입자로 나뉩니다.
  • 상향 이동하는 2의 입자는 제로 질량 조작을 통과하고 왼쪽으로 반사 된 다음 융합 반응기의 질량 승수를 설정합니다. 이 반응기는 우리가 H 블록을 곱하는 방법입니다.
  • 하향으로 이동하는 입자는 왼쪽으로 반사되어 장기적으로 질량을 흘려 궁극적으로 질량에 도달합니다 65521.
  • Z런이 끝날 때 회전 거울 ( )은 입자가 프라임을 복제하여 핵분열로 ( ^) 의 저장된 질량을 다시 오른쪽으로 보냅니다 . 이것이 우리가 계수 연산자를 H 블록에 적용하는 방법입니다.
  • 두 번째 사본은 다시 반영되어 <L 블록에 사용할 핵분열로 ( )와 유사한 기능을 수행합니다 .
  • 이제 상수가 정해 졌으므로 왼쪽 상단의 셰 나니 건에 참여하여 입력을 읽고 두 목록을 생성합니다. 솔직히 말해서, 나는 그것들이 어떻게 작동하는지 잊었지만, 빈 줄에 대해서는 |S"냉각탑" 을 설명하는 H 블록 합산 입자를 늦추어 야했습니다 .
  • \Y/ L 블록 (왼쪽 채널을 통해 들어오는)과 H 블록 (오른쪽 채널을 통해 들어오는)을 융합 한 다음 종료 코드를 융합 질량으로 설정하는 터미네이터로 슬램 핑합니다.

어딘가에서 실수를하지 않으면 공식 통역사 ( link ) 와 함께 작동하지 않는 것 같습니다 . 포트를 F #으로 어디에서 얻을 수 있습니까?
Dennis

@Dennis 버그가 내 끝에 있는지 여부를 알아 내려고 노력하고 있지만 통역사도 작동시킬 수 없습니다. 작동시킬 수 있는지 확인한 다음 필요한 경우 답변을 업데이트하십시오.
Andrew Coonce

@Dennis 온라인 인터프리터가 오류 코드 중단을 처리하지 않는 것 같습니다 *. 출력을 반환하는 방법입니다. 내일 출력을 확인할 다른 통역사를 찾을 수 있는지 살펴 보겠습니다.
Andrew Coonce
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.