1
|
|
|
import pathlib |
2
|
|
|
import re |
3
|
|
|
from typing import cast, List, Tuple |
4
|
|
|
|
5
|
|
|
MOVE_REGEX = re.compile(r'^move (\d+) from (\d+) to (\d+)$') |
6
|
|
|
|
7
|
|
|
|
8
|
|
|
def parse_initial_state(state_lines): |
9
|
|
|
stack_ids = list(map(int, state_lines.pop().split())) |
10
|
|
|
stacks = {i: [] for i in sorted(stack_ids)} |
11
|
|
|
|
12
|
|
|
def split_x(chunk_size): |
13
|
|
|
return [line[i:i + chunk_size] for i in range(0, len(line), chunk_size + 1)] |
14
|
|
|
|
15
|
|
|
for line in reversed(state_lines): |
16
|
|
|
for create, stack in zip(split_x(3), stack_ids): |
17
|
|
|
if create == ' ': |
18
|
|
|
continue |
19
|
|
|
|
20
|
|
|
stacks[stack].append(create) |
21
|
|
|
return stacks |
22
|
|
|
|
23
|
|
|
|
24
|
|
|
def parse_moves(lines) -> List[Tuple[int, int, int]]: |
25
|
|
|
return cast( |
26
|
|
|
List[Tuple[int, int, int]], |
27
|
|
|
[ |
28
|
|
|
tuple(map(int, re.match(MOVE_REGEX, line).groups())) |
29
|
|
|
for line in lines |
30
|
|
|
] |
31
|
|
|
) |
32
|
|
|
|
33
|
|
|
|
34
|
|
|
def parse(lines): |
35
|
|
|
split_idx = lines.index('') |
36
|
|
|
return ( |
37
|
|
|
parse_initial_state(lines[:split_idx]), |
38
|
|
|
parse_moves(lines[split_idx + 1:]) |
39
|
|
|
) |
40
|
|
|
|
41
|
|
|
|
42
|
|
|
def solve(init_state, moves, pick_group): |
43
|
|
|
state = {k: v[:] for k, v in init_state.items()} |
44
|
|
|
|
45
|
|
|
for n, from_, to in moves: |
46
|
|
|
pick = [state[from_].pop() for _ in range(n)] |
47
|
|
|
if pick_group: |
48
|
|
|
pick.reverse() |
49
|
|
|
|
50
|
|
|
state[to].extend(pick) |
51
|
|
|
return state |
52
|
|
|
|
53
|
|
|
|
54
|
|
|
def collect_output(state): |
55
|
|
|
return ''.join(g[-1][1] for g in state.values()) |
56
|
|
|
|
57
|
|
|
|
58
|
|
|
def main(): |
59
|
|
|
content = pathlib.Path('./input.txt').read_text() |
60
|
|
|
initial_state, moves = parse(content.splitlines()) |
61
|
|
|
|
62
|
|
|
print("Part 1:", collect_output(solve(initial_state, moves, False))) |
63
|
|
|
print("Part 2:", collect_output(solve(initial_state, moves, True))) |
64
|
|
|
|
65
|
|
|
|
66
|
|
|
if __name__ == '__main__': |
67
|
|
|
main() |
68
|
|
|
|