Add days 17 through 19
This commit is contained in:
parent
89e2c58a78
commit
4d5c4e86c6
4 changed files with 297 additions and 0 deletions
74
day17.py
Normal file
74
day17.py
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import heapq
|
||||||
|
from pprint import pprint
|
||||||
|
import sys
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
DIRS = [(1, 0), (0, -1), (-1, 0), (0, 1)]
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
with open(sys.argv[1]) as f:
|
||||||
|
map = [[int(c) for c in l.strip()] for l in f]
|
||||||
|
|
||||||
|
pprint(map)
|
||||||
|
|
||||||
|
heap: list[tuple[int, tuple[int, int], int, int, tuple[Any, ...]]] = [(0, (0, 0), 0, 0, ())]
|
||||||
|
seen = set()
|
||||||
|
while heap:
|
||||||
|
(cost, (x, y), dir, straight, trace) = heapq.heappop(heap)
|
||||||
|
if (x, y, dir, straight) in seen:
|
||||||
|
continue
|
||||||
|
seen.add((x, y, dir, straight))
|
||||||
|
|
||||||
|
if straight >= 3:
|
||||||
|
continue
|
||||||
|
if (x, y) == (len(map) - 1, len(map[0]) - 1):
|
||||||
|
break
|
||||||
|
|
||||||
|
(dx, dy) = DIRS[dir]
|
||||||
|
if (0 <= (y + dy) < len(map)) and (0 <= (x + dx) < len(map[y])):
|
||||||
|
newtrace = (*trace, (x + dx, y + dy, dir))
|
||||||
|
newcost = cost + map[y + dy][x + dx]
|
||||||
|
heapq.heappush(heap, (newcost, (x + dx, y + dy), dir, straight + 1, newtrace))
|
||||||
|
|
||||||
|
newdir = (dir + 1) % 4
|
||||||
|
(dx, dy) = DIRS[newdir]
|
||||||
|
if (0 <= (y + dy) < len(map)) and (0 <= (x + dx) < len(map[y])):
|
||||||
|
newtrace = (*trace, (x + dx, y + dy, newdir))
|
||||||
|
newcost = cost + map[y + dy][x + dx]
|
||||||
|
heapq.heappush(heap, (newcost, (x + dx, y + dy), newdir, 0, newtrace))
|
||||||
|
|
||||||
|
newdir = (dir + 3) % 4
|
||||||
|
(dx, dy) = DIRS[newdir]
|
||||||
|
if (0 <= (y + dy) < len(map)) and (0 <= (x + dx) < len(map[y])):
|
||||||
|
newtrace = (*trace, (x + dx, y + dy, newdir))
|
||||||
|
newcost = cost + map[y + dy][x + dx]
|
||||||
|
heapq.heappush(heap, (newcost, (x + dx, y + dy), newdir, 0, newtrace))
|
||||||
|
else:
|
||||||
|
print("oh no")
|
||||||
|
path = [["."] * len(map[y]) for y in range(len(map))]
|
||||||
|
for (x, y, dir) in trace:
|
||||||
|
path[y][x] = [">", "^", "<", "v"][dir]
|
||||||
|
print("\n".join("".join(line) for line in path))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
path = [["."] * len(map[y]) for y in range(len(map))]
|
||||||
|
for (x, y, dir) in trace:
|
||||||
|
path[y][x] = [">", "^", "<", "v"][dir]
|
||||||
|
print("\n".join("".join(line) for line in path))
|
||||||
|
|
||||||
|
cost = 0
|
||||||
|
for (x, y, _) in trace:
|
||||||
|
cost += map[y][x]
|
||||||
|
print(cost)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
71
day17b.py
Normal file
71
day17b.py
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import heapq
|
||||||
|
from pprint import pprint
|
||||||
|
import sys
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
DIRS = [(1, 0), (0, -1), (-1, 0), (0, 1)]
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
with open(sys.argv[1]) as f:
|
||||||
|
map = [[int(c) for c in l.strip()] for l in f]
|
||||||
|
|
||||||
|
(w, h) = (len(map[0]), len(map))
|
||||||
|
|
||||||
|
heap: list[tuple[int, tuple[int, int], int, int, tuple[Any, ...]]] = [
|
||||||
|
# cost, pos, dir, straight, trace
|
||||||
|
(0, (0, 0), 0, 0, ()),
|
||||||
|
(0, (0, 0), 3, 0, ()),
|
||||||
|
]
|
||||||
|
seen = set()
|
||||||
|
it = 0
|
||||||
|
while heap:
|
||||||
|
it += 1
|
||||||
|
(cost, (x, y), dir, straight, trace) = heapq.heappop(heap)
|
||||||
|
if it >= 10000:
|
||||||
|
if (x, y, dir, straight) in seen:
|
||||||
|
continue
|
||||||
|
seen.add((x, y, dir, straight))
|
||||||
|
|
||||||
|
if (x, y) == (len(map[0]) - 1, len(map) - 1) and 10 >= straight > 3:
|
||||||
|
break
|
||||||
|
|
||||||
|
(dx, dy) = DIRS[dir]
|
||||||
|
if 10 >= (straight + 1) and (0 <= (y + dy) < len(map)) and (0 <= (x + dx) < len(map[y])):
|
||||||
|
newtrace = trace + ((x + dx, y + dy, dir),)
|
||||||
|
newcost = cost + map[y + dy][x + dx]
|
||||||
|
heapq.heappush(heap, (newcost, (x + dx, y + dy), dir, straight + 1, newtrace))
|
||||||
|
|
||||||
|
if 11 >= (straight + 1) > 4:
|
||||||
|
newdir = (dir + 1) % 4
|
||||||
|
(dx, dy) = DIRS[newdir]
|
||||||
|
if (0 <= (y + dy) < len(map)) and (0 <= (x + dx) < len(map[y])):
|
||||||
|
newtrace = trace + ((x + dx, y + dy, newdir),)
|
||||||
|
newcost = cost + map[y + dy][x + dx]
|
||||||
|
heapq.heappush(heap, (newcost, (x + dx, y + dy), newdir, 1, newtrace))
|
||||||
|
|
||||||
|
newdir = (dir + 3) % 4
|
||||||
|
(dx, dy) = DIRS[newdir]
|
||||||
|
if (0 <= (y + dy) < len(map)) and (0 <= (x + dx) < len(map[y])):
|
||||||
|
newtrace = trace + ((x + dx, y + dy, newdir),)
|
||||||
|
newcost = cost + map[y + dy][x + dx]
|
||||||
|
heapq.heappush(heap, (newcost, (x + dx, y + dy), newdir, 1, newtrace))
|
||||||
|
else:
|
||||||
|
print("oh no")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
path = [[str(c) for c in row] for row in map]
|
||||||
|
for (x, y, dir) in trace:
|
||||||
|
# path[y][x] = "\033[93m" + [">", "^", "<", "v"][dir] + "\033[0m"
|
||||||
|
path[y][x] = f"\033[93m{path[y][x]}\033[0m"
|
||||||
|
print("\n".join("".join(line) for line in path))
|
||||||
|
print(cost)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
# 1040 too low
|
||||||
|
# 1066 too high
|
55
day18.py
Normal file
55
day18.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
DIRS = {
|
||||||
|
"U": (0, -1),
|
||||||
|
"D": (0, 1),
|
||||||
|
"L": (-1, 0),
|
||||||
|
"R": (1, 0),
|
||||||
|
"3": (0, -1),
|
||||||
|
"1": (0, 1),
|
||||||
|
"2": (-1, 0),
|
||||||
|
"0": (1, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def solve(lines: list[tuple[int, int]], points: int) -> int:
|
||||||
|
area = 0
|
||||||
|
for i in range(len(lines)):
|
||||||
|
(x_a, y_a) = lines[i]
|
||||||
|
(x_b, y_b) = lines[(i + 1) % len(lines)]
|
||||||
|
area += (x_b + x_a) * (y_b - y_a) // 2
|
||||||
|
|
||||||
|
return area + points // 2 + 1
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
(x1, x2, y1, y2) = (0, 0, 0, 0)
|
||||||
|
(lines1, lines2) = ([], [])
|
||||||
|
(points1, points2) = (0, 0)
|
||||||
|
|
||||||
|
with open(sys.argv[1]) as f:
|
||||||
|
for line in f:
|
||||||
|
(dir, steps, color) = line.split()
|
||||||
|
|
||||||
|
(dx1, dy1) = DIRS[dir]
|
||||||
|
steps1 = int(steps)
|
||||||
|
lines1.append((x1, y1))
|
||||||
|
x1 += dx1 * steps1
|
||||||
|
y1 += dy1 * steps1
|
||||||
|
points1 += steps1
|
||||||
|
|
||||||
|
(dx2, dy2) = DIRS[color[7]]
|
||||||
|
steps2 = int(color[2:7], 16)
|
||||||
|
lines2.append((x2, y2))
|
||||||
|
x2 += dx2 * steps2
|
||||||
|
y2 += dy2 * steps2
|
||||||
|
points2 += steps2
|
||||||
|
|
||||||
|
part1 = solve(lines1, points1)
|
||||||
|
part2 = solve(lines2, points2)
|
||||||
|
|
||||||
|
print(part1, part2)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
97
day19.py
Normal file
97
day19.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
from pprint import pprint
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def part1(workflows: dict[str, list[list[str]]], ratings: str) -> int:
|
||||||
|
result = 0
|
||||||
|
|
||||||
|
for rating in ratings.splitlines():
|
||||||
|
assert [r.split("=")[0] for r in rating[1:-1].split(",")] == list("xmas")
|
||||||
|
(x, m, a, s) = (int(r.split("=")[1]) for r in rating[1:-1].split(","))
|
||||||
|
|
||||||
|
workflow = "in"
|
||||||
|
while workflow not in "RA":
|
||||||
|
print(workflow)
|
||||||
|
for rule in workflows[workflow]:
|
||||||
|
match rule:
|
||||||
|
case [target]:
|
||||||
|
workflow = target
|
||||||
|
break
|
||||||
|
case [condition, target]:
|
||||||
|
if eval(condition):
|
||||||
|
workflow = target
|
||||||
|
break
|
||||||
|
|
||||||
|
if workflow == "A":
|
||||||
|
result += sum((x, m, a, s))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def part2(workflows: dict[str, list[list[str]]]) -> int:
|
||||||
|
result = 0
|
||||||
|
stack = [("in", (1, 4001), (1, 4001), (1, 4001), (1, 4001))]
|
||||||
|
while stack:
|
||||||
|
(workflow, x, m, a, s) = stack.pop()
|
||||||
|
|
||||||
|
if workflow == "A":
|
||||||
|
print(x, m, a, s)
|
||||||
|
result += (x[1] - x[0]) * (m[1] - m[0]) * (a[1] - a[0]) * (s[1] - s[0])
|
||||||
|
continue
|
||||||
|
|
||||||
|
if workflow == "R":
|
||||||
|
continue
|
||||||
|
|
||||||
|
for rule in workflows[workflow]:
|
||||||
|
match rule:
|
||||||
|
case [target]:
|
||||||
|
stack.append((target, x, m, a, s))
|
||||||
|
case [condition, target] if ">" in condition:
|
||||||
|
(var, value_) = condition.split(">")
|
||||||
|
value = int(value_) + 1
|
||||||
|
match var:
|
||||||
|
case "x":
|
||||||
|
stack.append((target, (value, x[1]), m, a, s))
|
||||||
|
x = (x[0], value)
|
||||||
|
case "m":
|
||||||
|
stack.append((target, x, (value, m[1]), a, s))
|
||||||
|
m = (m[0], value)
|
||||||
|
case "a":
|
||||||
|
stack.append((target, x, m, (value, a[1]), s))
|
||||||
|
a = (a[0], value)
|
||||||
|
case "s":
|
||||||
|
stack.append((target, x, m, a, (value, s[1])))
|
||||||
|
s = (s[0], value)
|
||||||
|
case [condition, target] if "<" in condition:
|
||||||
|
(var, value_) = condition.split("<")
|
||||||
|
value = int(value_)
|
||||||
|
match var:
|
||||||
|
case "x":
|
||||||
|
stack.append((target, (x[0], value), m, a, s))
|
||||||
|
x = (value, x[1])
|
||||||
|
case "m":
|
||||||
|
stack.append((target, x, (m[0], value), a, s))
|
||||||
|
m = (value, m[1])
|
||||||
|
case "a":
|
||||||
|
stack.append((target, x, m, (a[0], value), s))
|
||||||
|
a = (value, a[1])
|
||||||
|
case "s":
|
||||||
|
stack.append((target, x, m, a, (s[0], value)))
|
||||||
|
s = (value, s[1])
|
||||||
|
return result
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
with open(sys.argv[1]) as f:
|
||||||
|
(workflows_, ratings) = f.read().split("\n\n")
|
||||||
|
|
||||||
|
workflows = {}
|
||||||
|
for workflow in workflows_.splitlines():
|
||||||
|
(name, rules_) = workflow.split("{", 1)
|
||||||
|
rules = [rule.split(":") for rule in rules_[:-1].split(",")]
|
||||||
|
workflows[name] = rules
|
||||||
|
|
||||||
|
p1 = part1(workflows, ratings)
|
||||||
|
p2 = part2(workflows)
|
||||||
|
print(p1, p2)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in a new issue