Skip to content

Commit a981770

Browse files
committed
Added v2 of 2021-20
1 parent 3420f26 commit a981770

File tree

2 files changed

+193
-78
lines changed

2 files changed

+193
-78
lines changed

2021/20-Trench Map.py

Lines changed: 17 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -70,100 +70,39 @@ def words(s: str):
7070

7171
# -------------------------------- Actual code execution ----------------------------- #
7272

73-
dot.Dot.all_directions = directions_diagonals
7473
all_directions = directions_diagonals
75-
dot.Dot.allowed_direction_map = {
76-
".": {dir: all_directions for dir in all_directions},
77-
"#": {dir: all_directions for dir in all_directions},
78-
}
79-
dot.Dot.terrain_map = {
80-
".": [True, False],
81-
"#": [True, False],
82-
"X": [True, False],
83-
}
84-
85-
86-
def get_neighbors(self):
87-
if self.neighbors_obsolete:
88-
self.neighbors = {}
89-
for direction in self.allowed_directions:
90-
if (self + direction) and (self + direction).is_walkable:
91-
self.neighbors[self + direction] = 1
92-
else:
93-
new_dot = self.__class__(self.grid, self.position + direction, ".")
94-
self.grid.dots[self.position + direction] = new_dot
95-
self.neighbors[self + direction] = 1
96-
97-
self.neighbors_obsolete = False
98-
return self.neighbors
99-
100-
101-
dot.Dot.get_neighbors = get_neighbors
10274

103-
grid.Grid.all_directions = directions_diagonals
104-
105-
dot.Dot.sort_value = dot.Dot.sorting_map["reading"]
10675

10776
if part_to_test == 1:
10877
generations = 2
10978
else:
11079
generations = 50
11180

112-
81+
# Parsing algorithm
11382
algorithm = puzzle_input.split("\n")[0]
11483

115-
image = grid.Grid()
116-
image.all_directions = directions_diagonals
117-
image.text_to_dots("\n".join(puzzle_input.split("\n")[2:]))
118-
119-
# print (image.dots_to_text())
84+
rules = {}
85+
for i in range(2 ** 9):
86+
binary = "{0:>09b}".format(i)
87+
text = binary.replace("0", ".").replace("1", "#")
88+
rules[text] = algorithm[i]
12089

121-
for i in range(generations + 5):
122-
dots = image.dots.copy()
123-
[image.dots[x].get_neighbors() for x in dots]
90+
image = grid.GameOfLife(True)
91+
image.set_rules(rules)
92+
image.text_to_dots("\n".join(puzzle_input.split("\n")[2:]))
12493

94+
# Add some margin to make it 'infinite'
95+
image.extend_grid(2)
12596

12697
for i in range(generations):
127-
# print ('Generation', i)
128-
new_image = grid.Grid()
129-
new_image.dots = {
130-
x: dot.Dot(new_image, image.dots[x].position, image.dots[x].terrain)
131-
for x in image.dots
132-
}
133-
new_image.all_directions = directions_diagonals
134-
135-
for x in image.dots.copy():
136-
neighbors = [neighbor for neighbor in image.dots[x].get_neighbors()] + [
137-
image.dots[x]
138-
]
139-
text = "".join([neighbor.terrain for neighbor in sorted(neighbors)])
140-
binary = int(text.replace(".", "0").replace("#", "1"), 2)
141-
new_image.dots[x].set_terrain(algorithm[binary])
142-
# print (new_image.dots_to_text())
143-
144-
# Empty borders so they're not counted later
145-
# They use surrounding data (out of image) that default to . and this messes up the rest
146-
# This is done only for odd generations because that's enough (all non-borders get blanked out due to the "." at the end of the algorithm)
98+
image.evolve(1)
14799
if i % 2 == 1:
148-
borders, _ = new_image.get_borders()
149-
borders = functools.reduce(lambda a, b: a + b, borders)
150-
[dot.set_terrain(".") for dot in borders]
151-
152-
image.dots = {
153-
x: dot.Dot(image, new_image.dots[x].position, new_image.dots[x].terrain)
154-
for x in new_image.dots
155-
}
156-
157-
# print ('Lit dots', sum([1 for dot in image.dots if image.dots[dot].terrain == '#']))
158-
159-
# Remove the borders that were added (they shouldn't count because they take into account elements outside the image)
160-
borders, _ = image.get_borders()
161-
borders = functools.reduce(lambda a, b: a + b, borders)
162-
image.dots = {
163-
dot: image.dots[dot] for dot in image.dots if image.dots[dot] not in borders
164-
}
100+
image.reduce_grid(2)
101+
image.extend_grid(2)
102+
103+
image.reduce_grid(2)
165104

166-
puzzle_actual_result = sum([1 for dot in image.dots if image.dots[dot].terrain == "#"])
105+
puzzle_actual_result = image.dots_to_text().count("#")
167106

168107

169108
# -------------------------------- Outputs / results --------------------------------- #

2021/20-Trench Map.v1.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# -------------------------------- Input data ---------------------------------------- #
2+
import os, grid, graph, dot, assembly, re, itertools, copy, functools
3+
from collections import Counter, deque, defaultdict
4+
5+
from compass import *
6+
7+
8+
# This functions come from https://github.com/mcpower/adventofcode - Thanks!
9+
def lmap(func, *iterables):
10+
return list(map(func, *iterables))
11+
12+
13+
def ints(s: str):
14+
return lmap(int, re.findall(r"-?\d+", s)) # thanks mserrano!
15+
16+
17+
def positive_ints(s: str):
18+
return lmap(int, re.findall(r"\d+", s)) # thanks mserrano!
19+
20+
21+
def floats(s: str):
22+
return lmap(float, re.findall(r"-?\d+(?:\.\d+)?", s))
23+
24+
25+
def positive_floats(s: str):
26+
return lmap(float, re.findall(r"\d+(?:\.\d+)?", s))
27+
28+
29+
def words(s: str):
30+
return re.findall(r"[a-zA-Z]+", s)
31+
32+
33+
test_data = {}
34+
35+
test = 1
36+
test_data[test] = {
37+
"input": """..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
38+
39+
#..#.
40+
#....
41+
##..#
42+
..#..
43+
..###""",
44+
"expected": ["35", "Unknown"],
45+
}
46+
47+
test = "real"
48+
input_file = os.path.join(
49+
os.path.dirname(__file__),
50+
"Inputs",
51+
os.path.basename(__file__).replace(".py", ".txt"),
52+
)
53+
test_data[test] = {
54+
"input": open(input_file, "r+").read(),
55+
"expected": ["5044", "18074"],
56+
}
57+
58+
59+
# -------------------------------- Control program execution ------------------------- #
60+
61+
case_to_test = "real"
62+
part_to_test = 2
63+
64+
# -------------------------------- Initialize some variables ------------------------- #
65+
66+
puzzle_input = test_data[case_to_test]["input"]
67+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
68+
puzzle_actual_result = "Unknown"
69+
70+
71+
# -------------------------------- Actual code execution ----------------------------- #
72+
73+
dot.Dot.all_directions = directions_diagonals
74+
all_directions = directions_diagonals
75+
dot.Dot.allowed_direction_map = {
76+
".": {dir: all_directions for dir in all_directions},
77+
"#": {dir: all_directions for dir in all_directions},
78+
}
79+
dot.Dot.terrain_map = {
80+
".": [True, False],
81+
"#": [True, False],
82+
"X": [True, False],
83+
}
84+
85+
86+
def get_neighbors(self):
87+
if self.neighbors_obsolete:
88+
self.neighbors = {}
89+
for direction in self.allowed_directions:
90+
if (self + direction) and (self + direction).is_walkable:
91+
self.neighbors[self + direction] = 1
92+
else:
93+
new_dot = self.__class__(self.grid, self.position + direction, ".")
94+
self.grid.dots[self.position + direction] = new_dot
95+
self.neighbors[self + direction] = 1
96+
97+
self.neighbors_obsolete = False
98+
return self.neighbors
99+
100+
101+
dot.Dot.get_neighbors = get_neighbors
102+
103+
grid.Grid.all_directions = directions_diagonals
104+
105+
dot.Dot.sort_value = dot.Dot.sorting_map["reading"]
106+
107+
if part_to_test == 1:
108+
generations = 2
109+
else:
110+
generations = 50
111+
112+
113+
algorithm = puzzle_input.split("\n")[0]
114+
115+
image = grid.Grid()
116+
image.all_directions = directions_diagonals
117+
image.text_to_dots("\n".join(puzzle_input.split("\n")[2:]))
118+
119+
# print (image.dots_to_text())
120+
121+
for i in range(generations + 5):
122+
dots = image.dots.copy()
123+
[image.dots[x].get_neighbors() for x in dots]
124+
125+
126+
for i in range(generations):
127+
# print ('Generation', i)
128+
new_image = grid.Grid()
129+
new_image.dots = {
130+
x: dot.Dot(new_image, image.dots[x].position, image.dots[x].terrain)
131+
for x in image.dots
132+
}
133+
new_image.all_directions = directions_diagonals
134+
135+
for x in image.dots.copy():
136+
neighbors = [neighbor for neighbor in image.dots[x].get_neighbors()] + [
137+
image.dots[x]
138+
]
139+
text = "".join([neighbor.terrain for neighbor in sorted(neighbors)])
140+
binary = int(text.replace(".", "0").replace("#", "1"), 2)
141+
new_image.dots[x].set_terrain(algorithm[binary])
142+
# print (new_image.dots_to_text())
143+
144+
# Empty borders so they're not counted later
145+
# They use surrounding data (out of image) that default to . and this messes up the rest
146+
# This is done only for odd generations because that's enough (all non-borders get blanked out due to the "." at the end of the algorithm)
147+
if i % 2 == 1:
148+
borders, _ = new_image.get_borders()
149+
borders = functools.reduce(lambda a, b: a + b, borders)
150+
[dot.set_terrain(".") for dot in borders]
151+
152+
image.dots = {
153+
x: dot.Dot(image, new_image.dots[x].position, new_image.dots[x].terrain)
154+
for x in new_image.dots
155+
}
156+
157+
# print ('Lit dots', sum([1 for dot in image.dots if image.dots[dot].terrain == '#']))
158+
159+
# Remove the borders that were added (they shouldn't count because they take into account elements outside the image)
160+
borders, _ = image.get_borders()
161+
borders = functools.reduce(lambda a, b: a + b, borders)
162+
image.dots = {
163+
dot: image.dots[dot] for dot in image.dots if image.dots[dot] not in borders
164+
}
165+
166+
puzzle_actual_result = sum([1 for dot in image.dots if image.dots[dot].terrain == "#"])
167+
168+
169+
# -------------------------------- Outputs / results --------------------------------- #
170+
171+
print("Case :", case_to_test, "- Part", part_to_test)
172+
print("Expected result : " + str(puzzle_expected_result))
173+
print("Actual result : " + str(puzzle_actual_result))
174+
# Date created: 2021-12-20 08:30:35.363096
175+
# Part 1: 2021-12-20 10:19:36
176+
# Part 2: 2021-12-20 10:35:25

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy