Solve problem 301.
parent
8214d9f424
commit
e0be0b71cb
|
@ -0,0 +1,70 @@
|
|||
from functools import lru_cache
|
||||
|
||||
|
||||
@lru_cache
|
||||
def x_naiv(s):
|
||||
zcount = s.count(0)
|
||||
if zcount == 3:
|
||||
return 0
|
||||
elif zcount == 2:
|
||||
return 1
|
||||
elif zcount == 1:
|
||||
sl = list(s)
|
||||
sl.remove(0)
|
||||
if sl[0] == sl[1]:
|
||||
return 0
|
||||
|
||||
s = list(s)
|
||||
for i in range(len(s)):
|
||||
for v in range(1, s[i] + 1):
|
||||
ns = list(s)
|
||||
ns[i] -= v
|
||||
if x_naiv(tuple(sorted(ns))) == 0:
|
||||
# Other player loses.
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def x_nim_sum(s):
|
||||
""" I wasn't able to deduce this myself quickly and looked it up instead. """
|
||||
return 0 if (s[0] ^ s[1] ^ s[2]) == 0 else 1
|
||||
|
||||
|
||||
def test_nim_functions():
|
||||
assert(x_naiv(tuple([0, 0, 0])) == 0)
|
||||
assert(x_naiv(tuple([1, 0, 0])) == 1)
|
||||
assert(x_naiv(tuple([1, 1, 0])) == 0)
|
||||
assert(x_naiv(tuple([1, 1, 1])) == 1)
|
||||
assert(x_naiv(tuple([1, 2, 3])) == 0)
|
||||
|
||||
for n1 in range(0, 8):
|
||||
for n2 in range(1, n1 + 1):
|
||||
for n3 in range(1, n2 + 1):
|
||||
s = tuple([n1, n2, n3])
|
||||
assert x_naiv(s) == x_nim_sum(s)
|
||||
|
||||
|
||||
def euler_301():
|
||||
test_nim_functions()
|
||||
|
||||
# log(2**30, 10) ~= 9 -> 1 billion easy brute force
|
||||
# Probably a more efficient computation is possible by counting the permutations
|
||||
# where all binary digits are zero.
|
||||
# 0 0 0 -> 0
|
||||
# 0 0 1 -> 0
|
||||
# 0 1 1 -> 0
|
||||
|
||||
r = 0
|
||||
for n in range(1, 2**30 + 1):
|
||||
s = tuple([n, 2 * n, 3 * n])
|
||||
xr = x_nim_sum(s)
|
||||
if xr == 0:
|
||||
r += 1
|
||||
return r
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = euler_301()
|
||||
print("e301.py: " + str(solution))
|
||||
# assert(solution == 0)
|
||||
|
Loading…
Reference in New Issue