-
Notifications
You must be signed in to change notification settings - Fork 0
/
aoc05.py
142 lines (121 loc) · 3.29 KB
/
aoc05.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
########################################################################
# Advent of Code 2022 - solver
#
# Copyright (C) 2022 Antonio Ceballos Roa
########################################################################
def parse_input(input_str):
global stacks
global instructions
parsed_input = input_str.split('\n')
stacks = dict()
instructions = list()
stack_lines = list()
for line in parsed_input:
if line.split(' ')[0] == 'move':
instructions.append(line)
elif line.strip() != '':
stack_lines.append(line)
parse_stack(stack_lines)
def parse_stack(lines):
'''
[D]
[N] [C]
[Z] [M] [P]
1 2 3
0123456789
Stack positions starting at 4n-3, n = 0, 1, ..., 8
'''
n_stacks = int(lines[-1].split()[-1])
for n in range(1, n_stacks+1):
stacks[n] = list()
for line in reversed(lines[0:-1]):
for n in range(1, n_stacks+1):
try:
crate = line[4*n-3]
if crate != ' ':
stacks[n].append(crate)
except IndexError:
break
########################################################################
# Algorithms
########################################################################
def process(instruction, crate_mover):
'''
Instruction:
move 1 from 2 to 1
move <n> from <source> to target>
'''
tokens = instruction.split()
n = int(tokens[1])
source = int(tokens[3])
target = int(tokens[5])
crate_mover(n, source, target)
def crate_mover_9000(n, source, target):
for i in range(n):
crate = pop(stacks[source])
push(stacks[target], crate)
def crate_mover_9001(n, source, target):
heap = list()
for i in range(n):
crate = pop(stacks[source])
heap.append(crate)
for crate in reversed(heap):
push(stacks[target], crate)
def pop(stack):
crate = stack[-1]
del stack[-1]
return crate
def push(stack, crate):
stack.append(crate)
def solve_1(input_str):
parse_input(input_str)
for instruction in instructions:
process(instruction, crate_mover_9000)
tops = ''.join([stack[-1] for stack in stacks.values()])
return tops
def solve_2(input_str):
parse_input(input_str)
for instruction in instructions:
process(instruction, crate_mover_9001)
tops = ''.join([stack[-1] for stack in stacks.values()])
return tops
########################################################################
# Test class
########################################################################
import unittest
class TestAoc(unittest.TestCase):
def setUp(self):
self.tc_1 = [
(
"""
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
""", 'CMZ'),
]
self.tc_2 = [
(
"""
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
""", 'MCD'),
]
def tearDown(self):
pass
def test_solve_1(self):
for t in self.tc_1:
self.assertEqual(solve_1(t[0]), t[1])
def test_solve_2(self):
for t in self.tc_2:
self.assertEqual(solve_2(t[0]), t[1])