2022-24 attempt 1

Signed-off-by: AKP <tom@tdpain.net>

2022-24

Signed-off-by: AKP <tom@tdpain.net>
This commit is contained in:
akp 2022-12-24 17:06:50 +00:00
parent b22f34cdc6
commit a560c0b196
No known key found for this signature in database
GPG key ID: AA5726202C8879B7
6 changed files with 188 additions and 1 deletions

View file

@ -0,0 +1 @@
# [Day 24: Blizzard Basin](https://adventofcode.com/2022/day/24)

View file

@ -0,0 +1,15 @@
{
"day": 24,
"dir": "challenges/2022/24-blizzardBasin",
"implementations": {
"Python": {
"part.1.avg": 3.8155926863352456,
"part.1.max": 3.83038330078125,
"part.1.min": 3.801712989807129,
"part.2.avg": 11.761492411295572,
"part.2.max": 11.78315782546997,
"part.2.min": 11.74697995185852
}
},
"numRuns": 3
}

View file

@ -0,0 +1,17 @@
{
"inputFile": "input.txt",
"testCases": {
"one": [
{
"input": "#.######\n#>>.<^<#\n#.<..<<#\n#>v.><>#\n#<^v^^>#\n######.#\n",
"expected": "18"
}
],
"two": [
{
"input": "#.######\n#>>.<^<#\n#.<..<<#\n#>v.><>#\n#<^v^^>#\n######.#\n",
"expected": "54"
}
]
}
}

View file

@ -0,0 +1,150 @@
from typing import *
from dataclasses import dataclass
from aocpy import BaseChallenge, Vector
from enum import Enum
class CellState(Enum):
WALL = "#"
UP = "^"
DOWN = "v"
LEFT = "<"
RIGHT = ">"
def delta(self) -> Tuple[int, int]:
if self == CellState.WALL:
raise ValueError("cannot get delta of a wall")
elif self == CellState.UP:
return (0, -1)
elif self == CellState.DOWN:
return (0, 1)
elif self == CellState.LEFT:
return (-1, 0)
elif self == CellState.RIGHT:
return (1, 0)
else:
raise ValueError(f"unknown CellState {self}")
@dataclass
class Valley:
positions: Dict[Vector, List[CellState]]
width: int
height: int
start: Vector
end: Vector
def tick(self):
old_valley = self.positions
self.positions = {}
for cell in old_valley:
if old_valley[cell][0] == CellState.WALL:
self.positions[cell] = [CellState.WALL]
continue
for blizzard in old_valley[cell]:
next_pos = cell + blizzard.delta()
nx = old_valley.get(next_pos, [])
if len(nx) != 0 and nx[0] == CellState.WALL:
if blizzard == CellState.DOWN:
next_pos = Vector(cell.x, 1)
elif blizzard == CellState.UP:
next_pos = Vector(cell.x, self.height - 2)
elif blizzard == CellState.LEFT:
next_pos = Vector(self.width - 2, cell.y)
elif blizzard == CellState.RIGHT:
next_pos = Vector(1, cell.y)
else:
raise ValueError(f"unexpected cell state {blizzard} at {cell=}")
b = self.positions.get(next_pos, [])
b.append(blizzard)
self.positions[next_pos] = b
def __repr__(self) -> str:
res = ""
for y in range(self.height):
for x in range(self.width):
pos = self.positions.get(Vector(x, y))
res += (
"."
if pos is None
else pos[0].value
if len(pos) == 1
else str(len(pos))
)
res += "\n"
return res[:-1]
def parse(instr: str) -> Valley:
res: Dict[Vector, List[CellState]] = {}
start: Optional[Vector] = None
end: Optional[Vector] = None
split_lines = instr.strip().splitlines()
for y, line in enumerate(split_lines):
for x, char in enumerate(line):
if char == ".":
if y == 0:
start = Vector(x, y)
# res[start] = [CellState.WALL]
elif y == len(split_lines) - 1:
end = Vector(x, y)
else:
res[Vector(x, y)] = [CellState(char)]
assert start is not None
assert end is not None
return Valley(res, len(split_lines[0]), len(split_lines), start, end)
def quickest_time(valley: Valley, start: Vector, end: Vector, time: int = 1) -> int:
states: Dict[Vector, None] = {start: None}
while True:
valley.tick()
for cell in list(states.keys()):
adjacent = list(
filter(
lambda x: 0 <= x.x <= valley.width and 0 <= x.y <= valley.height,
map(lambda x: cell + x, ((0, 0), (0, 1), (0, -1), (1, 0), (-1, 0))),
)
)
for j in reversed(range(len(adjacent))):
pos = adjacent[j]
if pos in valley.positions:
_ = adjacent.pop(j)
del states[cell]
for item in adjacent:
states[item] = None
if end in states:
break
time += 1
return time
class Challenge(BaseChallenge):
@staticmethod
def one(instr: str) -> int:
valley = parse(instr)
return quickest_time(valley, valley.start, valley.end)
@staticmethod
def two(instr: str) -> int:
valley = parse(instr)
a = quickest_time(valley, valley.start, valley.end)
b = quickest_time(valley, valley.end, valley.start, time=a + 1)
c = quickest_time(valley, valley.start, valley.end, time=b + 1)
return c

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Before After
Before After

View file

@ -55,7 +55,7 @@ class Vector:
if len(args) == 1 and Vector._is_vector_tuple(args[0]):
x, y = args[0]
elif len(args) != 2:
return ValueError("expected integer tuple or pair of integers")
raise ValueError("expected integer tuple or pair of integers")
else:
x, y = args
@ -71,6 +71,10 @@ class Vector:
def manhattan_distance(self, o: Vector) -> int:
return abs(self.x - o.x) + abs(self.y - o.y)
@property
def tuple(self) -> Tuple[int, int]:
return self.x, self.y
def __add__(self, o: Any) -> Vector:
if Vector._is_vector_tuple(o):
return Vector(self.x + o[0], self.y + o[1])