-
Notifications
You must be signed in to change notification settings - Fork 0
/
d08.py
94 lines (67 loc) · 2.31 KB
/
d08.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from itertools import cycle
from math import lcm
print('Day 8 of Advent of Code!')
START = 'AAA'
END = 'ZZZ'
DIRS = {'L': 0, 'R': 1}
def get_nodes_and_instructions(data):
instruction_data, node_data = data.split('\n\n')
instructions = cycle(instruction_data)
nodes = {}
for node in node_data.splitlines():
node_id, node_targets = node.split(' = ')
node_targets = node_targets[1:-1].split(', ')
nodes[node_id] = node_targets
return instructions, nodes
def is_start(node):
return node[-1] == 'A'
def is_end(node):
return node[-1] == 'Z'
def is_finish(nodes):
return all((is_end(node) for node in nodes))
def find_steps_human(instructions, nodes):
current = START
steps = 0
while current != END:
current = nodes[current][DIRS[next(instructions)]]
steps += 1
return steps
def find_one_cycle(instructions, node, nodes):
steps = 0
current = node
while not is_end(current):
current = nodes[current][DIRS[next(instructions)]]
steps += 1
return steps
def find_steps_ghost(instructions, start_nodes, nodes):
return lcm(*[find_one_cycle(instructions, node, nodes) for node in start_nodes])
TEST_DATA = '''RL
AAA = (BBB, CCC)
BBB = (DDD, EEE)
CCC = (ZZZ, GGG)
DDD = (DDD, DDD)
EEE = (EEE, EEE)
GGG = (GGG, GGG)
ZZZ = (ZZZ, ZZZ)'''
TEST_DATA2 = '''LR
11A = (11B, XXX)
11B = (XXX, 11Z)
11Z = (11B, XXX)
22A = (22B, XXX)
22B = (22C, 22C)
22C = (22Z, 22Z)
22Z = (22B, 22B)
XXX = (XXX, XXX)'''
print('Testing...')
parsed_instructions, parsed_nodes = get_nodes_and_instructions(TEST_DATA)
print('Part 1:', find_steps_human(*get_nodes_and_instructions(TEST_DATA)) == 2)
parsed_instructions, parsed_nodes = get_nodes_and_instructions(TEST_DATA2)
starting_nodes = [node for node in parsed_nodes if is_start(node)]
print('Part 2:', find_steps_ghost(parsed_instructions, starting_nodes, parsed_nodes) == 6)
with open('inp', mode='r', encoding='utf-8') as inp:
print('Solution...')
actual_data = inp.read()
print('Part 1:', find_steps_human(*get_nodes_and_instructions(actual_data)))
parsed_instructions, parsed_nodes = get_nodes_and_instructions(actual_data)
starting_nodes = [node for node in parsed_nodes if is_start(node)]
print('Part 2:', find_steps_ghost(parsed_instructions, starting_nodes, parsed_nodes))