day22
This commit is contained in:
parent
eaaa845503
commit
b8c11565c7
@ -152,5 +152,15 @@
|
|||||||
"wrong": [],
|
"wrong": [],
|
||||||
"correct": 537
|
"correct": 537
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"22": {
|
||||||
|
"1": {
|
||||||
|
"wrong": [],
|
||||||
|
"correct": 8681
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"wrong": [],
|
||||||
|
"correct": 1070
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
152
day22.py
Normal file
152
day22.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
from enum import Enum
|
||||||
|
from heapq import heappush, heapify, heappop
|
||||||
|
from tools.aoc import AOCDay
|
||||||
|
from tools.coordinate import Coordinate
|
||||||
|
from tools.grid import Grid
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class RegionType(int, Enum):
|
||||||
|
ROCKY = 0
|
||||||
|
WET = 1
|
||||||
|
NARROW = 2
|
||||||
|
|
||||||
|
|
||||||
|
class Tools(int, Enum):
|
||||||
|
NEITHER = 0
|
||||||
|
TORCH = 1
|
||||||
|
CLIMBING_GEAR = 2
|
||||||
|
|
||||||
|
|
||||||
|
COMMON_TOOLS = {
|
||||||
|
RegionType.ROCKY: {Tools.TORCH, Tools.CLIMBING_GEAR},
|
||||||
|
RegionType.WET: {Tools.NEITHER, Tools.CLIMBING_GEAR},
|
||||||
|
RegionType.NARROW: {Tools.NEITHER, Tools.TORCH},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_common_tool(from_region_type: RegionType, to_region_type: RegionType) -> Tools:
|
||||||
|
return (COMMON_TOOLS[from_region_type] & COMMON_TOOLS[to_region_type]).pop()
|
||||||
|
|
||||||
|
|
||||||
|
class Cave(Grid):
|
||||||
|
def __init__(self, depth: int, target_x: int, target_y: int):
|
||||||
|
super().__init__()
|
||||||
|
self.depth = depth
|
||||||
|
self.target_x = target_x
|
||||||
|
self.target_y = target_y
|
||||||
|
self.set(Coordinate(0, 0), self.get_erosion_level(Coordinate(0, 0)))
|
||||||
|
|
||||||
|
def get_geologic_index(self, at: Coordinate) -> int:
|
||||||
|
if at.x == at.y == 0:
|
||||||
|
return 0
|
||||||
|
elif at.x == self.target_x and at.y == self.target_y:
|
||||||
|
return 0
|
||||||
|
elif at.y == 0:
|
||||||
|
return at.x * 16807
|
||||||
|
elif at.x == 0:
|
||||||
|
return at.y * 48271
|
||||||
|
else:
|
||||||
|
return self.get(at - Coordinate(1, 0)) * self.get(at - Coordinate(0, 1))
|
||||||
|
|
||||||
|
def get_region_type(self, at: Coordinate) -> RegionType:
|
||||||
|
return RegionType(self.get(at) % 3)
|
||||||
|
|
||||||
|
def get_erosion_level(self, at: Coordinate) -> int:
|
||||||
|
return (self.get_geologic_index(at) + self.depth) % 20183
|
||||||
|
|
||||||
|
def get(self, at: Coordinate) -> int:
|
||||||
|
if not self.isSet(at):
|
||||||
|
self.set(at, self.get_erosion_level(at))
|
||||||
|
|
||||||
|
return super().get(at)
|
||||||
|
|
||||||
|
def get_risk_level(self) -> int:
|
||||||
|
risk = 0
|
||||||
|
for x in range(0, self.target_x + 1):
|
||||||
|
for y in range(0, self.target_y + 1):
|
||||||
|
at = Coordinate(x, y)
|
||||||
|
risk += int(self.get_region_type(at))
|
||||||
|
|
||||||
|
return risk
|
||||||
|
|
||||||
|
|
||||||
|
class Day(AOCDay):
|
||||||
|
inputs = [
|
||||||
|
[
|
||||||
|
(114, "input22_test"),
|
||||||
|
(8681, "input22"),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
(45, "input22_test"),
|
||||||
|
(1070, "input22"),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_params(self) -> (int, int, int):
|
||||||
|
"""(depth, target_x, target_y)"""
|
||||||
|
lines = self.getInput()
|
||||||
|
depth = int(lines[0].split()[1])
|
||||||
|
target_x, target_y = map(int, lines[1].split()[1].split(","))
|
||||||
|
return depth, target_x, target_y
|
||||||
|
|
||||||
|
def part1(self) -> Any:
|
||||||
|
cave = Cave(*self.get_params())
|
||||||
|
return cave.get_risk_level()
|
||||||
|
|
||||||
|
def part2(self) -> Any:
|
||||||
|
params = self.get_params()
|
||||||
|
target = Coordinate(*params[1:])
|
||||||
|
cave = Cave(*params)
|
||||||
|
queue = [(0, 0, Tools.TORCH, Coordinate(0, 0))]
|
||||||
|
heapify(queue)
|
||||||
|
visited = set()
|
||||||
|
|
||||||
|
target_dist, target_tool = None, None
|
||||||
|
while len(queue) > 0:
|
||||||
|
_, current_dist, current_tool, at = heappop(queue)
|
||||||
|
if (at, current_tool) in visited:
|
||||||
|
continue
|
||||||
|
|
||||||
|
visited.add((at, current_tool))
|
||||||
|
|
||||||
|
if at == target:
|
||||||
|
target_dist = current_dist
|
||||||
|
target_tool = current_tool
|
||||||
|
break
|
||||||
|
|
||||||
|
for next in at.getNeighbours(includeDiagonal=False, minX=0, minY=0):
|
||||||
|
region_type_at = cave.get_region_type(at)
|
||||||
|
region_type_next = cave.get_region_type(next)
|
||||||
|
if region_type_at == region_type_next:
|
||||||
|
common_tool = current_tool
|
||||||
|
else:
|
||||||
|
common_tool = get_common_tool(region_type_at, region_type_next)
|
||||||
|
|
||||||
|
if common_tool == current_tool:
|
||||||
|
heappush(
|
||||||
|
queue, (next.getDistanceTo(target) + current_dist + 1, current_dist + 1, common_tool, next)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
heappush(
|
||||||
|
queue, (next.getDistanceTo(target) + current_dist + 7, current_dist + 8, common_tool, next)
|
||||||
|
)
|
||||||
|
|
||||||
|
if target_tool != Tools.TORCH:
|
||||||
|
target_dist += 7
|
||||||
|
while queue:
|
||||||
|
_, current_dist, current_tool, at = heappop(queue)
|
||||||
|
if at != target or current_dist >= target_dist:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if current_tool == Tools.TORCH:
|
||||||
|
target_dist = current_dist
|
||||||
|
elif current_dist + 7 < target_dist:
|
||||||
|
target_dist = current_dist + 7
|
||||||
|
|
||||||
|
return target_dist
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
day = Day(2018, 22)
|
||||||
|
day.run(verbose=True)
|
||||||
2
inputs/input22
Normal file
2
inputs/input22
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
depth: 5616
|
||||||
|
target: 10,785
|
||||||
2
inputs/input22_test
Normal file
2
inputs/input22_test
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
depth: 510
|
||||||
|
target: 10,10
|
||||||
Loading…
Reference in New Issue
Block a user