Solve 10 and 11.
This commit is contained in:
218
d10.py
Normal file
218
d10.py
Normal file
@@ -0,0 +1,218 @@
|
||||
import lib
|
||||
|
||||
EXAMPLE = """
|
||||
..F7.
|
||||
.FJ|.
|
||||
SJ.L7
|
||||
|F--J
|
||||
LJ...
|
||||
"""
|
||||
|
||||
EXAMPLE2 = """
|
||||
...........
|
||||
.S-------7.
|
||||
.|F-----7|.
|
||||
.||.....||.
|
||||
.||.....||.
|
||||
.|L-7.F-J|.
|
||||
.|..|.|..|.
|
||||
.L--J.L--J.
|
||||
...........
|
||||
"""
|
||||
|
||||
EXAMPLE3 = """
|
||||
..........
|
||||
.S------7.
|
||||
.|F----7|.
|
||||
.||OOOO||.
|
||||
.||OOOO||.
|
||||
.|L-7F-J|.
|
||||
.|II||II|.
|
||||
.L--JL--J.
|
||||
..........
|
||||
"""
|
||||
|
||||
EXAMPLE4 = """
|
||||
FF7FSF7F7F7F7F7F---7
|
||||
L|LJ||||||||||||F--J
|
||||
FL-7LJLJ||||||LJL-77
|
||||
F--JF--7||LJLJIF7FJ-
|
||||
L---JF-JLJIIIIFJLJJ7
|
||||
|F|F-JF---7IIIL7L|7|
|
||||
|FFJF7L7F-JF7IIL---7
|
||||
7-L-JL7||F7|L7F-7F7|
|
||||
L.L7LFJ|||||FJL7||LJ
|
||||
L7JLJL-JLJLJL--JLJ.L
|
||||
"""
|
||||
|
||||
|
||||
# | is a vertical pipe connecting north and south.
|
||||
# - is a horizontal pipe connecting east and west.
|
||||
# L is a 90-degree bend connecting north and east.
|
||||
# J is a 90-degree bend connecting north and west.
|
||||
# 7 is a 90-degree bend connecting south and west.
|
||||
# F is a 90-degree bend connecting south and east.
|
||||
# . is ground; there is no pipe in this tile.
|
||||
# S is the starting position of the animal; there is a pipe on this tile, but your sketch doesn't show what shape the pipe has.
|
||||
|
||||
# Mapping of in-direction to out-direction for each piece.
|
||||
DIRS = {
|
||||
'|': {
|
||||
(1, 0): (1, 0),
|
||||
(-1, 0): (-1, 0),
|
||||
},
|
||||
'-': {
|
||||
(0, -1): (0, -1),
|
||||
(0, 1): (0, 1),
|
||||
},
|
||||
'L': {
|
||||
(1, 0): (0, 1),
|
||||
(0, -1): (-1, 0),
|
||||
},
|
||||
'J': {
|
||||
(0, 1): (-1, 0),
|
||||
(1, 0): (0, -1),
|
||||
},
|
||||
'7': {
|
||||
(0, 1): (1, 0),
|
||||
(-1, 0): (0, -1),
|
||||
},
|
||||
'F': {
|
||||
(-1, 0): (0, 1),
|
||||
(0, -1): (1, 0),
|
||||
}
|
||||
}
|
||||
|
||||
RIGHTS = {
|
||||
'|': {
|
||||
(1, 0): [(0, -1)],
|
||||
(-1, 0): [(0, 1)],
|
||||
},
|
||||
'-': {
|
||||
(0, -1): [(-1, 0)],
|
||||
(0, 1): [(1, 0)],
|
||||
},
|
||||
'L': {
|
||||
(1, 0): [(0, -1), (1, 0)],
|
||||
(0, -1): [(-1, 1)],
|
||||
},
|
||||
'J': {
|
||||
(0, 1): [(1, 0), (0, 1)],
|
||||
(1, 0): [(-1, -1)],
|
||||
},
|
||||
'7': {
|
||||
(0, 1): [(1, -1)],
|
||||
(-1, 0): [(0, 1), (-1, 0)],
|
||||
},
|
||||
'F': {
|
||||
(-1, 0): [(1, 1)],
|
||||
(0, -1): [(-1, 0), (0, -1)],
|
||||
}
|
||||
}
|
||||
|
||||
def solve(lines: list[str], return_path=False):
|
||||
res = 0
|
||||
maze = []
|
||||
start = ()
|
||||
max_path, max_right = [], []
|
||||
maze = list(map(list, lines))
|
||||
for i, row in enumerate(maze):
|
||||
for j, col in enumerate(row):
|
||||
if col == "S":
|
||||
start = (i , j)
|
||||
row_max, col_max = len(maze), len(maze[0])
|
||||
|
||||
for current_dir in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
|
||||
current_field = start
|
||||
steps = 0
|
||||
path = []
|
||||
right = []
|
||||
# print(f"START: {start} {current_dir=}")
|
||||
while True:
|
||||
path.append(current_field)
|
||||
next_field = (current_field[0] + current_dir[0], current_field[1] + current_dir[1])
|
||||
if next_field == start:
|
||||
break
|
||||
|
||||
if next_field[0] < 0 or next_field[1] < 0 or next_field[0] >= row_max or next_field[1] >= col_max:
|
||||
# print(f"BREAK: Cannot go to {next_field=}!")
|
||||
break
|
||||
|
||||
prev_dir = current_dir
|
||||
next_char = maze[next_field[0]][next_field[1]]
|
||||
try:
|
||||
current_dir = DIRS[next_char][current_dir]
|
||||
except KeyError:
|
||||
# print(f"BREAK: Cannot go from {current_field=} with {current_dir=} to {next_field=} ({next_char})!")
|
||||
break
|
||||
|
||||
for rights in RIGHTS[next_char][prev_dir]:
|
||||
rf = (next_field[0] + rights[0], next_field[1] + rights[1])
|
||||
right.append(rf)
|
||||
|
||||
current_field = next_field
|
||||
steps += 1
|
||||
res = max(res, (steps + 1) // 2)
|
||||
if len(path) > len(max_path):
|
||||
max_path = path
|
||||
max_right = right
|
||||
|
||||
if return_path:
|
||||
return res, max_path, max_right
|
||||
else:
|
||||
return res
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
row_max = len(lines)
|
||||
col_max = len(lines[0])
|
||||
length, path, right = solve(lines, True)
|
||||
|
||||
def clean(fields):
|
||||
fields = list(set(fields))
|
||||
cleaned = []
|
||||
for f in fields:
|
||||
if f in path:
|
||||
continue
|
||||
if f[0] < 0 or f[1] < 0 or f[0] >= row_max or f[1] >= col_max:
|
||||
continue
|
||||
cleaned.append(f)
|
||||
return cleaned
|
||||
|
||||
right = clean(right)
|
||||
visited = set()
|
||||
to_visit = list(right)
|
||||
while to_visit:
|
||||
current = to_visit.pop()
|
||||
for nb in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
|
||||
f = (current[0] + nb[0], current[1] + nb[1])
|
||||
if f[0] < 0 or f[1] < 0 or f[0] >= row_max or f[1] >= col_max:
|
||||
continue
|
||||
|
||||
if f not in visited and f not in path:
|
||||
right.append(f)
|
||||
to_visit.append(f)
|
||||
visited.add(f)
|
||||
|
||||
right = clean(right)
|
||||
|
||||
n_all = row_max * col_max
|
||||
n_right = len(right)
|
||||
n_left = n_all - n_right - len(path)
|
||||
|
||||
return min(n_left, n_right)
|
||||
|
||||
def main():
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("i10.txt").read())
|
||||
print("Solution 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE4)
|
||||
print("Example 2:", solve2(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("i10.txt").read())
|
||||
print("Solution 2:", solve2(lines))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user