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))
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)