Initial commit
This commit is contained in:
commit
97a4330bc0
110 changed files with 7006 additions and 0 deletions
111
2024/16/two_opti.py
Normal file
111
2024/16/two_opti.py
Normal file
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import pprint
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
vec = tuple[int, int]
|
||||
|
||||
directions = [
|
||||
(-1, 0), # ^ North
|
||||
(0, 1), # > East
|
||||
(1, 0), # v South
|
||||
(0, -1), # < West
|
||||
]
|
||||
|
||||
directions_keys = ("^", ">", "v", "<")
|
||||
|
||||
min_scores: list[list[list[None | int]]] = list()
|
||||
for _ in range(height):
|
||||
line: list[list[None | int]] = list()
|
||||
for _ in range(width):
|
||||
cell: list[None | int] = [None] * len(directions)
|
||||
line.append(cell)
|
||||
min_scores.append(line)
|
||||
|
||||
start = height - 2, 1
|
||||
|
||||
valid_paths: list[tuple[int, set[vec]]] = list()
|
||||
|
||||
|
||||
def walk(pos: vec, dir: int, score: int, path: list[vec]) -> int | None:
|
||||
i, j = pos
|
||||
char = lines[i][j]
|
||||
|
||||
depth = len(path)
|
||||
path = path + [pos]
|
||||
|
||||
if depth > 1000:
|
||||
return None
|
||||
|
||||
# print("-" * depth, 28, pos, char, directions_keys[dir], score)
|
||||
if char == "E":
|
||||
valid_paths.append((score, set(path)))
|
||||
return score
|
||||
elif char == "#":
|
||||
return None
|
||||
|
||||
min_score = min_scores[i][j][dir]
|
||||
for d, min_score in enumerate(min_scores[i][j]):
|
||||
if min_score is None:
|
||||
continue
|
||||
if d == dir:
|
||||
if score > min_score:
|
||||
return None
|
||||
else:
|
||||
if score > min_score + 1000:
|
||||
return None
|
||||
min_scores[i][j][dir] = score
|
||||
|
||||
mscore = None
|
||||
for ndir, direction in enumerate(directions):
|
||||
ii, jj = i + direction[0], j + direction[1]
|
||||
price = 1 if dir == ndir else 1001
|
||||
nscore = walk((ii, jj), ndir, score + price, path)
|
||||
if nscore is None:
|
||||
continue
|
||||
if mscore is None or nscore < mscore:
|
||||
mscore = nscore
|
||||
return mscore
|
||||
|
||||
|
||||
sys.setrecursionlimit(9000)
|
||||
tot_score = walk(start, 1, 0, [])
|
||||
|
||||
print(76, len(valid_paths))
|
||||
all_best: set[vec] = set()
|
||||
for s, path in valid_paths:
|
||||
if s != tot_score:
|
||||
continue
|
||||
print(81, "BEST")
|
||||
all_best |= path
|
||||
|
||||
# Viz
|
||||
for i in range(height):
|
||||
cline = ""
|
||||
for j in range(width):
|
||||
char = lines[i][j]
|
||||
pos = i, j
|
||||
if pos in all_best:
|
||||
min_score = None
|
||||
for d in range(len(directions)):
|
||||
score = min_scores[i][j][d]
|
||||
if score is None:
|
||||
continue
|
||||
if min_score is None or score < min_score:
|
||||
char = directions_keys[d]
|
||||
min_score = score
|
||||
cline += char
|
||||
print(cline)
|
||||
print()
|
||||
|
||||
|
||||
print(tot_score)
|
||||
print(len(all_best))
|
Loading…
Add table
Add a link
Reference in a new issue