Fix linting.
This commit is contained in:
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import heapq
|
||||
import sys
|
||||
from typing import Literal, TypeAlias
|
||||
from typing import Literal, TypeAlias, cast
|
||||
|
||||
PlayerType: TypeAlias = Literal["player", "boss"]
|
||||
SpellType: TypeAlias = Literal["magic missile", "drain", "shield", "poison", "recharge"]
|
||||
@@ -18,6 +18,16 @@ Node: TypeAlias = tuple[
|
||||
tuple[tuple[SpellType, int], ...],
|
||||
]
|
||||
|
||||
ATTACK_SPELLS: list[tuple[SpellType, int, int, int]] = [
|
||||
("magic missile", 53, 4, 0),
|
||||
("drain", 73, 2, 2),
|
||||
]
|
||||
BUFF_SPELLS: list[tuple[BuffType, int, int]] = [
|
||||
("shield", 113, 6),
|
||||
("poison", 173, 6),
|
||||
("recharge", 229, 5),
|
||||
]
|
||||
|
||||
|
||||
def play(
|
||||
player_hp: int,
|
||||
@@ -97,10 +107,7 @@ def play(
|
||||
else:
|
||||
buff_types = {b for b, _ in buffs}
|
||||
|
||||
for spell, cost, damage, regeneration in (
|
||||
("magic missile", 53, 4, 0),
|
||||
("drain", 73, 2, 2),
|
||||
):
|
||||
for spell, cost, damage, regeneration in ATTACK_SPELLS:
|
||||
if player_mana < cost:
|
||||
continue
|
||||
|
||||
@@ -114,15 +121,11 @@ def play(
|
||||
player_armor,
|
||||
max(0, boss_hp - damage),
|
||||
buffs,
|
||||
spells + ((spell, cost),),
|
||||
spells + cast("tuple[tuple[SpellType, int]]", ((spell, cost),)),
|
||||
),
|
||||
)
|
||||
|
||||
for buff_type, buff_cost, buff_length in (
|
||||
("shield", 113, 6),
|
||||
("poison", 173, 6),
|
||||
("recharge", 229, 5),
|
||||
):
|
||||
for buff_type, buff_cost, buff_length in BUFF_SPELLS:
|
||||
if buff_type in buff_types:
|
||||
continue
|
||||
|
||||
@@ -138,8 +141,14 @@ def play(
|
||||
player_mana - buff_cost,
|
||||
player_armor + 7 * (buff_type == "shield"),
|
||||
boss_hp,
|
||||
buffs + ((buff_type, buff_length),),
|
||||
spells + ((buff_type, buff_cost),),
|
||||
buffs
|
||||
+ cast(
|
||||
"tuple[tuple[BuffType, int]]", ((buff_type, buff_length),)
|
||||
),
|
||||
spells
|
||||
+ cast(
|
||||
"tuple[tuple[SpellType, int]]", ((buff_type, buff_cost),)
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
@@ -10,7 +10,8 @@ lines = sys.stdin.read().splitlines()
|
||||
distances: dict[str, dict[str, int]] = defaultdict(dict)
|
||||
for line in lines:
|
||||
origin, destination, length = cast(
|
||||
tuple[str, str, int], parse.parse("{} to {} = {:d}", line) # type: ignore
|
||||
tuple[str, str, int],
|
||||
parse.parse("{} to {} = {:d}", line), # type: ignore
|
||||
)
|
||||
distances[origin][destination] = distances[destination][origin] = length
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,12 +1,13 @@
|
||||
import sys
|
||||
from math import prod
|
||||
from typing import Literal, cast
|
||||
from typing import Literal, TypeAlias, cast
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
commands = [
|
||||
(cast(Literal["forward", "up", "down"], (p := line.split())[0]), int(p[1]))
|
||||
for line in lines
|
||||
Command: TypeAlias = Literal["forward", "up", "down"]
|
||||
|
||||
commands: list[tuple[Command, int]] = [
|
||||
(cast(Command, (p := line.split())[0]), int(p[1])) for line in lines
|
||||
]
|
||||
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
|
@@ -1,21 +1,19 @@
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
positions = [int(c) for c in sys.stdin.read().strip().split(",")]
|
||||
|
||||
positions = np.asarray([int(c) for c in sys.stdin.read().strip().split(",")])
|
||||
|
||||
min_position, max_position = positions.min(), positions.max()
|
||||
min_position, max_position = min(positions), max(positions)
|
||||
|
||||
# part 1
|
||||
answer_1 = min(
|
||||
np.sum(np.abs(positions - position))
|
||||
sum(abs(p - position) for p in positions)
|
||||
for position in range(min_position, max_position + 1)
|
||||
)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
# part 2
|
||||
answer_2 = min(
|
||||
np.sum(abs(positions - position) * (abs(positions - position) + 1) // 2)
|
||||
sum(abs(p - position) * (abs(p - position) + 1) // 2 for p in positions)
|
||||
for position in range(min_position, max_position + 1)
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
@@ -122,8 +122,8 @@ lines = sys.stdin.read().splitlines()
|
||||
|
||||
grid = [[ord(cell) - ord("a") for cell in line] for line in lines]
|
||||
|
||||
start: tuple[int, int]
|
||||
end: tuple[int, int]
|
||||
start: tuple[int, int] | None = None
|
||||
end: tuple[int, int] | None = None
|
||||
|
||||
# for part 2
|
||||
start_s: list[tuple[int, int]] = []
|
||||
@@ -138,6 +138,9 @@ for i_row, row in enumerate(grid):
|
||||
elif col == 0:
|
||||
start_s.append((i_row, i_col))
|
||||
|
||||
assert start is not None
|
||||
assert end is not None
|
||||
|
||||
# fix values
|
||||
grid[start[0]][start[1]] = 0
|
||||
grid[end[0]][end[1]] = ord("z") - ord("a")
|
||||
|
@@ -1,20 +1,22 @@
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import parse
|
||||
import parse # type: ignore
|
||||
from numpy.typing import NDArray
|
||||
|
||||
|
||||
def part1(sensor_to_beacon: dict[tuple[int, int], tuple[int, int]], row: int) -> int:
|
||||
no_beacons_row_l: list[np.ndarray] = []
|
||||
no_beacons_row_l: list[NDArray[np.floating[Any]]] = []
|
||||
|
||||
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
||||
d = abs(sx - bx) + abs(sy - by) # closest
|
||||
|
||||
no_beacons_row_l.append(sx - np.arange(0, d - abs(sy - row) + 1))
|
||||
no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1))
|
||||
no_beacons_row_l.append(sx - np.arange(0, d - abs(sy - row) + 1)) # type: ignore
|
||||
no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1)) # type: ignore
|
||||
|
||||
beacons_at_row = set(bx for (bx, by) in sensor_to_beacon.values() if by == row)
|
||||
no_beacons_row = set(np.concatenate(no_beacons_row_l)).difference(beacons_at_row)
|
||||
no_beacons_row = set(np.concatenate(no_beacons_row_l)).difference(beacons_at_row) # type: ignore
|
||||
|
||||
return len(no_beacons_row)
|
||||
|
||||
@@ -56,11 +58,12 @@ def part2_cplex(
|
||||
|
||||
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
||||
d = abs(sx - bx) + abs(sy - by)
|
||||
m.add_constraint(m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}")
|
||||
m.add_constraint(m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}") # type: ignore
|
||||
|
||||
m.set_objective("min", x + y)
|
||||
|
||||
s = m.solve()
|
||||
assert s is not None
|
||||
|
||||
vx = int(s.get_value(x))
|
||||
vy = int(s.get_value(y))
|
||||
@@ -72,7 +75,7 @@ lines = sys.stdin.read().splitlines()
|
||||
sensor_to_beacon: dict[tuple[int, int], tuple[int, int]] = {}
|
||||
|
||||
for line in lines:
|
||||
r = parse.parse(
|
||||
r: dict[str, str] = parse.parse( # type: ignore
|
||||
"Sensor at x={sx}, y={sy}: closest beacon is at x={bx}, y={by}", line
|
||||
)
|
||||
sensor_to_beacon[int(r["sx"]), int(r["sy"])] = (int(r["bx"]), int(r["by"]))
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import sys
|
||||
from typing import FrozenSet
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import sys
|
||||
from typing import Literal
|
||||
from typing import Any, Literal
|
||||
|
||||
import numpy as np
|
||||
import parse
|
||||
from tqdm import tqdm
|
||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
||||
from numpy.typing import NDArray
|
||||
|
||||
Reagent = Literal["ore", "clay", "obsidian", "geode"]
|
||||
REAGENTS: tuple[Reagent, ...] = (
|
||||
@@ -35,7 +35,7 @@ class State:
|
||||
self.robots = robots
|
||||
self.reagents = reagents
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
def __eq__(self, other: object) -> bool:
|
||||
return (
|
||||
isinstance(other, State)
|
||||
and self.robots == other.robots
|
||||
@@ -66,7 +66,7 @@ lines = sys.stdin.read().splitlines()
|
||||
|
||||
blueprints: list[dict[Reagent, IntOfReagent]] = []
|
||||
for line in lines:
|
||||
r = parse.parse(
|
||||
r: list[int] = parse.parse( # type: ignore
|
||||
"Blueprint {}: "
|
||||
"Each ore robot costs {:d} ore. "
|
||||
"Each clay robot costs {:d} ore. "
|
||||
@@ -94,11 +94,12 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
||||
name: max(blueprint[r].get(name, 0) for r in REAGENTS) for name in REAGENTS
|
||||
}
|
||||
|
||||
state_after_t: dict[int, set[State]] = {0: [State()]}
|
||||
state_after_t: dict[int, set[State]] = {0: {State()}}
|
||||
|
||||
for t in range(1, max_time + 1):
|
||||
# list of new states at the end of step t that we are going to prune later
|
||||
states_for_t: set[State] = set()
|
||||
robots_that_can_be_built: list[Reagent]
|
||||
|
||||
for state in state_after_t[t - 1]:
|
||||
robots_that_can_be_built = [
|
||||
@@ -132,7 +133,7 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
||||
for robot in robots_that_can_be_built:
|
||||
robots = state.robots.copy()
|
||||
robots[robot] += 1
|
||||
reagents = {
|
||||
reagents: IntOfReagent = {
|
||||
reagent: state.reagents[reagent]
|
||||
+ state.robots[reagent]
|
||||
- blueprint[robot].get(reagent, 0)
|
||||
@@ -151,7 +152,7 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
||||
]
|
||||
)
|
||||
|
||||
to_keep = []
|
||||
to_keep: list[NDArray[np.integer[Any]]] = []
|
||||
while len(np_states) > 0:
|
||||
first_dom = (np_states[1:] >= np_states[0]).all(axis=1).any()
|
||||
|
||||
|
@@ -56,7 +56,7 @@ def propagate(
|
||||
[() for _ in range(len(layout[0]))] for _ in range(len(layout))
|
||||
]
|
||||
|
||||
queue = [(start, direction)]
|
||||
queue: list[tuple[tuple[int, int], Direction]] = [(start, direction)]
|
||||
|
||||
while queue:
|
||||
(row, col), direction = queue.pop()
|
||||
|
@@ -114,11 +114,12 @@ for workflow_s in workflows_s.split("\n"):
|
||||
for block in block_s[:-1].split(","):
|
||||
check: Check
|
||||
if (i := block.find(":")) >= 0:
|
||||
check, target = (
|
||||
check = (
|
||||
cast(Category, block[0]),
|
||||
cast(Literal["<", ">"], block[1]),
|
||||
int(block[2:i]),
|
||||
), block[i + 1 :]
|
||||
)
|
||||
target = block[i + 1 :]
|
||||
else:
|
||||
check, target = None, block
|
||||
workflows[name].append((check, target))
|
||||
|
@@ -19,7 +19,7 @@ def _name(i: int) -> str:
|
||||
|
||||
|
||||
def build_supports(
|
||||
bricks: list[tuple[tuple[int, int, int], tuple[int, int, int]]]
|
||||
bricks: list[tuple[tuple[int, int, int], tuple[int, int, int]]],
|
||||
) -> tuple[dict[int, set[int]], dict[int, set[int]]]:
|
||||
# 1. compute locations where a brick of sand will land after falling by processing
|
||||
# them in sorted order of bottom z location
|
||||
|
@@ -2,24 +2,34 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import Literal, Sequence, TypeAlias, cast
|
||||
|
||||
VERBOSE = os.getenv("AOC_VERBOSE") == "True"
|
||||
logging.basicConfig(level=logging.INFO if VERBOSE else logging.WARNING)
|
||||
|
||||
Direction = {
|
||||
DirectionType: TypeAlias = Literal[">", "<", "^", "v", ".", "#"]
|
||||
|
||||
Direction: dict[DirectionType, tuple[int, int]] = {
|
||||
">": (0, +1),
|
||||
"<": (0, -1),
|
||||
"^": (-1, 0),
|
||||
"v": (+1, 0),
|
||||
}
|
||||
|
||||
Neighbors = {".": ((+1, 0), (-1, 0), (0, +1), (0, -1)), "#": ()} | {
|
||||
k: (v,) for k, v in Direction.items()
|
||||
}
|
||||
Neighbors = cast(
|
||||
"dict[DirectionType, tuple[tuple[int, int], ...]]",
|
||||
{
|
||||
".": ((+1, 0), (-1, 0), (0, +1), (0, -1)),
|
||||
"#": (),
|
||||
}
|
||||
| {k: (v,) for k, v in Direction.items()},
|
||||
)
|
||||
|
||||
|
||||
def neighbors(
|
||||
grid: list[str], node: tuple[int, int], ignore: set[tuple[int, int]] = set()
|
||||
grid: list[Sequence[DirectionType]],
|
||||
node: tuple[int, int],
|
||||
ignore: set[tuple[int, int]] = set(),
|
||||
):
|
||||
"""
|
||||
Compute neighbors of the given node, ignoring the given set of nodes and considering
|
||||
@@ -51,7 +61,7 @@ def neighbors(
|
||||
|
||||
|
||||
def reachable(
|
||||
grid: list[str], start: tuple[int, int], target: tuple[int, int]
|
||||
grid: list[Sequence[DirectionType]], start: tuple[int, int], target: tuple[int, int]
|
||||
) -> tuple[tuple[int, int], int]:
|
||||
"""
|
||||
Compute the next 'reachable' node in the grid, starting at the given node.
|
||||
@@ -75,7 +85,7 @@ def reachable(
|
||||
|
||||
|
||||
def compute_direct_links(
|
||||
grid: list[str], start: tuple[int, int], target: tuple[int, int]
|
||||
grid: list[Sequence[DirectionType]], start: tuple[int, int], target: tuple[int, int]
|
||||
) -> dict[tuple[int, int], list[tuple[tuple[int, int], int]]]:
|
||||
if start == target:
|
||||
return {}
|
||||
@@ -85,7 +95,7 @@ def compute_direct_links(
|
||||
i, j = neighbor
|
||||
di, dj = Direction[grid[i][j]]
|
||||
|
||||
reach, distance = reachable(lines, (i + di, j + dj), target)
|
||||
reach, distance = reachable(grid, (i + di, j + dj), target)
|
||||
direct[start].append((reach, distance + 2))
|
||||
|
||||
direct.update(compute_direct_links(grid, reach, target))
|
||||
@@ -124,7 +134,7 @@ def longest_path_length(
|
||||
return max_distance
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
lines = cast(list[Sequence[DirectionType]], sys.stdin.read().splitlines())
|
||||
n_rows, n_cols = len(lines), len(lines[0])
|
||||
start = (0, 1)
|
||||
target = (len(lines) - 1, len(lines[0]) - 2)
|
||||
|
Reference in New Issue
Block a user