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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# -*- coding: utf-8 -*-
import re
from abc import ABC
from typing import Iterator, Any, TypedDict, Tuple, List
from queue import LifoQueue
from aoc import BaseAssignment
move_regex = re.compile("^move (?P<amount>\d+) from (?P<start>\d+) to (?P<end>\d+)$")
class Move(TypedDict):
amount: int
start: int
end: int
class Assignment(BaseAssignment, ABC):
def parse_move(self, move: str) -> Move:
match = move_regex.match(move)
if match:
move = match.groupdict()
return Move(
amount=int(move["amount"]),
start=int(move["start"]),
end=int(move["end"]),
)
def parse_stacks(self, string_stacks: List[str]) -> List[LifoQueue]:
stacks = []
columns = string_stacks.pop().replace(" ", "")
for i in range(len(columns)):
stacks.append(LifoQueue())
for line in reversed(string_stacks):
for index, stack in enumerate(stacks):
item_index = (index * 4) + 1
try:
item = line[item_index]
if item != " ":
stack.put(item)
except IndexError:
pass
return stacks
def parse_input(self, input: Iterator) -> Tuple[List[LifoQueue], List[Move]]:
parsing_stacks = True
tmp_stacks = []
stacks = []
moves = []
for line in input:
if line == "":
parsing_stacks = False
stacks = self.parse_stacks(tmp_stacks)
continue
if parsing_stacks:
tmp_stacks.append(line)
else:
moves.append(self.parse_move(line))
return stacks, moves
def execute_moves(self, stacks: List[LifoQueue], moves: List[Move]):
raise NotImplementedError()
def run(self, input: Iterator) -> Any:
stacks, moves = self.parse_input(input)
self.execute_moves(stacks, moves)
return "".join([stack.get() for stack in stacks])
class AssignmentOne(Assignment):
example_result = "CMZ"
def execute_moves(self, stacks: List[LifoQueue], moves: List[Move]):
for move in moves:
start = stacks[move["start"] - 1]
end = stacks[move["end"] - 1]
for _ in range(move["amount"]):
end.put(start.get())
return stacks
class AssignmentTwo(Assignment):
example_result = "MCD"
def execute_moves(self, stacks: List[LifoQueue], moves: List[Move]):
for move in moves:
start = stacks[move["start"] - 1]
end = stacks[move["end"] - 1]
tmp_stack = LifoQueue()
for _ in range(move["amount"]):
tmp_stack.put(start.get())
while not tmp_stack.empty():
end.put(tmp_stack.get())
return stacks
|