Thử thách chơi gôn CPU GOLF: Phân vùng chính


14

Thách thức này là vấn đề đầu tiên trong một loạt các cố nên được ghi trong CPU GOLF . Bạn có thể tìm thấy cái tiếp theo ở đây

Một phân vùng của một số, Nlà một danh sách các số cộng lại N. Một phân vùng thủ là một danh sách các số nguyên tố mà thêm đến N.

Đối với thử thách này, bạn được cung cấp một số nguyên duy nhất N ≥ 2. Bạn cần tạo phân vùng nguyên tố ngắn nhất có thể cho N. Nếu có nhiều phân vùng có thể, bạn có thể in bất kỳ phân vùng nào.

Ví dụ:

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

Chương trình của bạn nên được viết bằng CPU GOLF . Đối với đầu vào / đầu ra, bạn có thể sử dụng STDIO hoặc các thanh ghi. Danh sách có thể theo bất kỳ thứ tự nào và nếu bạn đang sử dụng STDOUT, có thể được phân tách bằng khoảng trắng hoặc dấu phẩy (không cần dấu ngoặc). Rõ ràng, mã hóa các giải pháp không được phép, cũng không mã hóa nhiều hơn các số nguyên tố đầu tiên.

Đây là một vấn đề nhất, vì vậy câu trả lời giải quyết các ví dụ ở trên với số lượng chu kỳ ít nhất sẽ thắng!


Đã đến lúc tôi quảng bá GOLF-C , nơi cung cấp một cách nhanh hơn để chạy các chương trình .golf .. và có thể làm việc với nó nhiều hơn nữa
Claudiu

@Claudiu Golf-C chắc chắn sẽ được cho phép ở đây
Nathan Merrill

1
Có giới hạn kích thước?
lirtosiast

Tôi nghi ngờ các phỏng đoán của Goldbach và Levy sẽ có ích ở đây ...
2012rcampion 01/07/2015

@ThomasKwa không, không giới hạn kích thước, nhưng không có số nguyên tố mã hóa cứng (ngoài cặp đôi đầu tiên)
Nathan Merrill

Câu trả lời:


1

159.326.251 chu kỳ

Đầu vào là n, đầu ra là r, st(bỏ qua số không).

# 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

Testcase:

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

Tổng số chu kỳ cho các ví dụ: 477.918.603

Cập nhật 1: Cập nhật để sử dụng phỏng đoán của Lemoine .

Cập nhật 2: Cập nhật để sử dụng Sàng của Eratosthenes thay vì ngây thơ tìm các số nguyên tố.

Chạy với:

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

Chạy ví dụ:

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

Số chu kỳ cho ví dụ đầu vào:

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

Chúng tôi coi các (N+1)*8byte đầu tiên của heap, là một mảng chứa N+1các giá trị 64 bit. (Vì heap bị giới hạn về kích thước, điều này sẽ chỉ hoạt động N < 2^57). Giá trị của mục tại i*8chỉ ra thời tiết ilà một số nguyên tố:

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

Khi chúng ta hoàn thành việc xây dựng mảng, nó sẽ trông như thế [-1, -1, 3, 5, -1, 7, -1, 11, -1, -1, -1, 13, ...].

Chúng tôi sử dụng Sàng của Eratosthenes để xây dựng mảng.

Tiếp theo chương trình thực hiện như sau trong mã giả:

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

Điều này được đảm bảo để hoạt động vì phỏng đoán của Lemoinephỏng đoán yếu của Goldbach . Phỏng đoán của Lemoine chưa được chứng minh, nhưng có lẽ đúng với các số dưới 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

Bạn có thể in số chu kỳ cho các số được liệt kê trong ví dụ không?
Nathan Merrill

@NathanMerrill Xong.
Tyilo 7/07/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.