2022-24
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:
parent
b22f34cdc6
commit
a560c0b196
6 changed files with 188 additions and 1 deletions
1
challenges/2022/24-blizzardBasin/README.md
Normal file
1
challenges/2022/24-blizzardBasin/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# [Day 24: Blizzard Basin](https://adventofcode.com/2022/day/24)
|
15
challenges/2022/24-blizzardBasin/benchmark.json
Normal file
15
challenges/2022/24-blizzardBasin/benchmark.json
Normal 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
|
||||
}
|
17
challenges/2022/24-blizzardBasin/info.json
Normal file
17
challenges/2022/24-blizzardBasin/info.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
150
challenges/2022/24-blizzardBasin/py/__init__.py
Normal file
150
challenges/2022/24-blizzardBasin/py/__init__.py
Normal 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 |
|
@ -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])
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue