Compare commits
No commits in common. "8e8e26f2d66fb7f7b20c614aab40a133fb36b597" and "e18d783d3996a4360801742349bfef9f344fe5d6" have entirely different histories.
8e8e26f2d6
...
e18d783d39
|
@ -1,43 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from collections.abc import Iterator
|
|
||||||
from typing import NamedTuple
|
|
||||||
|
|
||||||
|
|
||||||
class Point3(NamedTuple):
|
|
||||||
x: int
|
|
||||||
y: int
|
|
||||||
z: int
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_input(cls, input: str) -> "Point3":
|
|
||||||
x, y, z = map(int, input.split(","))
|
|
||||||
return cls(x, y, z)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def neighbours(cls, p: "Point3") -> Iterator["Point3"]:
|
|
||||||
for dx, dy, dz in (
|
|
||||||
(0, 0, -1),
|
|
||||||
(0, 0, 1),
|
|
||||||
(0, -1, 0),
|
|
||||||
(0, 1, 0),
|
|
||||||
(-1, 0, 0),
|
|
||||||
(1, 0, 0),
|
|
||||||
):
|
|
||||||
yield cls(p.x + dx, p.y + dy, p.z + dz)
|
|
||||||
|
|
||||||
|
|
||||||
def solve(input: list[str]) -> int:
|
|
||||||
cubes = {Point3.from_input(line) for line in input}
|
|
||||||
|
|
||||||
return sum(1 for p in cubes for n in Point3.neighbours(p) if n not in cubes)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
input = sys.stdin.read().splitlines()
|
|
||||||
print(solve(input))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
2145
2022/d18/ex1/input
2145
2022/d18/ex1/input
File diff suppressed because it is too large
Load diff
|
@ -1,119 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import itertools
|
|
||||||
import sys
|
|
||||||
from collections import deque
|
|
||||||
from collections.abc import Iterator
|
|
||||||
from typing import NamedTuple
|
|
||||||
|
|
||||||
|
|
||||||
class Point3(NamedTuple):
|
|
||||||
x: int
|
|
||||||
y: int
|
|
||||||
z: int
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_input(cls, input: str) -> "Point3":
|
|
||||||
x, y, z = map(int, input.split(","))
|
|
||||||
return cls(x, y, z)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def neighbours(cls, p: "Point3") -> Iterator["Point3"]:
|
|
||||||
for dx, dy, dz in (
|
|
||||||
(0, 0, -1),
|
|
||||||
(0, 0, 1),
|
|
||||||
(0, -1, 0),
|
|
||||||
(0, 1, 0),
|
|
||||||
(-1, 0, 0),
|
|
||||||
(1, 0, 0),
|
|
||||||
):
|
|
||||||
yield cls(p.x + dx, p.y + dy, p.z + dz)
|
|
||||||
|
|
||||||
|
|
||||||
def solve(input: list[str]) -> int:
|
|
||||||
def compute_unreachable(cubes: set[Point3]) -> set[Point3]:
|
|
||||||
def explore(p: Point3, can_reach_out: dict[Point3, bool]) -> bool:
|
|
||||||
seen: set[Point3] = set()
|
|
||||||
queue: list[Point3] = [p]
|
|
||||||
while queue:
|
|
||||||
p = queue.pop()
|
|
||||||
if p in seen:
|
|
||||||
continue
|
|
||||||
if p in can_reach_out:
|
|
||||||
if can_reach_out[p]:
|
|
||||||
return True
|
|
||||||
continue # Don't go through walls
|
|
||||||
seen.add(p)
|
|
||||||
queue.extend(Point3.neighbours(p))
|
|
||||||
return False
|
|
||||||
|
|
||||||
minx, maxx = min(p.x for p in cubes), max(p.x for p in cubes)
|
|
||||||
miny, maxy = min(p.y for p in cubes), max(p.y for p in cubes)
|
|
||||||
minz, maxz = min(p.z for p in cubes), max(p.z for p in cubes)
|
|
||||||
|
|
||||||
can_reach_out = {p: False for p in cubes}
|
|
||||||
can_reach_out |= {
|
|
||||||
Point3(x, y, z): True
|
|
||||||
for x, (y, z) in zip(
|
|
||||||
itertools.repeat(minx - 1),
|
|
||||||
itertools.product(range(miny, maxy + 1), range(minz, maxz + 1)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
can_reach_out |= {
|
|
||||||
Point3(x, y, z): True
|
|
||||||
for x, (y, z) in zip(
|
|
||||||
itertools.repeat(maxx + 1),
|
|
||||||
itertools.product(range(miny, maxy + 1), range(minz, maxz + 1)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
can_reach_out |= {
|
|
||||||
Point3(x, y, z): True
|
|
||||||
for y, (x, z) in zip(
|
|
||||||
itertools.repeat(miny - 1),
|
|
||||||
itertools.product(range(minx, maxx + 1), range(minz, maxz + 1)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
can_reach_out |= {
|
|
||||||
Point3(x, y, z): True
|
|
||||||
for y, (x, z) in zip(
|
|
||||||
itertools.repeat(maxy + 1),
|
|
||||||
itertools.product(range(minx, maxx + 1), range(minz, maxz + 1)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
can_reach_out |= {
|
|
||||||
Point3(x, y, z): True
|
|
||||||
for z, (x, y) in zip(
|
|
||||||
itertools.repeat(minz - 1),
|
|
||||||
itertools.product(range(minx, maxx + 1), range(miny, maxy + 1)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
can_reach_out |= {
|
|
||||||
Point3(x, y, z): True
|
|
||||||
for z, (x, y) in zip(
|
|
||||||
itertools.repeat(maxz + 1),
|
|
||||||
itertools.product(range(minx, maxx + 1), range(miny, maxy + 1)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
for x, y, z in itertools.product(
|
|
||||||
range(minx, maxx + 1),
|
|
||||||
range(miny, maxy + 1),
|
|
||||||
range(minz, maxz + 1),
|
|
||||||
):
|
|
||||||
p = Point3(x, y, z)
|
|
||||||
can_reach_out[p] = explore(p, can_reach_out)
|
|
||||||
return {p for p, can_reach in can_reach_out.items() if not can_reach}
|
|
||||||
|
|
||||||
cubes = {Point3.from_input(line) for line in input}
|
|
||||||
unreachable = compute_unreachable(cubes)
|
|
||||||
|
|
||||||
return sum(1 for p in cubes for n in Point3.neighbours(p) if n not in unreachable)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
input = sys.stdin.read().splitlines()
|
|
||||||
print(solve(input))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
2145
2022/d18/ex2/input
2145
2022/d18/ex2/input
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue