summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tomasz@kramkow.ski>2023-12-11 15:17:00 +0000
committerTomasz Kramkowski <tomasz@kramkow.ski>2023-12-11 15:17:00 +0000
commit0b715584879ddea7d72a6b033faf8fa43595aa2e (patch)
treec8801897dd57bc878e5d6f47aa814e9d38c995e5
parent0ef867a34e8dd3d042f003f50ad8ea012549993e (diff)
downloadaoc2023-0b715584879ddea7d72a6b033faf8fa43595aa2e.tar.gz
aoc2023-0b715584879ddea7d72a6b033faf8fa43595aa2e.tar.xz
aoc2023-0b715584879ddea7d72a6b033faf8fa43595aa2e.zip
day 11 more functional
-rw-r--r--11.py52
1 files changed, 31 insertions, 21 deletions
diff --git a/11.py b/11.py
index 645c6c7..ae1b6a8 100644
--- a/11.py
+++ b/11.py
@@ -1,38 +1,48 @@
# pyright: strict
-from itertools import accumulate, combinations
+from collections.abc import Callable, Iterable, Iterator
+from dataclasses import dataclass
+from itertools import accumulate, combinations, starmap
from sys import stdin
+from typing import Self
+
+
+@dataclass(frozen=True, slots=True)
+class Point:
+ x: int
+ y: int
+
+ def distance(self, other: Self) -> int:
+ return abs(self.x - other.x) + abs(self.y - other.y)
+
+ def __add__(self, other: Self) -> Self:
+ return self.__class__(self.x + other.x, self.y + other.y)
def offsets(length: int, present: set[int]) -> list[int]:
return list(accumulate(1 if i not in present else 0 for i in range(length)))
-def solve(
- points: set[tuple[int, int]],
- x_offsets: list[int],
- y_offsets: list[int],
- expansion: int = 2,
-) -> int:
- def offset(p: tuple[int, int]) -> tuple[int, int]:
- return (
- p[0] + x_offsets[p[0]] * (expansion - 1),
- p[1] + y_offsets[p[1]] * (expansion - 1),
- )
+def dists(points: Iterable[Point]) -> Iterator[int]:
+ return starmap(Point.distance, combinations(points, 2))
+
+
+def offsetter(
+ x_offsets: list[int], y_offsets: list[int], factor: int = 2
+) -> Callable[[Point], Point]:
+ scale = factor - 1
- def manhattan_distance(a: tuple[int, int], b: tuple[int, int]) -> int:
- return abs(a[0] - b[0]) + abs(a[1] - b[1])
+ def f(p: Point) -> Point:
+ return p + Point(x_offsets[p.x] * scale, y_offsets[p.y] * scale)
- return sum(
- manhattan_distance(offset(a), offset(b)) for a, b in combinations(points, 2)
- )
+ return f
-points = {(x, y) for y, l in enumerate(stdin) for x, c in enumerate(l) if c == "#"}
+points = {Point(x, y) for y, l in enumerate(stdin) for x, c in enumerate(l) if c == "#"}
-x_present, y_present = set(p[0] for p in points), set(p[1] for p in points)
+x_present, y_present = set(p.x for p in points), set(p.y for p in points)
width, height = max(x for x in x_present) + 1, max(y for y in y_present) + 1
x_offsets = offsets(width, x_present)
y_offsets = offsets(height, y_present)
-print(solve(points, x_offsets, y_offsets))
-print(solve(points, x_offsets, y_offsets, 1000000))
+print(sum(dists(map(offsetter(x_offsets, y_offsets), points))))
+print(sum(dists(map(offsetter(x_offsets, y_offsets, 1000000), points))))