Solve problem 78 and 79 in Python.

main
Felix Martin 2019-08-29 00:29:12 -04:00
parent 45692feacb
commit 5fc0e4324f
3 changed files with 258 additions and 4 deletions

View File

@ -1,8 +1,126 @@
from functools import lru_cache
def euler_078():
return 0
piles_look_up = {}
def count_piles_limited(n, max_size):
if max_size == 1:
return 1
try:
return piles_look_up[(n, max_size)]
except KeyError:
pass
count = 0
for i in range(1, n):
n_new = n - i
count_i = count_piles_limited(n_new, min([n_new, i]))
count += count_i
piles_look_up[(n, i)] = count
# for n itself
count += 1
piles_look_up[(n, n)] = count
return count
piles_look_up_modular = {}
def count_piles_limited_modular(n, max_size, modulu):
if max_size == 1:
return 1
try:
return piles_look_up_modular[(n, max_size)]
except KeyError:
pass
count = 0
for i in range(1, n):
n_new = n - i
count_i = count_piles_limited_modular(
n_new, min([n_new, i]), modulu)
count = (count + count_i) % modulu
piles_look_up_modular[(n, i)] = count
# for n itself
count = (count + 1) % modulu
piles_look_up_modular[(n, n)] = count
return count
@lru_cache(maxsize=1000000)
def count_piles(n, max_size):
if max_size == 0 or max_size == 1:
return 1
if n == 0 or n == 1:
return 1
count = 0
for k in range(1, max_size + 1):
n_new = n - k
max_size_new = min([k, n_new])
count += count_piles(n_new, max_size_new)
return count
"""
I tried to implement my own algorithm but I would run out of memory.
I tried to find a pattern in how the count can be calculated directly,
but I could not find a pattern. I then looked up partioning and
implemented the algorithm explained here [1]. This was literally the first
time in my life that I have learned about generator functions. Once I
used this algorithm it was easy. I definitely want to learn more about
generator functions.
[1] https://www.coursera.org/lecture/enumerative-combinatorics/computing-the-number-of-partitions-via-the-pentagonal-theorem-CehOM
"""
def sign(n):
if n % 2 == 0:
return -1
return 1
@lru_cache(maxsize=1000000)
def euler_identity(n):
r = (3 * n * n - n) // 2
return r
@lru_cache(maxsize=1000000)
def p(n):
"""
"""
if n == 0:
return 1
if n == 1:
return 1
m = 1000000
r = 0
for i in range(1, n):
s = sign(i)
e = euler_identity(i)
new_n = n - e
if new_n < 0:
break
if m:
r = (r + s * p(new_n)) % m
else:
r = r + s * p(new_n)
e = euler_identity(-i)
new_n = n - e
if new_n < 0:
break
if m:
r = (r + s * p(new_n)) % m
else:
r = r + s * p(new_n)
return r
for n in range(1, 100000):
a = p(n)
if a == 0:
return n
break
if __name__ == "__main__":
print("e078.py: " + str(euler_078()))
assert(euler_078() == 0)
assert(euler_078() == 55374)

View File

@ -1,8 +1,94 @@
def verify(passcode, rule):
"""
Passcode is a string of numbers. Rule is two character string "ab". Verify
returns False if "a" occurs and never comes before "b" at some point in
the passcode and True otherwise.
"""
a, b = rule
if a == b:
return True
a_found = False
b_found = False
result = True
for c in passcode:
if a == c:
a_found = True
if b == c:
b_found = True
if b_found and c == a:
result = False
if a_found and c == b:
return True
return result
def verify_all(passcode, rules):
for rule in rules:
if not verify(passcode, rule):
return False
return True
def tests():
passcode = "abcded"
assert(verify(passcode, "ab"))
assert(verify(passcode, "cz"))
assert(verify(passcode, "zc"))
assert(verify(passcode, "bb"))
assert(verify(passcode, "ed"))
assert(verify(passcode, "fg"))
assert(verify(passcode, "ac"))
assert(verify(passcode, "de"))
assert(verify(passcode, "ca") is False)
assert(verify(passcode, "dc") is False)
def get_rules(passcodes):
rules = []
for p in passcodes:
for i in range(len(p) - 1):
rules.append(p[i:i + 2])
return rules
def get_digits(passcodes):
r = []
for p in passcodes:
for d in p:
if d not in r:
r.append(d)
return r
def add_single_digit(code, digit):
# print("add_single_digit({}, {})".format(code, digit))
r = []
for i in range(len(code) + 1):
new_code = code[:i] + str(digit) + code[i:]
r.append(new_code)
return r
def euler_079():
return 0
tests()
with open("../txt/EulerProblem079.txt", "r") as f:
passcodes = sorted(list(set([line.strip() for line in f])))
codes = [""]
rules = get_rules(passcodes)
for d in get_digits(passcodes):
temp_codes = []
for code in codes:
if d not in code:
for new_code in add_single_digit(code, d):
if verify_all(new_code, rules):
temp_codes.append(new_code)
codes = temp_codes
return int(codes[0])
if __name__ == "__main__":
print("e079.py: " + str(euler_079()))
assert(euler_079() == 0)
assert(euler_079() == 73162890)

50
txt/EulerProblem079.txt Normal file
View File

@ -0,0 +1,50 @@
319
680
180
690
129
620
762
689
762
318
368
710
720
710
629
168
160
689
716
731
736
729
316
729
729
710
769
290
719
680
318
389
162
289
162
718
729
319
790
680
890
362
319
760
316
729
380
319
728
716