Day 11 complete
This commit is contained in:
parent
86fdab567f
commit
0f233f8324
1 changed files with 101 additions and 37 deletions
138
aoc/day11.py
138
aoc/day11.py
|
@ -1,66 +1,130 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from array import array
|
||||
from collections.abc import Iterable
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .aoc import Aoc2, AocSameParser
|
||||
|
||||
|
||||
@dataclass
|
||||
class Position:
|
||||
x: int
|
||||
y: int
|
||||
|
||||
def __add__(self, other: Position) -> Position:
|
||||
return Position(self.x + other.x, self.y + other.y)
|
||||
|
||||
def __sub__(self, other: Position) -> Position:
|
||||
return Position(self.x - other.x, self.y - other.y)
|
||||
|
||||
def __or__(self, other: Position) -> int:
|
||||
return abs(self.x - other.x) + abs(self.y - other.y)
|
||||
|
||||
def __rmul__(self, other: int) -> Position:
|
||||
return Position(other * self.x, other * self.y)
|
||||
|
||||
def __getitem__(self, pi: int) -> int:
|
||||
if pi == 0:
|
||||
return self.x
|
||||
return self.y
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"[{self.x},{self.y}]"
|
||||
|
||||
|
||||
class Matrix:
|
||||
def __init__(self, inpt: str) -> None:
|
||||
lines = inpt.splitlines()
|
||||
self.height = len(lines)
|
||||
self.width = len(lines[0])
|
||||
self.array = array("u")
|
||||
for line in lines:
|
||||
self.array.fromlist(list(line))
|
||||
|
||||
def __getitem__(self, pos: Position | tuple[int, int]) -> str:
|
||||
return self.array[self.width * pos[1] + pos[0]]
|
||||
|
||||
def __setitem__(self, pos: Position | tuple[int, int], value: str) -> None:
|
||||
self.array[self.width * pos[1] + pos[0]] = value
|
||||
|
||||
def get_row(self, row_no: int) -> array[str]:
|
||||
return self.array[self.width * row_no : self.width * (row_no + 1)]
|
||||
|
||||
def iter_rows(self) -> Iterable[array[str]]:
|
||||
return (self.get_row(y) for y in range(self.height))
|
||||
|
||||
def get_col(self, col_no: int) -> array[str]:
|
||||
return array("u", [self[col_no, y] for y in range(self.height)])
|
||||
|
||||
def iter_cols(self) -> Iterable[array[str]]:
|
||||
return (self.get_col(x) for x in range(self.width))
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "\n".join((x.tounicode() for x in self.iter_rows()))
|
||||
|
||||
def finditer(self, element: str) -> Iterable[Position]:
|
||||
for y, line in enumerate(self.iter_rows()):
|
||||
for x, char in enumerate(line):
|
||||
if char == element:
|
||||
yield Position(x, y)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Map:
|
||||
galaxies: list[tuple[int, int]]
|
||||
map: Matrix
|
||||
galaxies: list[Position]
|
||||
adjusted_galaxies: list[Position]
|
||||
large_adjusted_galaxies: list[Position]
|
||||
|
||||
@classmethod
|
||||
def from_input(cls, inpt: str) -> Map:
|
||||
lines = inpt.splitlines()
|
||||
matrix = Matrix(inpt)
|
||||
|
||||
galaxies = []
|
||||
|
||||
for y, line in enumerate(lines):
|
||||
for x, char in enumerate(line):
|
||||
if char == "#":
|
||||
galaxies.append((x, y))
|
||||
|
||||
print(galaxies)
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
missing_ys = []
|
||||
missing_xs = []
|
||||
|
||||
for y in range(height):
|
||||
if y not in (y for (_, y) in galaxies):
|
||||
missing_ys.append(y)
|
||||
|
||||
for x in range(width):
|
||||
if x not in (x for (x, _) in galaxies):
|
||||
missing_xs.append(x)
|
||||
|
||||
print(missing_xs)
|
||||
print(missing_ys)
|
||||
galaxies = list(matrix.finditer("#"))
|
||||
missing_ys = [
|
||||
y for y, row in enumerate(matrix.iter_rows()) if row.count("#") == 0
|
||||
]
|
||||
missing_xs = [
|
||||
x for x, col in enumerate(matrix.iter_cols()) if col.count("#") == 0
|
||||
]
|
||||
|
||||
adjusted_galaxies = []
|
||||
large_adjusted_galaxies = []
|
||||
|
||||
for x, y in galaxies:
|
||||
x_offset = len([m for m in missing_xs if m < x])
|
||||
y_offset = len([m for m in missing_ys if m < y])
|
||||
adjusted_galaxies.append((x + x_offset, y + y_offset))
|
||||
for pos in galaxies:
|
||||
offset = Position(
|
||||
len([m for m in missing_xs if m < pos.x]),
|
||||
len([m for m in missing_ys if m < pos.y]),
|
||||
)
|
||||
adjusted_galaxies.append(pos + offset)
|
||||
large_adjusted_galaxies.append(pos + 999_999 * offset)
|
||||
|
||||
return cls(galaxies)
|
||||
return cls(matrix, galaxies, adjusted_galaxies, large_adjusted_galaxies)
|
||||
|
||||
|
||||
class Day11(AocSameParser[Map], Aoc2[Map, Map]):
|
||||
def parseinput(self, inpt: str) -> Map:
|
||||
return Map.from_input(inpt)
|
||||
|
||||
def part1(self, inpt: Map) -> None:
|
||||
print(inpt)
|
||||
def part1(self, inpt: Map) -> int:
|
||||
return sum(
|
||||
g1 | g2
|
||||
for i, g1 in enumerate(inpt.adjusted_galaxies)
|
||||
for g2 in inpt.adjusted_galaxies[i + 1 :]
|
||||
)
|
||||
|
||||
def part2(self, inpt: Map) -> None:
|
||||
print(inpt)
|
||||
def part2(self, inpt: Map) -> int:
|
||||
return sum(
|
||||
g1 | g2
|
||||
for i, g1 in enumerate(inpt.large_adjusted_galaxies)
|
||||
for g2 in inpt.large_adjusted_galaxies[i + 1 :]
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
day11 = Day11(2023, 11)
|
||||
day11.run_example_1()
|
||||
day11.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
Loading…
Add table
Reference in a new issue