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