การแข่งขันกอล์ฟ GOLF CPU: พาร์ติชั่นอันดับหนึ่ง


14

ความท้าทายนี้เป็นครั้งแรกของซีรีส์ของปัญหาที่ควรจะเขียนในCPU GOLF คุณสามารถหาคนต่อไปที่นี่

พาร์ติชันของตัวเลขเป็นรายการตัวเลขที่เพิ่มขึ้นถึงN พาร์ทิชันที่สำคัญคือรายการของตัวเลขที่สำคัญที่เพิ่มขึ้นเป็นNN

N ≥ 2สำหรับความท้าทายนี้คุณจะได้รับจำนวนเต็มเดียว Nคุณจำเป็นต้องสร้างพาร์ทิชันที่สำคัญที่สั้นที่สุดที่เป็นไปได้ หากมีหลายพาร์ติชันที่เป็นไปได้คุณสามารถพิมพ์พาร์ทิชันเหล่านั้นได้

ตัวอย่าง:

9: [2, 7]
12: [5, 7]
95: [89, 3, 3]
337: [337]
1023749: [1023733, 13, 3]
20831531: [20831323, 197, 11]

โปรแกรมของคุณควรจะเขียนในGOLF CPU สำหรับอินพุต / เอาต์พุตคุณสามารถใช้ STDIO หรือรีจิสเตอร์ รายการสามารถอยู่ในลำดับใดก็ได้และหากคุณใช้ STDOUT สามารถคั่นด้วยช่องว่างหรือเครื่องหมายจุลภาค (ไม่ต้องใช้วงเล็บ) เห็นได้ชัดว่าการเข้ารหัสฮาร์ดไดร์ฟไม่ได้รับอนุญาตและไม่ได้เข้ารหัสฮาร์ดโค้ดมากกว่าสองสามช่วงแรก

นี่เป็นปัญหาดังนั้นคำตอบที่แก้ตัวอย่างข้างต้นด้วยจำนวนรอบที่น้อยที่สุดจะเป็นผู้ชนะ!


ถึงเวลาที่ฉันจะโปรโมตGOLF-Cซึ่งเสนอวิธีที่เร็วกว่าในการรันโปรแกรม . golf .. และอาจจะทำให้สำเร็จมากกว่านี้อีก
Claudiu

@Claudiu Golf-C จะได้รับอนุญาตที่นี่อย่างแน่นอน
Nathan Merrill

1
มีการ จำกัด ขนาดหรือไม่?
lirtosiast

ฉันสงสัยว่าการคาดคะเนของ Goldbach และ Levy จะมีประโยชน์ที่นี่ ...
2012rcampion

@ThomasKwa ไม่ จำกัด ขนาด แต่ไม่มีการเข้ารหัสยาก (เกินกว่าคู่แรก)
Nathan Merrill

คำตอบ:


1

159,326,251 รอบ

การป้อนข้อมูลเป็นnเอาท์พุทเป็นr, sและt(ไม่สนใจศูนย์)

# Input in register n
# Outputs in registers r, s, t
# (I use the return value as a debug parameter)

# hardcoded case n=2
cmp c, n, 2
jz skip_n2, c
  mov r, 2
  halt 0
skip_n2:
# hardcoded case n=4
cmp c, n, 4
jz skip_n4, c
  mov r, 2
  mov s, 2
  halt 0
skip_n4:

# Sieve of Eratosthenes
mov i, 1
sieve_loop:
  add i, i, 2
  lb a, i
  jnz sieve_loop, a

  mulu j, k, i, i
  geu c, j, n
  jnz end_sieve_loop, c

  sieve_inner_loop:
    sb j, 1
    add j, j, i
    lequ c, j, n
    jnz sieve_inner_loop, c

  jmp sieve_loop

end_sieve_loop:

lb a, n

# if n is even, skip to search
and c, n, 1
jz search, c

# if n is prime, the partition is simply [n]
jnz not_prime, a
  mov r, n
  halt 1
not_prime:

# if n is odd, check n-2
sub i, n, 2
lb a, i

jnz sub_3, a
# if n-2 is prime, the partition is [2, n-2]
mov r, 2
mov s, i
halt 2

sub_3:
# otherwise the partition is [3] + partition(n-3)
mov t, 3
sub n, n, 3

search:
mov i, 1
sub n, n, 1

search_loop:
  add i, i, 2
  sub n, n, 2
  lb a, i
  jnz search_loop, a
  lb a, n
  jnz search_loop, a
  mov r, i
  mov s, n
  halt 3

Testcases:

robert@unity:~/golf-cpu$ ./assemble.py partition.golf
robert@unity:~/golf-cpu$ ./golf.py -p r,s,t partition.bin n=9
2, 7, 0
Execution terminated after 51 cycles with exit code 2.
robert@unity:~/golf-cpu$ ./golf.py -p r,s,t partition.bin n=12
5, 7, 0
Execution terminated after 77 cycles with exit code 3.
robert@unity:~/golf-cpu$ ./golf.py -p r,s,t partition.bin n=95
3, 89, 3
Execution terminated after 302 cycles with exit code 3.
robert@unity:~/golf-cpu$ ./golf.py -p r,s,t partition.bin n=337
337, 0, 0
Execution terminated after 1122 cycles with exit code 1.
robert@unity:~/golf-cpu$ ./golf.py -p r,s,t partition.bin n=1023749
13, 1023733, 3
Execution terminated after 6654139 cycles with exit code 3.
robert@unity:~/golf-cpu$ ./golf.py -p r,s,t partition.bin n=20831531
229, 20831299, 3
Execution terminated after 152670560 cycles with exit code 3.
robert@unity:~/golf-cpu$ 

7

รอบทั้งหมดสำหรับตัวอย่าง: 477,918,603

การปรับปรุงที่ 1:การปรับปรุงเพื่อใช้การคาดเดาของ Lemoine

อัปเดต 2:อัปเดตเพื่อใช้ตะแกรงของ Eratosthenesแทนการค้นหาช่วงเวลา

ทำงานด้วย:

python3 assemble.py 52489-prime-partitions.golf
python3 golf.py 52489-prime-partitions.bin x=<INPUT>

ตัวอย่างการเรียกใช้:

$ python3 golf.py 52489-prime-partitions.bin x=10233
5
5
10223
Execution terminated after 194500 cycles with exit code 0.

จำนวนรอบสำหรับอินพุตตัวอย่าง:

Input    Cycles
9        191
12       282
95       1,666
337      5,792
1023749  21,429,225
20831531 456,481,447

เราพิจารณา(N+1)*8ไบต์แรกของฮีปเพื่อเป็นอาร์เรย์ที่มีค่าN+164- บิต (เนื่องจากฮีปมีขนาด จำกัด จึงเหมาะสำหรับN < 2^57) ค่าของรายการที่i*8ระบุว่า wether iเป็นค่าเฉพาะ:

Value Description
-1    Not a prime
0     Unknown
1     The largest prime found
n > 1 This is a prime and the next prime is n

[-1, -1, 3, 5, -1, 7, -1, 11, -1, -1, -1, 13, ...]เมื่อเราจะทำสร้างอาร์เรย์มันจะมีลักษณะเช่น

เราใช้Sieve of Eratosthenesเพื่อสร้างอาเรย์

ถัดไปโปรแกรมทำสิ่งต่อไปนี้ในรหัสเทียม:

if is_prime(x):
    print x
else:
    if is_even(x):
        for p in primes:
            if is_prime(x - p):
                print p, x - p
                exit
    else:
        if is_prime(x - 2):
            print 2, x - 2
        else:
            for p in primes:
                if is_prime(x - 2 * p):
                    print p, p, 2 * p
                    exit

นี้มีการประกันการทำงานเนื่องจากการคาดเดา Lemoine ของและGoldbach ของการคาดเดาที่อ่อนแอ การคาดเดาของ Lemoine ยังไม่ได้รับการพิสูจน์ แต่อาจเป็นจริงสำหรับตัวเลขที่ต่ำกว่า 2 ^ 57

    call build_primes

    mov q, x
    call is_prime

    jnz print_prime, a

    and b, x, 1
    jz find_pair, b

    # Check if x - 2 is a prime
    sub q, x, 2
    call is_prime
    jnz print_prime_odd2, a

# Input: x, b
find_pair:
    mov p, 2
find_pair_loop:
    mov d, p
    jz find_pair_even, b

    add d, d, p

find_pair_even:
    sub q, x, d

    call is_prime
    jnz print_prime2_or_3, a

    shl i, p, 3
    lw p, i
    jmp find_pair_loop

print_prime2_or_3:
    jz print_prime2, b

    mov x, p
    call write_int_ln

print_prime2:
    mov x, p
    call write_int_ln

    mov x, q
    call print_prime

print_prime_odd2:
    mov p, 2
    call print_prime2

print_prime:
    call write_int_ln
    halt 0

# Input: x
# Memory layout: [-1, -1, 3, 5, -1, 7, -1, 11, ...]
# x: max integer
# p: current prime
# y: pointer to last found prime
# i: current integer
build_primes:
    sw 0, -1
    sw 8, -1
    sw 16, 1
    mov y, 16

    mov p, 2

build_primes_outer:
    mulu i, r, p, p
    jnz build_primes_final, r

    geu a, i, x
    jnz build_primes_final, a

build_primes_inner:
    shl m, i, 3
    sw m, -1

    add i, i, p

    geu a, i, x
    jz build_primes_inner, a

build_primes_next:
    inc p
    shl m, p, 3
    lw a, m
    jnz build_primes_next, a

    sw y, p
    mov y, m
    sw y, 1

    jmp build_primes_outer

build_primes_final:
    inc p
    geu a, p, x
    jnz build_primes_ret, a

    shl m, p, 3
    lw a, m
    jnz build_primes_final, a

    sw y, p
    mov y, m
    sw y, 1

    jmp build_primes_final

build_primes_ret:
    ret

# Input: q
# Output: a
is_prime:
    shl m, q, 3
    lw a, m
    neq a, a, -1
    ret a

write_int:
    divu x, m, x, 10
    jz write_int_done, x
    call write_int
write_int_done:
    add m, m, ord("0")
    sw -1, m
    ret

write_int_ln:
    call write_int
    mov m, ord("\n")
    sw -1, m
    ret

คุณสามารถพิมพ์จำนวนรอบสำหรับหมายเลขที่แสดงในตัวอย่างได้หรือไม่?
Nathan Merrill

@NathanMerrill เรียบร้อยแล้ว
Tyilo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.