คำนวณการตรวจสอบ Adler-32


32

พื้นหลัง

Adler-32เป็นเช็คซัม 32 บิตที่คิดค้นโดย Mark Adler ในปี 1995 ซึ่งเป็นส่วนหนึ่งของ zlib library ที่ใช้กันอย่างแพร่หลาย (พัฒนาโดย Adler) Adler-32 ไม่น่าเชื่อถือเท่ากับการตรวจสอบความซ้ำซ้อนแบบ 32 บิตแต่อย่างน้อยในซอฟต์แวร์ - มันเร็วกว่าและง่ายกว่าในการนำไปใช้

คำนิยาม

ให้B = [b 1 , ⋯, b n ]เป็นอาร์เรย์ไบต์

การตรวจสอบ Adler-32 ของBหมายถึงผลลัพธ์ของ+ 65536 ×สูงต่ำโดยที่:

  • ต่ำ: = ((1 + b 1 + ⋯ + b n ) mod 65521)

  • สูง: = (((1 + b 1 ) + (1 + b 1 + b 2 ) + ⋯ (1 + b 1 + ⋯ + b n )) mod 65521)

งาน

ให้อาร์เรย์ไบต์เป็นอินพุตให้คำนวณและส่งคืนการตรวจสอบ Adler-32 โดยปฏิบัติตามสิ่งต่อไปนี้

  • คุณสามารถรับอินพุตเป็นอาร์เรย์ของไบต์หรือจำนวนเต็มหรือเป็นสตริง

    ในทั้งสองกรณีจะมีเพียงไบต์ที่สอดคล้องกับอักขระ ASCII ที่พิมพ์ได้เท่านั้นที่จะเกิดขึ้นในอินพุต

    คุณอาจจะคิดว่าระยะเวลาของการป้อนข้อมูลที่จะตอบสนอง0 <ยาว≤ 4096

  • หากคุณเลือกที่จะพิมพ์ผลลัพธ์คุณอาจใช้ฐานบวกใด ๆ รวมถึง 256

    หากคุณเลือกเอกให้แน่ใจว่าล่ามสามารถจัดการได้ถึง2 32 - 983056ไบต์ของการส่งออกในเครื่องที่มี 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 หืมจุดยุติธรรม เนื่องจากฉันไม่ได้ระบุว่าโซลูชันจะต้องทำงานกับสตริงที่มีความยาวโดยพลการและฉันไม่ต้องการทำให้คำตอบที่มีอยู่เป็นโมฆะฉันจะตั้งค่าขีดจำกัดความยาวของอินพุต
เดนนิส

@ MarkAdler ฉันไม่คิดว่ามันสำคัญ ผมค่อนข้างมั่นใจว่าล้น (ลงนามจำนวนเต็ม 32 บิต) สามารถเกิดขึ้นเฉพาะกับ 4104 หรือมากกว่าไบต์ของการป้อนข้อมูลเป็นค่าสูงสุดของสูงก่อนที่จะเป็นแบบโมดูโลn * (1 + n) / 2 * 255 + n ความท้าทายจะ จำกัด อินพุตเป็นไบต์ที่สอดคล้องกับอักขระ ASCII ที่พิมพ์ได้
เดนนิส

นอกจากนี้เรายังสามารถอนุญาตให้ภาษาโอเวอร์โฟลว์ชนิดตัวเลขของพวกเขาและต้องการให้ผลลัพธ์ที่ส่งคืนนั้นมีค่าเทียบเท่าการบัญชีสำหรับการโอเวอร์โฟลว์เพื่อผลลัพธ์ที่ถูกต้อง
ไมล์

1
@PeterCordes ใช่อาร์เรย์ของ 32- บิต ints ดีอย่างสมบูรณ์ อย่างน้อยที่สุดในความคิดของฉันการส่งควรมุ่งเน้นไปที่การเล่นกอล์ฟอัลกอริทึมและให้ความสนใจน้อยที่สุดกับ 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 ไบต์ของคุณ
Leun Nun

1
เอาล่ะคุณได้ดีกว่า ..
Nun

64

Mathematica ขนาด 46 ไบต์

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

ฟังก์ชั่นไม่ระบุชื่อที่ใช้อาร์เรย์จำนวนเต็มและส่งคืน Adler-32 พร้อมการปรับปรุงบางอย่างจากไมล์และมาร์ติน (ดูความคิดเห็น)

ไมล์ 'ก็เป็น46 ไบต์แต่เร็วกว่า:

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

37
... คุณเล่นกอล์ฟอัลกอริทึมที่มีชื่อเสียงของคุณเองหรือไม่?
Mego

25
ยกโทษให้ฉันถ้าฉันเป็นดาวหลง ไม่ใช่ทุกวันที่คุณเห็นชื่อใหญ่ในวิศวกรรมซอฟต์แวร์ในไซต์เล็ก ๆ ของเรา ยินดีต้อนรับบนเรือ!
Mego

6
ไม่ใช่ทุกสิ่งที่ยิ่งใหญ่
Mark Adler

3
ถ้าคุณหมายถึงฉันนี่เป็นครั้งแรกที่ฉันคิดว่าจะใช้ Adler-32 ใน Mathematica
Mark Adler

9
หรือบางทีคุณอาจมีวิธีแก้ปัญหานี้พร้อมตั้งแต่คุณเข้าร่วม Code Golf เพียงแค่รอให้มีการถาม "ในที่สุด!" ;-)
Antti Haapala

13

จูเลีย, 73ไบต์

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

นี่คือฟังก์ชั่นที่ไม่ระบุชื่อที่ยอมรับอาร์เรย์และส่งกลับจำนวนเต็ม หากต้องการเรียกใช้กำหนดค่าให้กับตัวแปร

เรารวมsum(x) + 1และsum(cumsum(x) + 1)เป็นอาเรย์ที่xเป็นอาร์เรย์การป้อนข้อมูลและใช้เวลาในแต่ละแบบโมดูโล 65521. จากนั้นเราคำนวณคูณจุดด้วย 1 และ 4 8ซึ่งจะช่วยให้เรา(sum(x) + 1) + 4^8 * sum(cumsum(x) + 1)ซึ่งเป็นสิ่งสูตร Adler-32

ลองออนไลน์!(รวมถึงกรณีทดสอบทั้งหมด)

บันทึก 27 ไบต์ด้วย Sp3000 และ Dennis!


ว้าวมันฉลาดจริงๆ
แมว

@cat ฉันมี Sp3000 และ Dennis ขอขอบคุณสำหรับความฉลาดส่วนใหญ่ :)
Alex A.

11

ฟังก์ชันรหัสเครื่อง x86-64: 33 32 ไบต์ (หรือ31 30 ไบต์พร้อมint[]อินพุตแทนที่จะเป็นchar[])

x86-32 ฟังก์ชั่นรหัสเครื่อง: 31 ไบต์

ในฐานะที่เป็นส่วนย่อยของโค้ด Inline-asm GNU C: บันทึก2B 1B (เฉพาะretinsn)

แสดงความคิดเห็นแหล่งที่มาและทดสอบไดรเวอร์บน GitHub

เวอร์ชัน 64 บิตสามารถเรียกใช้ได้โดยตรงจาก C พร้อมกับ System V x86-64 ABI มาตรฐาน (โดยใช้ 2 dummy args เพื่อรับ args ใน regs ที่ต้องการ) แบบแผนการโทรที่กำหนดเองไม่ใช่เรื่องแปลกสำหรับรหัส asm ดังนั้นนี่คือคุณลักษณะโบนัส

รหัสเครื่อง 32 บิตจะบันทึก 1B เนื่องจากการผสานครึ่งสูงและครึ่งต่ำเข้าด้วยกันpush16/push16 => pop32จะทำงานในโหมด 32 บิตเท่านั้น ฟังก์ชั่น 32 บิตจะต้องมีการเรียกประชุมที่กำหนดเอง เราไม่ควรถือมันเอาไว้ แต่การโทรจาก C ต้องใช้ฟังก์ชั่น wrapper

หลังจากการประมวลผล 4096 ~(ASCII 126) high = 0x3f040000, low = 0x7e001ไบต์ ดังนั้นhighบิตที่สำคัญที่สุดยังไม่ได้ตั้งค่า รหัสของฉันจะได้ประโยชน์จากนี้ลงนามขยายeaxเข้าไปedx:eaxด้วยcdqเป็นวิธีการ edxzeroing

# 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, r32เป็นหนึ่งไบต์ ราคาถูกกว่า mov 8086 ข้อมูลที่จำเป็นต้องใช้ในขวานสำหรับสิ่งที่มากขึ้นกว่า> = 386 ดังนั้นพวกเขาจึงตัดสินใจที่จะใช้จ่ายมาก opcode xchg ax, r16พื้นที่ในตอนนี้ไม่ค่อยได้ใช้

  • การผสม push64 และ push16 สำหรับการรวมค่าสูงและค่าต่ำเข้ากับการลงทะเบียนครั้งเดียวจะบันทึกคำแนะนำการย้ายข้อมูล reg-reg รอบสองdivวินาที เคล็ดลับนี้เวอร์ชั่น 32 บิตทำงานได้ดียิ่งขึ้น: push16 / push16 / pop32รวมเพียง 5B ไม่ใช่ 6

เนื่องจากเราผลักดัน / ป๊อปอัพนี้ไม่ปลอดภัยสำหรับ asm อินไลน์ใน SysV amd64 ABI (ที่มีพื้นที่สีแดง)

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 จนถึงศูนย์และใช้movzx r32, [rsi+rcx]เพียงแค่ใช้จำนวนไบต์มากเกินไป

หากเราต้องการพิจารณาการเพิ่มพอยน์เตอร์ของเราเองรหัส 32 บิตน่าจะเป็นวิธีที่ควรทำ แม้แต่ตัว x32 ABI (ตัวชี้ 32 บิต) ก็ยังไม่เพียงพอเพราะinc esiเป็น 2B ใน amd64 แต่เป็น 1B ใน i386 ดูเหมือนยากที่จะเอาชนะxor eax,eax/ lodsb/ loop: รวม 4B เพื่อให้แต่ละองค์ประกอบเปลี่ยนศูนย์ให้กลายเป็น eax inc esi/ movzx r32, byte [esi]/loopเป็น 5B

scasเป็นอีกทางเลือกหนึ่งสำหรับการเพิ่มตัวชี้ด้วยคำสั่ง 1B ในโหมด 64 บิต ( rdi/ ediแทนrsiดังนั้นเราจึงใช้ตัวชี้หาเรื่องrdi) เราไม่สามารถใช้ผลการตั้งค่าสถานะscasเป็นเงื่อนไขลูปได้เนื่องจากเราไม่ต้องการให้ eax เป็นศูนย์ การจัดสรรการลงทะเบียนที่แตกต่างกันอาจจะสามารถบันทึกไบต์หลังจากวนซ้ำ


int[] อินพุต

ฟังก์ชั่นเต็มรูปแบบuint8_t[]คือคำตอบ "หลัก" เพราะมันเป็นความท้าทายที่น่าสนใจมากขึ้น เปิดออกไปint[]เป็นสิ่งที่ไม่สมเหตุสมผลเพื่อขอให้ผู้โทรของเราทำในภาษานี้ แต่จะประหยัด 2B

หากเรารับอินพุตเป็นอาร์เรย์จำนวนเต็ม 32 บิตที่คลายการบีบอัดเราสามารถบันทึกหนึ่งไบต์ได้อย่างง่ายดาย (ใช้lodsdและแทนที่xor eax,eax / cdqด้วยเพียงxor edx,edx)

เราสามารถบันทึกไบต์อื่นได้โดยการทำให้เป็นศูนย์ edx ด้วยlodsd/ 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) และadd eax, [rdi]แทนlodsdแต่ก็ยังมี 30 ไบต์ การประหยัดจากการมีhigheax ที่ส่วนท้ายของลูปนั้นมีความสมดุลกับโค้ดขนาดใหญ่ที่อื่น มันมีข้อได้เปรียบที่ไม่ขึ้นอยู่กับ0องค์ประกอบที่สิ้นสุดลงในอินพุตแม้ว่าอาจจะไม่มีเหตุผลสำหรับอาเรย์ที่ยังไม่ได้แพ็คซึ่งเรายังให้ความยาวอย่างชัดเจน


ไดรเวอร์ทดสอบ C ++ 11

ดูลิงค์ GitHub คำตอบนี้ใหญ่เกินไปและไดร์เวอร์ทดสอบมีคุณสมบัติเพิ่มเติมพร้อมโค้ดที่ใหญ่กว่า


2
ฉันอนุญาตให้ใช้จำนวนเต็มแทนไบต์เป็นหลักเพราะหลายภาษาไม่มีประเภทไบต์ จำนวนเต็ม 32- บิตอาจเป็นทางเลือกที่ผิดธรรมชาติสำหรับการชุมนุม แต่โค้ดกอล์ฟเกี่ยวกับการบีบอัดไบต์สุดท้ายในขณะที่อยู่ในกฎ หากตัวเลือก "ผิดธรรมชาติ" นำไปสู่การนับไบต์ที่ต่ำกว่าฉันจะบอกว่าไปได้
Dennis

@Dennis: ฉันเข้าใจความต้องการของกฎสำหรับบางภาษา ฉันหวังว่าจะมีวิธีสำหรับกฎที่จะให้คุณใช้เฉพาะint[]เมื่อจำเป็นเท่านั้นหรือบันทึกรหัสมากกว่า 4 ไบต์หรือบางอย่าง ฉันไม่มีปัญหาในการนำเสนอวิธีแก้ไขadler32(int[])ปัญหา แต่ฉันรู้สึกว่าadler32(char[])ปัญหาน่าสนใจกว่าเนื่องจากเป็นฟังก์ชัน adler32 จริง มันเป็นสิ่งที่ฉันต้องการจะเล่นกอล์ฟใน asm (และฉันชอบที่จะประหยัดอีกหนึ่งไบต์ตั้งแต่ในชีวิตจริง 33 ไบต์ = 48 ไบต์ถ้าฟังก์ชั่นต่อไปใช้ALIGN 16) ฉันเดาว่าฉันจะเล่นกอล์ฟต่อไปทั้งคู่
Peter Cordes

@Dennis: นอกจากนี้เราจำเป็นต้องจัดการกับ len = 0 กรณีหรือไม่ ฉันบันทึก 2B โดยใช้รูปแบบของวงแทนdo{}while(--len) while(len--){}
Peter Cordes

4
เมื่อพูดถึงคำอธิบายยิ่งมีรายละเอียดมากเท่าไหร่ก็ยิ่งดีเท่านั้น
Dennis

3
@cat: ไม่ฉันไม่พบความเจ็บปวด asm ฉันจะไม่ใช้เวลาเขียน Stackoverflow ตอบคำถาม asm / performance และอัปเดตwiki แท็ก 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

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

หากโซลูชั่นของจาวาควรจะเป็นโค้ดที่คอมไพล์ได้ทั้งหมดโปรดแจ้งให้เราทราบ

Ungolfed

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

บันทึก

คุณจะต้องแปลงอินพุตStringให้เป็นint[]( int[]สั้นกว่า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 Codels codelsize 1

ด้วย codelsize 20:

codelsize 20

หมายเหตุ / มันทำงานอย่างไร

  • เนื่องจากมันเป็นไปไม่ได้ที่จะใช้อาร์เรย์หรือสตริงเป็นอินพุตโปรแกรมนี้ทำงานโดยใช้ชุดของจำนวนเต็ม (แสดงถึงตัวอักษร ASCII) เป็นอินพุต ฉันคิดเกี่ยวกับการใช้อินพุตอักขระในตอนแรก แต่พยายามหาวิธีแก้ปัญหาที่ดีสำหรับการเลิกจ้างดังนั้นตอนนี้ก็จะสิ้นสุดลงเมื่อมีการป้อนตัวเลขใด ๆ ที่เล็กกว่า 1 เดิมเป็นเพียงค่าลบสำหรับการเลิกจ้าง แต่ฉันต้องเปลี่ยนการเริ่มต้นหลังจากเขียนโปรแกรมดังนั้นตอนนี้ฉันไม่สามารถพอดีกับที่จำเป็น2เท่านั้น1(26/45 ในภาพการติดตาม) สิ่งนี้ไม่สำคัญเพราะตามกฎการท้าทายอนุญาตให้ใช้อักขระ ASCII ที่พิมพ์ได้เท่านั้น

  • ดิ้นรนมาเป็นเวลานานด้วยการวนกลับเข้าไปใหม่แม้ว่าฉันจะพบทางออกที่สวยงามในที่สุด ไม่มีpointerหรือswitchการดำเนินการเฉพาะล่ามที่วิ่งเข้าไปในกำแพงจนกว่ามันจะเปลี่ยนกลับเป็น codel สีเขียวเพื่ออ่านอินพุต (43-> 44 ในภาพการติดตาม)

  • การเลิกลูปถูกทำให้สำเร็จโดยการทำซ้ำอินพุตแรกเพิ่ม 1 จากนั้นตรวจสอบว่ามันใหญ่กว่า 1 หรือไม่ถ้าใช่ codel Chooser จะถูกทริกเกอร์และการดำเนินการจะดำเนินต่อไปที่พา ธ ล่าง หากไม่เป็นเช่นนั้นโปรแกรมก็จะเหลือ (โคเดอร์สีเหลืองสดใส 31/50 ในอิมเมจการติดตาม)

  • ขนาดอินพุตที่ได้รับการสนับสนุนนั้นขึ้นอยู่กับการใช้งานล่ามแม้ว่ามันจะเป็นไปได้ที่จะสนับสนุนอินพุตขนาดใหญ่ตามอำเภอใจพร้อมล่ามที่ถูกต้อง (ตัวอย่างเช่นล่าม Java ที่ใช้BigIntegerเป็นค่าภายใน)

  • เพิ่งเห็นว่าการตั้งค่ารวมถึงหนึ่งที่ไม่จำเป็นDUPและCC(7-> 8-> 9 ในภาพการติดตาม) ไม่รู้เลยว่าเกิดอะไรขึ้น สิ่งนี้เป็นสิ่งที่ไม่มีประสิทธิภาพ แต่มันจะสลับ codel chooser 16 ครั้งซึ่งทำให้ไม่มีการเปลี่ยนแปลง

ติดตามภาพ

การตั้งค่าและลูปแรก:

starttrace

การเลิกลูป, เอาท์พุทและออก:

endtrace

เอาท์พุท

ยกโทษให้ฉันถ้าฉันมีเพียงหนึ่งเอาท์พุทมันใช้เวลานานในการป้อนข้อมูล: ^)

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

ติดตาม Npiet สำหรับ [65, -1]

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 version ของฉัน
Peter Cordes

สามารถบันทึก 1 ไบต์โดยใช้forแทนwhile:for(h=0,l=1;*B;)h+=l+=*B++;
ninjalj

5

เขาวงกต , 37 36 32 31 ไบต์

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

ลองออนไลน์!

อินพุตเป็นรายการของจำนวนเต็ม โปรแกรมสิ้นสุดลงพร้อมกับข้อผิดพลาด (ซึ่งข้อความแสดงข้อผิดพลาดไปที่ STDERR)

คำอธิบาย

ไพรเมอร์เขาวงกต:

  • เขาวงกตมีสองจำนวนเต็มความแม่นยำโดยพลการหลักและaux (iliary) ซึ่งในตอนแรกจะเต็มไปด้วยจำนวนศูนย์ (โดยปริยาย) จำนวนอนันต์
  • ซอร์สโค้ดมีลักษณะคล้ายเขาวงกตที่ซึ่งตัวชี้คำแนะนำ (IP) ตามทางเดินเมื่อมันสามารถ (แม้รอบมุม) รหัสเริ่มต้นที่อักขระตัวแรกที่ถูกต้องในลำดับการอ่านคือที่มุมบนซ้ายในกรณีนี้ เมื่อ IP มาถึงจุดเชื่อมต่อรูปแบบใด ๆ (เช่นเซลล์ที่อยู่ติดกันหลายแห่งนอกเหนือจากที่มาจาก) มันจะเลือกทิศทางตามด้านบนของสแต็กหลัก กฎพื้นฐานคือเลี้ยวซ้ายเมื่อลบเดินหน้าต่อไปเมื่อศูนย์เลี้ยวขวาเมื่อบวก และเมื่อหนึ่งในสิ่งเหล่านี้เป็นไปไม่ได้เพราะมีกำแพงแล้ว IP จะไปในทิศทางตรงกันข้าม IP ยังหันไปรอบ ๆ เมื่อกดปุ่ม Dead Dead
  • ตัวเลขจะถูกประมวลผลโดยการคูณด้านบนของสแต็กหลักด้วย 10 จากนั้นเพิ่มตัวเลข _ในการเริ่มต้นเป็นจำนวนใหม่คุณสามารถผลักดันศูนย์

แม้ว่ารหัสจะเริ่มต้นด้วย 4x2 "ห้อง" ซึ่งจริงๆแล้วเป็นสองลูปสองต่อสองแยกจากกันบีบด้วยกัน 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รวมถึงสำเนาของผลรวมเหนือค่าทั้งหมดและ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 - 1และHIGHเป็นศูนย์ยกเว้นเรายังไม่ได้ใช้โมดูโล่ ส่วนที่เหลือของรหัสเป็นเส้นตรงอย่างสมบูรณ์:

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 ตอนนี้โดนจุดจบและหมุนไปรอบ ๆ +และ*เป็นหลักไม่มี Ops เนื่องจากศูนย์ที่ด้านล่างสแต็ค 36ตอนนี้จะเปิดด้านบนของหลักลงใน63แต่ทั้งสอง{{ดึงสองศูนย์จากauxด้านบนของมัน จากนั้น%พยายามหารด้วยศูนย์ซึ่งจะยุติโปรแกรม

โปรดทราบว่าเขาวงกตใช้จำนวนเต็มความแม่นยำโดยพลการดังนั้นการชะลอการโมดูโลจนถึงจุดสิ้นสุดของผลรวมจะไม่ทำให้เกิดปัญหากับจำนวนเต็มล้น


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]e กรัม

(ขอบคุณ @xnor สำหรับเคล็ดลับนามแฝง / การเริ่มต้นที่น่าทึ่ง)


2
คุณสามารถทำการH=h=65521เริ่มต้นhในขณะที่นามแฝง 65521
xnor

4

J, 30 ไบต์

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

นี่อาจจะทำให้ข้นขึ้นด้วยรถไฟที่แตกต่างกัน

การใช้

ที่นี่x $ yสร้างรายการที่มีสำเนาของxy

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

คำอธิบาย

+/(+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 52ไบต์

บันทึก 2 ไบต์ด้วย @LuisMendo

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

รับอาร์เรย์จำนวนเต็มเป็นอินพุต

lowถูกนำมาจากองค์ประกอบสุดท้ายของhigh (ก่อนที่จะรวมกัน) แทนที่จะคำนวณผลรวมอย่างชัดเจนช่วยประหยัดยอดรวมของ ... 1 ไบต์ !

เรียกใช้ตัวอย่างใน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

Perl 6 , 60 bytes

{(.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ลงในรายการก่อนที่จะรวม

แก้ไข: ขอบคุณ @xnor สำหรับ 4 ไบต์


ดูเหมือนว่าคุณสามารถแยกออกจากข้อสรุปลงใน: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

แก้ไข: บันทึก 2 ไบต์ด้วย @ user81655


3

ฟังก์ชั่น ARM Thumb-2 ยอมรับได้uint8_t[]: 40 ไบต์ (36B สำหรับ 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เป็นเพียง 6B ในโหมด Thumb2 สำนวนมาตรฐานสำหรับ% 8B ในโหมด Thumb2:

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

adler(char *)รุ่นความยาวโดยนัยเป็นขนาดรหัสเดียวกับความยาวอย่างชัดเจนadler(uint8_t[], uint32_t len)รุ่นเดียวกันรหัสขนาดความยาวอย่างชัดเจนเราสามารถตั้งค่าสถานะสำหรับเงื่อนไข loop-exit ด้วยคำสั่ง 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 ข้าม devel เพียงสำหรับคำตอบนี้เพราะผมคิดว่าความคิดบอกกล่าว-ลบของฉันเป็นที่เรียบร้อย.) เมื่อวันที่ 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.cppมีกรณีทดสอบเดียวกันและmain()สำหรับคำตอบ 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 ไบต์โดยใช้แบบแผนการโทรที่กำหนดเอง

เกิดขึ้นในการลงทะเบียนและไม่รักษา regs นอกเหนือจาก bp (และ sp)

ในรหัส 16 บิตเราจะคืนค่า 32 บิตในdx:axคู่ทะเบียน ซึ่งหมายความว่าเราไม่ได้มีการใช้จ่ายใด ๆ คำแนะนำการควบรวมhighและการlowเข้าสู่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 ไบต์

ผ่านการทดสอบโดยการรวบรวมรหัสเดียวกันสำหรับโหมด 32bit ดังนั้นฉันสามารถเรียกมัน (ที่มีฟังก์ชั่นเสื้อคลุม) จาก 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 บิตเราไม่สามารถเลื่อนการลดโมดูโลได้จนกว่าจะถึงลูป มีความแตกต่างที่น่าสนใจระหว่าง 16bit และถูกดำเนินการขนาดอื่น ๆ : m = 65521( 0xFFF1) มากกว่าครึ่ง 65536 การลบmเกี่ยวกับการดำเนินการเก็บค่าต่ำกว่า 2 เมตร * high=0xFFF0 + 0xFFF0แม้ว่า หลังจากวนลูปการเปรียบเทียบและการลบจะทำเคล็ดลับแทนที่จะเป็นdivหลังจากที่วงเปรียบเทียบและลบจะทำเคล็ดลับแทน

ฉันมาพร้อมกับเทคนิคใหม่ในการลดการลงทะเบียนแบบโมดูโลหลังจากการเพิ่มที่สามารถผลิตได้ แทนที่จะ zeroing ครึ่งบนของการป้อนข้อมูลสำหรับdivใช้setc dlในการสร้างเงินปันผล 32bit ถือผลเพิ่มที่ไม่ถูกตัดทอน ( dhจะกลายเป็นศูนย์แล้ว) (divทำ 32b / 16b => 16 บิตส่วน)

setcc(3 bytes) ถูกนำมาใช้กับ 386 ในการทำงานนี้ใน 286 หรือก่อนหน้านี้ที่ดีที่สุดที่ผมเคยเกิดขึ้นกับการนำมาใช้ประโยชน์ที่ไม่มีเอกสารsalcการเรียนการสอน (ชุด AL จากการดำเนินการ) มันเป็นรหัสสำหรับหนึ่งไบต์sbb al,alดังนั้นเราจึงสามารถใช้salc/ neg alก่อนทำxchg ax, dx(ซึ่งเราต้องการอยู่ดี) โดยไม่ต้องsalcมีลำดับ sbb dx,dx4B: neg dx/ เราไม่สามารถใช้ 3B sbb dx,dx/ inc dxเพราะที่จะเลียนแบบมากกว่าsetncsetc


ฉันพยายามใช้ขนาดตัวถูกดำเนินการ 32 บิตแทนที่จะจัดการกับการพกพา แต่มันไม่ใช่แค่addคำแนะนำที่ต้องการคำนำหน้าขนาดตัวถูกดำเนินการ คำแนะนำในการตั้งค่าคงที่และอื่น ๆ จำเป็นต้องมีส่วนนำหน้าของตัวถูกดำเนินการด้วยเช่นกันดังนั้นจึงไม่ได้เล็กที่สุด



2

Perl 5, 43 ไบต์

42 ไบต์บวก 1 สำหรับ-aEแทน-e

อินพุตเป็นจำนวนเต็มฐานสิบคั่นด้วยช่องว่าง

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

ปลายหมวกของฉันไปที่Sp3000ซึ่งฉันได้นำความคิดสำหรับคำตอบนี้

มันทำงานอย่างไร:

  1. เพราะ-a, $. เริ่มต้นที่ 1 และ@Fเป็นอาร์เรย์การป้อนข้อมูล $hเริ่มต้นที่ 0 $_ถูกใช้โดย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 ]

Ungolfed:

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

คาดว่าลำดับของตัวเลขหรือสตริงใด ๆ (ไม่แตกต่างกันมากนักแม้ว่าจะไม่เหมือนกันในทางเทคนิค)

ฉันไม่ทราบว่าวิธีการนี้จะทำงานได้ตามขีด จำกัด ที่กำหนดในเวอร์ชันของ Factor ที่คอมไพล์ด้วยขนาดคำ 32 บิต แต่บนเครื่อง 6GB 64-bit 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 แอดเลอร์แก้ปัญหา

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

Ungolfed

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

การใช้

=> (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 ตัวอักษรกอล์ฟ)

Ungolfed

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

แข็งแรงเล่นกอล์ฟ

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 ฉันเชื่อว่ามันทำ แต่ฉันไม่แน่ใจว่ามันรองรับ "tuples จริง ๆ หรือไม่"
brianush1

BrainFuck ก็เช่นกันดังนั้นคุณอาจไม่เป็นไร หากการทำให้เสร็จสมบูรณ์สามารถค้นหาหมายเลขเฉพาะและสามารถทำสิ่งพื้นฐานที่ภาษาอื่น ๆ สามารถทำได้ (และทำได้) มันจะทำงานได้ดี :) CSS ไม่ใช่ภาษาโปรแกรมด้วยตัวเองและไม่ใช่ HTML แต่ CSS3 + HTML ทัวริงสมบูรณ์และสามารถค้นหาช่วงเวลา
แมว

ดังนั้นมันก็โอเคที่จะใช้ใน CodeGolf?
brianush1

ฉันคิดอย่างนั้น - ฉันรู้ทั้ง TMP และ Lua ดังนั้นคำอธิบายของรหัสนี้จะเป็นความช่วยเหลือที่ดี (และจะทำให้คำตอบนี้เป็นคำตอบที่ดี) : D
cat

1

Python 3.5, 82 ไบต์:

( -1 ไบต์ขอบคุณNeil ! )

( -1 ไบต์ขอบคุณmathmandan ! )

( -4 ไบต์ขอบคุณเดนนิส ! )

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

lambdaฟังก์ชั่นที่ไม่ระบุชื่อ ยอมรับอาร์เรย์ไบต์ใช้อัลกอริธึมทั้งหมดกับอาร์เรย์และส่งผลลัพธ์ ทำงานได้สำเร็จสำหรับทุกกรณีทดสอบ คุณเรียกสิ่งนี้โดยการกำหนดตัวแปรให้แล้วเรียกตัวแปรนั้นเหมือนคุณจะเรียกใช้ฟังก์ชันปกติ หากคุณกำลังใช้เชลล์คุณควรส่งเอาต์พุตโดยไม่มีฟังก์ชันการพิมพ์ อย่างไรก็ตามถ้าคุณไม่ได้คุณจะต้องตัดการเรียกใช้ฟังก์ชันในprint()ฟังก์ชันเพื่อดูผลลัพธ์จริง ๆ

ลองออนไลน์! (Ideone)


(E+15)65536เป็นจริงไบต์นานกว่า
Neil

@ Neil ขอบคุณสำหรับเคล็ดลับ ตอนนี้ได้รับการแก้ไขแล้ว
R. Kap

@ Sp3000 งั้นเหรอ? มันจะสำคัญถ้าพวกเขาเพิ่มไบต์บางส่วน แต่ความจริงที่ว่าพวกเขาเพิ่มไม่มีไบต์วางตัวดีกับฉัน
R. Kap

4**865536เป็นไบต์สั้นกว่า
mathmandan

คุณสามารถบันทึก 4 ไบต์ได้โดยวางวงเล็บไว้รอบตัวสร้างและวนซ้ำ 0ไปlen (w) สามารถบันทึกได้อีก 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บล็อกฟิวส์อีก 256 และเปิดตัวขึ้นต่อเครื่องปฏิกรณ์ดังกล่าวข้างต้นซึ่ง fissions อนุภาคเป็นสองหลายมวลของ65536มวลแต่ละเปิดตัวไปทางซ้ายและขวา (ที่อนุภาคที่เหมาะสมจะถูกทำลายทันทีโดยเทอร์มิ)
  • อนุภาคด้านซ้ายกระทบกับเครื่องปฏิกรณ์อื่นและผ่านการแยกฟิชชันโดยแยกเป็นสองอนุภาคที่มีมวลเท่ากันโดยขึ้นและลง
  • พลังการเดินทางที่เพิ่มขึ้นของอนุภาคสองอนุภาคผ่านการจัดการมวลสุทธิที่ไม่เป็นศูนย์สะท้อนไปทางซ้ายจากนั้นตั้งค่าตัวคูณมวลของเครื่องปฏิกรณ์ฟิวชั่น เครื่องปฏิกรณ์นี้จะเป็นวิธีที่เราคูณ H block
  • อนุภาคที่เคลื่อนที่ลงนั้นจะสะท้อนไปทางซ้ายและหลั่งออกมาในระยะยาว 65521 (นายกขนาดใหญ่ของเรา)
  • กระจกหมุน ( Z) ในตอนท้ายของการวิ่งทำให้อนุภาคซ้ำตัวนายกส่งหนึ่งกลับไปทางขวาซึ่งท้ายที่สุดมันจะกำหนดมวลที่เก็บไว้ของเครื่องปฏิกรณ์ฟิชชัน (^ ) นี่คือวิธีที่เราจะใช้ตัวดำเนินการโมดูลัสกับบล็อก H
  • สำเนาที่สองจะสะท้อนกลับมาซึ่งจะทำหน้าที่คล้ายกับเครื่องปฏิกรณ์ฟิชชัน ( <) เราจะใช้สำหรับบล็อก L
  • ตอนนี้ค่าคงที่ของเราอยู่ในตำแหน่งแล้วเรามีส่วนร่วมใน shenanigans ที่มุมบนซ้ายเพื่ออ่านอินพุตของเราและสร้างสองรายการของเรา พูดตามตรงฉันลืมว่ามันทำงานอย่างไร แต่สำหรับสายว่างฉันต้องชะลอการรวมอนุภาคบล็อก H ซึ่งจะอธิบาย|S"หอระบายความร้อน"
  • \Y/ รวมบล็อก L (ซึ่งเข้ามาทางช่องทางซ้าย) และบล็อก H (ซึ่งเข้ามาทางช่องทางขวา) จากนั้นกดให้บล็อกดังกล่าวเป็นเทอร์มิเนเตอร์ซึ่งกำหนดรหัสทางออกให้กับมวลที่ถูกหลอมรวม

ดูเหมือนว่าฉันจะไม่ทำงานกับล่ามทางการ ( ลิงก์ ) เว้นแต่ฉันจะทำผิดพลาดที่ไหนสักแห่ง ฉันจะนำพอร์ตของคุณไปที่ F # ได้ที่ไหน
เดนนิส

@Dennis ฉันกำลังพยายามหาว่าบั๊กอยู่ที่จุดสิ้นสุดหรือไม่ แต่ฉันก็ไม่สามารถให้ล่ามทำงานได้เช่นกัน ฉันจะดูว่าฉันสามารถทำงานได้หรือไม่แล้วอัปเดตคำตอบถ้าจำเป็น
Andrew Coonce

@Dennis ปรากฏว่าล่ามออนไลน์ไม่ได้จัดการกับรหัสข้อผิดพลาดการยกเลิก*ซึ่งเป็นวิธีที่ฉันส่งคืนผลลัพธ์ ฉันจะดูว่าฉันสามารถหาล่ามคนอื่นเพื่อตรวจสอบผลลัพธ์ในวันพรุ่งนี้ได้ไหม
Andrew Coonce
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.