Skip to content

Commit 9418a5a

Browse files
committed
Added solutions for day 17
1 parent 810df13 commit 9418a5a

File tree

3 files changed

+142
-1
lines changed

3 files changed

+142
-1
lines changed

advent2020/day17.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2021 Andrew Krepps
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
24+
from . import util
25+
26+
27+
def parse_initial_state(lines):
28+
initial_state = set()
29+
max_dim = 0
30+
for y, line in enumerate(lines):
31+
max_dim = max(max_dim, y + 1)
32+
for x, c in enumerate(line.strip()):
33+
max_dim = max(max_dim, x + 1)
34+
if c == '#':
35+
initial_state.add((x, y, 0, 0))
36+
return initial_state, max_dim
37+
38+
39+
def count_active_neighbors(x, y, z, w, current_state):
40+
count = 0
41+
for test_x in range(x - 1, x + 2):
42+
for test_y in range(y - 1, y + 2):
43+
for test_z in range(z - 1, z + 2):
44+
for test_w in range(w - 1, w + 2):
45+
if (test_x != x or test_y != y or test_z != z or test_w != w) \
46+
and (test_x, test_y, test_z, test_w) in current_state:
47+
count += 1
48+
# stop early if count is above rule thresholds
49+
if count > 3:
50+
return count
51+
return count
52+
53+
54+
def cube_will_be_active(x, y, z, w, current_state):
55+
active_neighbors = count_active_neighbors(x, y, z, w, current_state)
56+
return active_neighbors == 3 or (active_neighbors == 2 and (x, y, z, w) in current_state)
57+
58+
59+
def do_simulation_step(current_state, dim_size, w_size):
60+
next_state = set()
61+
xyz_range = range(-dim_size + 1, dim_size)
62+
for x in xyz_range:
63+
for y in xyz_range:
64+
for z in xyz_range:
65+
for w in range(-w_size + 1, w_size):
66+
if cube_will_be_active(x, y, z, w, current_state):
67+
next_state.add((x, y, z, w))
68+
return next_state
69+
70+
71+
def run_simulation(initial_state, max_dim, num_steps, max_w=-1):
72+
state = initial_state
73+
for step in range(num_steps):
74+
dim_size = max_dim + step + 1
75+
if max_w < 0:
76+
w_size = dim_size
77+
else:
78+
w_size = max_w
79+
state = do_simulation_step(state, max_dim + step + 1, w_size)
80+
return state
81+
82+
83+
def get_part1_answer(initial_state, max_dim):
84+
return len(run_simulation(initial_state, max_dim, 6, max_w=1))
85+
86+
87+
def get_part2_answer(initial_state, max_dim):
88+
return len(run_simulation(initial_state, max_dim, 6))
89+
90+
91+
def run():
92+
lines = util.get_input_file_lines("day17.txt")
93+
initial_state, max_dim = parse_initial_state(lines)
94+
print(f"The answer to part 1 is {get_part1_answer(initial_state, max_dim)}")
95+
print(f"The answer to part 2 is {get_part2_answer(initial_state, max_dim)}")

main.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from advent2020 import day14
4040
from advent2020 import day15
4141
from advent2020 import day16
42+
from advent2020 import day17
4243

4344

4445
day_runners = [
@@ -57,7 +58,8 @@
5758
lambda: day13.run(),
5859
lambda: day14.run(),
5960
lambda: day15.run(),
60-
lambda: day16.run()
61+
lambda: day16.run(),
62+
lambda: day17.run()
6163
]
6264

6365

test/test_day17.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2021 Andrew Krepps
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
24+
import unittest
25+
26+
from advent2020.day17 import get_part1_answer
27+
from advent2020.day17 import get_part2_answer
28+
from advent2020.day17 import parse_initial_state
29+
from advent2020.util import get_input_data_lines
30+
31+
32+
data = """
33+
.#.
34+
..#
35+
###
36+
"""
37+
38+
39+
class Day17Test(unittest.TestCase):
40+
def test_day17(self):
41+
lines = get_input_data_lines(data)
42+
initial_state, max_dim = parse_initial_state(lines)
43+
self.assertEqual(get_part1_answer(initial_state, max_dim), 112)
44+
self.assertEqual(get_part2_answer(initial_state, max_dim), 848)

0 commit comments

Comments
 (0)