Compare commits
1 Commits
master
...
2023/day17
Author | SHA1 | Date | |
---|---|---|---|
|
40ab70271e |
12
.drone.yml
12
.drone.yml
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: default
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: tests
|
|
||||||
image: python:3.10-slim
|
|
||||||
commands:
|
|
||||||
- pip install poetry
|
|
||||||
- poetry install
|
|
||||||
- poetry run poe lint
|
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,6 +1 @@
|
|||||||
# python / VS Code
|
|
||||||
venv
|
venv
|
||||||
__pycache__
|
|
||||||
.ruff_cache
|
|
||||||
.vscode
|
|
||||||
build
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,13 +1,12 @@
|
|||||||
import sys
|
import sys
|
||||||
from math import prod
|
from math import prod
|
||||||
from typing import Literal, TypeAlias, cast
|
from typing import Literal, cast
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
Command: TypeAlias = Literal["forward", "up", "down"]
|
commands = [
|
||||||
|
(cast(Literal["forward", "up", "down"], (p := line.split())[0]), int(p[1]))
|
||||||
commands: list[tuple[Command, int]] = [
|
for line in lines
|
||||||
(cast(Command, (p := line.split())[0]), int(p[1])) for line in lines
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
21
2021/day7.py
Normal file
21
2021/day7.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
positions = np.asarray([int(c) for c in sys.stdin.read().strip().split(",")])
|
||||||
|
|
||||||
|
min_position, max_position = positions.min(), positions.max()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = min(
|
||||||
|
np.sum(np.abs(positions - position))
|
||||||
|
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)
|
||||||
|
for position in range(min_position, max_position + 1)
|
||||||
|
)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
13
2021/day9.py
Normal file
13
2021/day9.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
# part 2
|
||||||
|
answer_2 = ...
|
||||||
|
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]
|
grid = [[ord(cell) - ord("a") for cell in line] for line in lines]
|
||||||
|
|
||||||
start: tuple[int, int] | None = None
|
start: tuple[int, int]
|
||||||
end: tuple[int, int] | None = None
|
end: tuple[int, int]
|
||||||
|
|
||||||
# for part 2
|
# for part 2
|
||||||
start_s: list[tuple[int, int]] = []
|
start_s: list[tuple[int, int]] = []
|
||||||
@ -138,9 +138,6 @@ for i_row, row in enumerate(grid):
|
|||||||
elif col == 0:
|
elif col == 0:
|
||||||
start_s.append((i_row, i_col))
|
start_s.append((i_row, i_col))
|
||||||
|
|
||||||
assert start is not None
|
|
||||||
assert end is not None
|
|
||||||
|
|
||||||
# fix values
|
# fix values
|
||||||
grid[start[0]][start[1]] = 0
|
grid[start[0]][start[1]] = 0
|
||||||
grid[end[0]][end[1]] = ord("z") - ord("a")
|
grid[end[0]][end[1]] = ord("z") - ord("a")
|
@ -1,22 +1,20 @@
|
|||||||
import sys
|
import sys
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import parse # type: ignore
|
import parse
|
||||||
from numpy.typing import NDArray
|
|
||||||
|
|
||||||
|
|
||||||
def part1(sensor_to_beacon: dict[tuple[int, int], tuple[int, int]], row: int) -> int:
|
def part1(sensor_to_beacon: dict[tuple[int, int], tuple[int, int]], row: int) -> int:
|
||||||
no_beacons_row_l: list[NDArray[np.floating[Any]]] = []
|
no_beacons_row_l: list[np.ndarray] = []
|
||||||
|
|
||||||
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
||||||
d = abs(sx - bx) + abs(sy - by) # closest
|
d = abs(sx - bx) + abs(sy - by) # closest
|
||||||
|
|
||||||
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))
|
||||||
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))
|
||||||
|
|
||||||
beacons_at_row = set(bx for (bx, by) in sensor_to_beacon.values() if by == row)
|
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) # type: ignore
|
no_beacons_row = set(np.concatenate(no_beacons_row_l)).difference(beacons_at_row)
|
||||||
|
|
||||||
return len(no_beacons_row)
|
return len(no_beacons_row)
|
||||||
|
|
||||||
@ -58,12 +56,11 @@ def part2_cplex(
|
|||||||
|
|
||||||
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
||||||
d = abs(sx - bx) + abs(sy - by)
|
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}") # type: ignore
|
m.add_constraint(m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}")
|
||||||
|
|
||||||
m.set_objective("min", x + y)
|
m.set_objective("min", x + y)
|
||||||
|
|
||||||
s = m.solve()
|
s = m.solve()
|
||||||
assert s is not None
|
|
||||||
|
|
||||||
vx = int(s.get_value(x))
|
vx = int(s.get_value(x))
|
||||||
vy = int(s.get_value(y))
|
vy = int(s.get_value(y))
|
||||||
@ -75,7 +72,7 @@ lines = sys.stdin.read().splitlines()
|
|||||||
sensor_to_beacon: dict[tuple[int, int], tuple[int, int]] = {}
|
sensor_to_beacon: dict[tuple[int, int], tuple[int, int]] = {}
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
r: dict[str, str] = parse.parse( # type: ignore
|
r = parse.parse(
|
||||||
"Sensor at x={sx}, y={sy}: closest beacon is at x={bx}, y={by}", line
|
"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"]))
|
sensor_to_beacon[int(r["sx"]), int(r["sy"])] = (int(r["bx"]), int(r["by"]))
|
@ -1,4 +1,5 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from typing import FrozenSet
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
import sys
|
import sys
|
||||||
from typing import Any, Literal
|
from typing import Literal
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
import parse
|
||||||
from numpy.typing import NDArray
|
from tqdm import tqdm
|
||||||
|
|
||||||
Reagent = Literal["ore", "clay", "obsidian", "geode"]
|
Reagent = Literal["ore", "clay", "obsidian", "geode"]
|
||||||
REAGENTS: tuple[Reagent, ...] = (
|
REAGENTS: tuple[Reagent, ...] = (
|
||||||
@ -35,7 +35,7 @@ class State:
|
|||||||
self.robots = robots
|
self.robots = robots
|
||||||
self.reagents = reagents
|
self.reagents = reagents
|
||||||
|
|
||||||
def __eq__(self, other: object) -> bool:
|
def __eq__(self, other) -> bool:
|
||||||
return (
|
return (
|
||||||
isinstance(other, State)
|
isinstance(other, State)
|
||||||
and self.robots == other.robots
|
and self.robots == other.robots
|
||||||
@ -66,7 +66,7 @@ lines = sys.stdin.read().splitlines()
|
|||||||
|
|
||||||
blueprints: list[dict[Reagent, IntOfReagent]] = []
|
blueprints: list[dict[Reagent, IntOfReagent]] = []
|
||||||
for line in lines:
|
for line in lines:
|
||||||
r: list[int] = parse.parse( # type: ignore
|
r = parse.parse(
|
||||||
"Blueprint {}: "
|
"Blueprint {}: "
|
||||||
"Each ore robot costs {:d} ore. "
|
"Each ore robot costs {:d} ore. "
|
||||||
"Each clay robot costs {:d} ore. "
|
"Each clay robot costs {:d} ore. "
|
||||||
@ -94,12 +94,11 @@ 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
|
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):
|
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
|
# list of new states at the end of step t that we are going to prune later
|
||||||
states_for_t: set[State] = set()
|
states_for_t: set[State] = set()
|
||||||
robots_that_can_be_built: list[Reagent]
|
|
||||||
|
|
||||||
for state in state_after_t[t - 1]:
|
for state in state_after_t[t - 1]:
|
||||||
robots_that_can_be_built = [
|
robots_that_can_be_built = [
|
||||||
@ -133,7 +132,7 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
|||||||
for robot in robots_that_can_be_built:
|
for robot in robots_that_can_be_built:
|
||||||
robots = state.robots.copy()
|
robots = state.robots.copy()
|
||||||
robots[robot] += 1
|
robots[robot] += 1
|
||||||
reagents: IntOfReagent = {
|
reagents = {
|
||||||
reagent: state.reagents[reagent]
|
reagent: state.reagents[reagent]
|
||||||
+ state.robots[reagent]
|
+ state.robots[reagent]
|
||||||
- blueprint[robot].get(reagent, 0)
|
- blueprint[robot].get(reagent, 0)
|
||||||
@ -152,7 +151,7 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
to_keep: list[NDArray[np.integer[Any]]] = []
|
to_keep = []
|
||||||
while len(np_states) > 0:
|
while len(np_states) > 0:
|
||||||
first_dom = (np_states[1:] >= np_states[0]).all(axis=1).any()
|
first_dom = (np_states[1:] >= np_states[0]).all(axis=1).any()
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user