My Advent of Code solutions in Python. kevinyap.ca/2019/12/going-fast-in-advent-of-code/
advent-of-code python
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update 2016/day15.py

Add numerical solution using Chinese remainder theorem.

+32 -3
+32 -3
2016/day15.py
··· 1 1 import re 2 2 import fileinput 3 - from utils import parse_line 3 + from utils import parse_line, mul 4 4 5 5 6 6 def button_timing(discs): ··· 20 20 21 21 i += stride 22 22 23 + # https://stackoverflow.com/a/9758173/239076 24 + def egcd(a, b): 25 + if a == 0: 26 + return (b, 0, 1) 27 + else: 28 + g, y, x = egcd(b % a, a) 29 + return (g, x - (b // a) * y, y) 30 + 31 + def modinv(a, m): 32 + g, x, y = egcd(a, m) 33 + if g != 1: 34 + raise Exception('modular inverse does not exist') 35 + else: 36 + return x % m 37 + 38 + def chinese_remainder_theorem(discs): 39 + M = mul(d[0] for d in discs) 40 + x = 0 41 + 42 + for i, (size, initial) in enumerate(discs, start=1): 43 + # Disc #2 has 17 positions; at time=0, it is at position 15. 44 + # => x \equiv (17 - 15 - 2) (mod 17) 45 + M_i = (M / size) 46 + x += (size - initial - i) * M_i * modinv(M_i, size) 47 + 48 + return x 49 + 23 50 24 51 DISCS = [] 25 52 DISC_RE = re.compile(r'Disc #\d+ has (\d+) positions; at time=0, it is at position (\d+).') ··· 28 55 disc = parse_line(DISC_RE, line.strip()) 29 56 DISCS.append(disc) 30 57 31 - print "Timing to press button:", button_timing(DISCS) 32 - print "Timing with added disc:", button_timing(DISCS + [[11, 0]]) 58 + # print "Timing to press button:", button_timing(DISCS) 59 + # print "Timing with added disc:", button_timing(DISCS + [[11, 0]]) 60 + print "Timing to press button:", chinese_remainder_theorem(DISCS) 61 + print "Timing with added disc:", chinese_remainder_theorem(DISCS + [[11, 0]])