Total cycles for examples: 29,566,640
It cubes the input number in the algorithm, so the input can't be larger than around 2^21
.
Cycle count for example input:
Input Cycles
1 153
5 75
8 773
24 1,528
100 3,185
1080 27,608
468719 9,676,846
468720 9,764,814
468721 10,091,658
I'm using an algorithm I found on OEIS, which does the following:
cuboids(n):
if is_prime(n):
return 1
res = 0
for d in divisors(n):
if d^3 <= n:
for d0 in divisors(n/d):
if d0^2 <= n/d:
res += 1
if d0 < d:
res -= 1
return res
This might actually be slower than just trying every divisor combination and checking if d1 <= d2 <= d3
, however the bottle-neck is finding the prime anyway.
Divisors are found by using the prime factorization of the number. I'm using the same method to build an array of all primes below the input number as I used in the previous problem.
Run with:
python3 assemble.py 52489-cuboids.golf
python3 golf.py -d 52489-cuboids.bin x=<INPUT>
Output will be in the t
register.
Example run:
$ python3 golf.py -d 52489-cuboids.bin x=1080 | grep 'Execution\|t: '
Execution terminated after 27608 cycles with exit code 0. Register file at exit:
t: 52 0x34
Code:
call build_primes
mov q, x
call is_prime
jnz prime, a
shl m, x, 3
add m, m, 8
call divisors
mov y, x
mov k, l
mov t, 0
mov p, m
outer_loop:
cmp a, p, k
jnz done, a
lw d, p
add p, p, 8
mulu a, r, d, d
mulu a, r, a, d
lequ a, a, y
jz outer_loop, a
divu x, r, y, d
mov m, k
call divisors
mov q, m
inner_loop:
cmp a, q, l
jnz outer_loop, a
lw o, q
add q, q, 8
mulu a, r, o, o
lequ a, a, x
jz skip1, a
inc t
skip1:
leu a, o, d
jz inner_loop, a
dec t
jmp inner_loop
done:
halt 0
prime:
mov t, 1
halt 0
# Input: x, m
# Output: l
# x: input number
# m: memory location to store divisors
# l: memory location where last divisor is stored + 8
divisors:
sw m, 1
add l, m, 8
mov p, 2
divisors_outer:
mov q, 1
push z, 0
divisors_inner:
divu y, r, x, p
jnz divisors_not_divisible, r
mulu q, r, q, p
push z, q
mov x, y
jmp divisors_inner
divisors_not_divisible:
mov w, l
divisors_not_divisible_outer:
mov v, m
pop t, z
jz divisors_not_divisible_last, t
divisors_not_divisible_inner:
cmp a, v, w
jnz divisors_not_divisible_outer, a
lw s, v
mulu a, r, s, t
sw l, a
add l, l, 8
add v, v, 8
jmp divisors_not_divisible_inner
divisors_not_divisible_last:
shl i, p, 3
lw p, i
cmp a, x, 1
jz divisors_outer, a
ret l
# 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