GOLF CPU Golf Mücadelesi: Ana Bölümler


14

Bu zorluk, GOLF CPU'da yazılması gereken sorununun ilkidir . Bir sonrakini burada bulabilirsiniz

Bir sayının bölümü,, Ntoplanan sayıların listesidir N. Bir asal bölüm kadar ekleyin asal sayıların bir listedir N.

Bu zorluk için size tek bir tamsayı verilir N ≥ 2. İçin mümkün olan en kısa ana bölümü oluşturmanız gerekir N. Birden fazla olası bölüm varsa, bunlardan herhangi birini yazdırabilirsiniz.

Örnekler:

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

Programınız GOLF CPU ile yazılmalıdır . Giriş / çıkış için STDIO veya kayıtları kullanabilirsiniz. Liste herhangi bir sırada olabilir ve STDOUT kullanıyorsanız boşluk veya virgülle ayrılabilir (parantez gerekmez). Açıkçası, çözümlerin kodlanmasına izin verilmez ve ilk birkaç primerden daha fazla kodlamaya izin verilmez.

Bu sorunudur, bu nedenle yukarıdaki örnekleri en az sayıda döngü ile çözen cevap kazanır!


Benim için .golf programlarını çalıştırmak için daha hızlı bir yol sunan GOLF-C'yi tanıma zamanı .. ve belki de biraz daha üzerinde çalışma
Claudiu

@Claudiu Golf-C'ye kesinlikle burada izin verilir
Nathan Merrill

1
Boyut sınırı var mı?
lirtosiast

Goldbach ve Levy varsayımlarının burada
işe

@ThomasKwa no, boyut sınırı yok, ancak sabit kodlama primleri yok (ilk çiftin ötesinde)
Nathan Merrill

Yanıtlar:


1

159.326.251 döngü

Girdi olan nçıkış, r, sve t(sıfır göz ardı edilerek).

# 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

Örnekler için toplam döngü sayısı: 477.918.603

Güncelleme 1: Lemoine varsayımlarını kullanmak için güncellendi .

Güncelleme 2: Asalleri saf bulmak yerine Eratosthenes Elekini kullanacak şekilde güncellendi .

Şununla çalıştır:

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

Örnek çalışma:

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

Döngü sayısı, örneğin giriş:

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

(N+1)*8Yığının ilk baytını N+164 bit değerler içeren bir dizi olarak kabul ediyoruz . (Yığın boyutu sınırlı olduğundan, bu yalnızca işe yarayacaktır N < 2^57). i*8Adresindeki girişin değeri, iasal olup olmadığını gösterir :

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

Diziyi oluşturmayı bitirdiğimizde, bu şekilde görünecektir [-1, -1, 3, 5, -1, 7, -1, 11, -1, -1, -1, 13, ...].

Biz kullanmak Eratosthenes Elek dizisi inşa etmek.

Sonra program sözde kodda şunları yapar:

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'in varsayımı ve Goldbach'ın zayıf varsayımı nedeniyle bunun çalışması garanti edilir . Lemoine'in varsayımı henüz kanıtlanmamıştır, ancak muhtemelen 2 ^ 57'nin altındaki sayılar için doğrudur.

    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

Örnekte listelenen sayılar için döngü sayısını yazdırabilir misiniz?
Nathan Merrill

@NathanMerrill Bitti.
Tyilo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.