Add days 17 through 19

This commit is contained in:
Sijmen 2024-01-03 21:50:55 +01:00
parent 89e2c58a78
commit 4d5c4e86c6
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
4 changed files with 297 additions and 0 deletions

74
day17.py Normal file
View 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
View 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
View 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
View 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()