#!/usr/bin/env python3
import sys, math
from itertools import product
DIR = {
('A', '>'): ['vA'],
('A', '^'): ['', '>'): ['A'],
('^', 'A'): ['>A'],
('^', '>'): ['v>A', '>vA'],
('^', 'v'): ['vA'],
('^', '<'): ['v>^A'],
('<', '^'): ['>^A'],
('<', 'v'): ['>A'],
('<', '>'): ['>>A'],
('v', 'A'): ['>^A', '^>A'],
('v', '^'): ['^A'],
('v', '<'): [''): ['>A'],
('>', 'A'): ['^A'],
('>', '<'): ['<', '^'): ['<^A', '^', 'v'): ['': (0,1), '<': (0,-1)}
dy = e[0]-s[0]
dx = e[1]-s[1]
opt = ['^'] * dy + ['v'] * -dy + ['<'] * -dx + ['>'] * dx
for o in [tuple(opt), tuple(reversed(opt))]:
s, e = pad[start], pad[end]
gap = False
for step in list(o):
s = s[0] + d[step][0], s[1] + d[step][1]
if s == (0,0): gap = True
if not gap: yield ''.join(o+('A',))
def numeric(code):
strings = ['']
prev = 'A'
for key in list(code):
strings = [s1+s2 for (s1,s2) in product(strings,[opt for opt in options(prev, key, NUM)])]
prev = key
return strings
# reddit solution... (prevKey is 'A' the first time)
def buildSeq(keys, index, prevKey, currPath, result):
if index == len(keys):
result.append(currPath)
return
for path in DIR[(prevKey,keys[index])]:
buildSeq(keys, index+1, keys[index], currPath + path, result)
@memo
def shortestSeq(keys, depth):
if depth == 0: return len(keys)
total = 0
subKeys = keys.split('A')
for subKey in subKeys[:-1]:
seqs = []
buildSeq(subKey+'A', 0, 'A', '', seqs)
minimum = min([shortestSeq(seq, depth-1) for seq in seqs])
total += minimum
return total
if __name__ == '__main__':
codes = [line.strip('\n') for line in open(sys.argv[1])]
res1, res2 = 0, 0
for code in codes:
dirs = set(numeric(code))
l1, l2 = math.inf, math.inf
for d in dirs: l1 = min(shortestSeq(d,2), l1)
res1 += l1 * int(code[:-1])
for d in dirs: l2 = min(shortestSeq(d,25), l2)
res2 += l2 * int(code[:-1])
# challenge 1
print(f"challenge 1:\n{res1}\n")
# challenge 2
print(f"challenge 2:\n{res2}")