Skip to content

Commit 804e989

Browse files
committed
Added days 2018-17, 2018-18 and 2018-19
1 parent 7b91f98 commit 804e989

File tree

3 files changed

+552
-0
lines changed

3 files changed

+552
-0
lines changed

2018/17-Reservoir Research.py

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# -------------------------------- Input data ---------------------------------------- #
2+
import os
3+
4+
test_data = {}
5+
6+
test = 1
7+
test_data[test] = {
8+
"input": """x=495, y=2..7
9+
y=7, x=495..501
10+
x=501, y=3..7
11+
x=498, y=2..4
12+
x=506, y=1..2
13+
x=498, y=10..13
14+
x=504, y=10..13
15+
y=13, x=498..504""",
16+
"expected": ["Unknown", "Unknown"],
17+
}
18+
19+
test += 1
20+
test_data[test] = {
21+
"input": """x=496, y=2..8
22+
x=499, y=3..5
23+
x=501, y=3..5
24+
y=5, x=499..501
25+
x=505, y=2..8""",
26+
"expected": ["Unknown", "Unknown"],
27+
}
28+
29+
test += 1
30+
test_data[test] = {
31+
"input": """x=491, y=2..8
32+
x=497, y=4..8
33+
x=504, y=3..8
34+
y=8, x=497..504
35+
x=508, y=2..8""",
36+
"expected": ["Unknown", "Unknown"],
37+
}
38+
39+
test = "real"
40+
input_file = os.path.join(
41+
os.path.dirname(__file__),
42+
"Inputs",
43+
os.path.basename(__file__).replace(".py", ".txt"),
44+
)
45+
test_data[test] = {
46+
"input": open(input_file, "r+").read().strip(),
47+
"expected": ["39877", "33291"],
48+
}
49+
50+
# -------------------------------- Control program execution ------------------------- #
51+
52+
case_to_test = "real"
53+
part_to_test = 2
54+
55+
# -------------------------------- Initialize some variables ------------------------- #
56+
57+
puzzle_input = test_data[case_to_test]["input"]
58+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
59+
puzzle_actual_result = "Unknown"
60+
61+
62+
# -------------------------------- Actual code execution ----------------------------- #
63+
64+
65+
walls = []
66+
min_y, max_y = 0, -(10 ** 6)
67+
min_x, max_x = 500, 500
68+
69+
for string in puzzle_input.split("\n"):
70+
a, b = string.split(", ")
71+
dim1, val1 = a.split("=")
72+
val1 = int(val1)
73+
74+
dim2, val2 = b.split("=")
75+
val2 = val2.split("..")
76+
val2, val3 = int(val2[0]), int(val2[1])
77+
78+
if dim1 == "x":
79+
min_y = min(min_y, -val3)
80+
max_y = max(max_y, -val2)
81+
min_x = min(min_x, val1)
82+
max_x = max(max_x, val1)
83+
else:
84+
min_y = min(min_y, -val1)
85+
max_y = max(max_y, -val1)
86+
min_x = min(min_x, val2)
87+
max_x = max(max_x, val3)
88+
89+
for spot in range(val2, val3 + 1):
90+
if dim1 == "x":
91+
dot = val1 - spot * 1j
92+
else:
93+
dot = spot - val1 * 1j
94+
walls.append(dot)
95+
96+
walls = set(walls)
97+
98+
current_position = 500
99+
wet_positions = set()
100+
pools = set()
101+
flowing = [current_position]
102+
settled = set()
103+
104+
i = 0
105+
while flowing:
106+
current_position = flowing.pop()
107+
# print ('--------------')
108+
# print ('now', current_position, current_position - 1j not in walls, current_position - 1j not in pools)
109+
# print ('pools', pools)
110+
111+
if current_position.imag <= min_y:
112+
settled.add(current_position)
113+
position = current_position + 1j
114+
115+
while position in flowing:
116+
settled.add(position)
117+
flowing.remove(position)
118+
position += 1j
119+
continue
120+
121+
if current_position - 1j in settled:
122+
settled.add(current_position)
123+
continue
124+
if current_position - 1j not in walls and current_position - 1j not in pools:
125+
flowing.append(current_position)
126+
flowing.append(current_position - 1j)
127+
current_position -= 1j
128+
if current_position.imag >= min_y and current_position.imag <= max_y:
129+
wet_positions.add(current_position)
130+
else:
131+
132+
pooling = True
133+
settling = False
134+
pool = set([current_position])
135+
# fill horizontally
136+
137+
for direction in [-1, 1]:
138+
position = current_position
139+
while True:
140+
# Extend to the right
141+
position += direction
142+
if position in walls:
143+
break
144+
elif position in settled:
145+
settling = True
146+
break
147+
else:
148+
wet_positions.add(position)
149+
pool.add(position)
150+
if position - 1j not in walls and position - 1j not in pools:
151+
pooling = False
152+
flowing.append(position)
153+
break
154+
155+
if settling:
156+
settled = settled.union(pool)
157+
elif pooling:
158+
pools = pools.union(pool)
159+
160+
# print ('pools', pools)
161+
# print ('flowing', flowing)
162+
163+
# This limit is totally arbitrary
164+
if i == 10 ** 4:
165+
print("stop")
166+
break
167+
i += 1
168+
169+
print("step", i)
170+
for y in range(max_y + 1, min_y - 1, -1):
171+
for x in range(min_x - 2, max_x + 3):
172+
if x + y * 1j in pools:
173+
print("~", end="")
174+
elif x + y * 1j in settled:
175+
print("S", end="")
176+
elif x + y * 1j in flowing:
177+
print("F", end="")
178+
elif x + y * 1j in pools:
179+
print("~", end="")
180+
elif x + y * 1j in wet_positions:
181+
print("|", end="")
182+
elif x + y * 1j in walls:
183+
print("#", end="")
184+
else:
185+
print(".", end="")
186+
print("")
187+
188+
189+
if part_to_test == 1:
190+
puzzle_actual_result = len(wet_positions)
191+
else:
192+
puzzle_actual_result = len(pools)
193+
# 33556 too high
194+
195+
196+
# -------------------------------- Outputs / results --------------------------------- #
197+
198+
print("Expected result : " + str(puzzle_expected_result))
199+
print("Actual result : " + str(puzzle_actual_result))

2018/18-Settlers of The North Pole.py

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# -------------------------------- Input data ---------------------------------------- #
2+
import os, drawing
3+
from complex_utils import *
4+
5+
test_data = {}
6+
7+
test = 1
8+
test_data[test] = {
9+
"input": """.#.#...|#.
10+
.....#|##|
11+
.|..|...#.
12+
..|#.....#
13+
#.#|||#|#|
14+
...#.||...
15+
.|....|...
16+
||...#|.#|
17+
|.||||..|.
18+
...#.|..|.""",
19+
"expected": ["1147", "Unknown"],
20+
}
21+
22+
test = "real"
23+
input_file = os.path.join(
24+
os.path.dirname(__file__),
25+
"Inputs",
26+
os.path.basename(__file__).replace(".py", ".txt"),
27+
)
28+
test_data[test] = {
29+
"input": open(input_file, "r+").read().strip(),
30+
"expected": ["483840", "219919"],
31+
}
32+
33+
# -------------------------------- Control program execution ------------------------- #
34+
35+
case_to_test = "real"
36+
part_to_test = 2
37+
verbose_level = 2
38+
39+
# -------------------------------- Initialize some variables ------------------------- #
40+
41+
puzzle_input = test_data[case_to_test]["input"]
42+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
43+
puzzle_actual_result = "Unknown"
44+
45+
46+
# -------------------------------- Actual code execution ----------------------------- #
47+
48+
49+
def text_to_grid(text):
50+
"""
51+
Converts a text to a set of coordinates
52+
53+
The text is expected to be separated by newline characters
54+
Each character will have its coordinates as keys
55+
56+
:param string text: The text to convert
57+
:return: The converted grid, its height and width
58+
"""
59+
grid = {}
60+
lines = text.splitlines()
61+
height = len(lines)
62+
width = 0
63+
for y in range(len(lines)):
64+
width = max(width, len(lines[y]))
65+
for x in range(len(lines[y])):
66+
grid[x - 1j * y] = lines[y][x]
67+
68+
return grid
69+
70+
71+
def grid_to_text(grid, blank_character=" "):
72+
"""
73+
Converts the grid to a text format
74+
75+
:param dict grid: The grid to convert, in format (x, y): value
76+
:param string blank_character: What to use for cells with unknown value
77+
:return: The grid in text format
78+
"""
79+
80+
text = ""
81+
82+
min_y, max_y = int(max_imag(grid.keys())), int(min_imag(grid.keys()))
83+
min_x, max_x = int(min_real(grid.keys())), int(max_real(grid.keys()))
84+
85+
for y in range(min_y, max_y + 1, -1):
86+
for x in range(min_x, max_x + 1):
87+
if x + 1j * y in grid:
88+
text += str(grid[x + 1j * y])
89+
else:
90+
text += blank_character
91+
text += os.linesep
92+
text = text[: -len(os.linesep)]
93+
94+
return text
95+
96+
97+
if part_to_test == 1:
98+
end = 10
99+
else:
100+
end = 1000000000
101+
102+
103+
graph = text_to_grid(puzzle_input)
104+
105+
if verbose_level == 3:
106+
print("Initial state")
107+
print(grid_to_text(graph))
108+
109+
i = 1
110+
scores = []
111+
while i <= end:
112+
new_graph = graph.copy()
113+
114+
for space in graph:
115+
neighbors = [
116+
graph[space + direction]
117+
for direction in directions_diagonals
118+
if space + direction in graph
119+
]
120+
if graph[space] == ".":
121+
if len([x for x in neighbors if x == "|"]) >= 3:
122+
new_graph[space] = "|"
123+
elif graph[space] == "|":
124+
if len([x for x in neighbors if x == "#"]) >= 3:
125+
new_graph[space] = "#"
126+
elif graph[space] == "#":
127+
if (
128+
len([x for x in neighbors if x == "#"]) >= 1
129+
and len([x for x in neighbors if x == "|"]) >= 1
130+
):
131+
new_graph[space] = "#"
132+
else:
133+
new_graph[space] = "."
134+
135+
graph = new_graph.copy()
136+
if verbose_level == 3:
137+
print("step", i)
138+
print(grid_to_text(new_graph))
139+
140+
score = len([1 for x in graph if graph[x] == "#"]) * len(
141+
[1 for x in graph if graph[x] == "|"]
142+
)
143+
if i > 800 and i < 10 ** 8 and score in scores:
144+
repeats_every = i - scores.index(score) - 1 - 800
145+
i += (end - i) // repeats_every * repeats_every
146+
print(
147+
"repeats_every",
148+
repeats_every,
149+
"score",
150+
score,
151+
"index",
152+
scores.index(score),
153+
i,
154+
)
155+
156+
if i > 800:
157+
scores.append(score)
158+
print(i, score)
159+
160+
i += 1
161+
162+
puzzle_actual_result = len([1 for x in graph if graph[x] == "#"]) * len(
163+
[1 for x in graph if graph[x] == "|"]
164+
)
165+
166+
# -------------------------------- Outputs / results --------------------------------- #
167+
168+
print("Expected result : " + str(puzzle_expected_result))
169+
print("Actual result : " + str(puzzle_actual_result))

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