project-euler/315_digital_clock_roots.py

59 lines
1.3 KiB
Python

#!/usr/bin/env python3
from lib import primegen
from itertools import product
segments = {"th" : (0,1), "mh" : (1,1),
"bh" : (2,1), "tl" : (1,0),
"bl" : (2,0), "tr" : (1,2),
"br" : (2,2)
}
def rootdiff(n):
chain = list(rootchain(n))
return sum(transdiff(n1, n2)
for n1, n2 in zip(chain, chain[1:]))
def rootchain(n):
n = str(n)
while len(n) > 1:
yield n
n = str(sum(map(int, n)))
yield n
def transdiff(n1, n2):
return sum(cache[(d1, d2)]
for d1, d2 in zip(n1[::-1], n2[::-1]))
def init_cache(digs):
return {(d1, d2) : 2 * len(digs[d1] & digs[d2])
for d1, d2 in product(digs, repeat=2)
}
def parsenum(text):
return set(s for s, (rw, cl) in segments.items()
if str(text[rw] + 3*' ')[cl] != ' '
)
def parse(fname):
with open(fname) as f:
r = f.read().split('\n')
for n in range(10):
yield str(n), parsenum(r[3*n : 3*n+3])
def main(A, B):
s = 0
gen = primegen(B)
for p in gen:
if p > A: break
s = rootdiff(p)
for p in gen:
s += rootdiff(p)
return s
digs = {d : segs for d, segs in parse("data/digs.txt")}
digs[' '] = set()
cache = init_cache(digs)
print(main(10**7, 2*10**7))