diff --git a/day8/part1.py b/day8/part1.py index b2513d4..8c2727d 100644 --- a/day8/part1.py +++ b/day8/part1.py @@ -1,49 +1,33 @@ -from functools import reduce from math import prod, sqrt from pathlib import Path from typing import TypeAlias Point: TypeAlias = tuple[int, int, int] +Circuit: TypeAlias = set[Point] FILE = "input.txt" -class Circuit: - def __init__(self, points: set[Point]) -> None: - self.points: set[Point] = points - - def __contains__(self, other: Circuit) -> bool: - for p in other.points: - if p in self.points: return True - return False - - def merge(self, other: Circuit) -> Circuit: - return Circuit(self.points.union(other.points)) - def main(): lines = Path(FILE).read_text().splitlines() points: list[Point] = [parse_point(line) for line in lines] distances = sorted([ - (distance(p1, p2), Circuit({p1, p2})) + (distance(p1, p2), Circuit([p1, p2])) for i, p1 in enumerate(points) for p2 in points[i+1:] ], key=lambda x: x[0]) - big_circuits: list[Circuit] = [] - for (_, small_circuit) in distances[:1000]: - new_circuits: list[Circuit] = [] - for big_circuit in big_circuits: - if small_circuit in big_circuit: - new_circuits.append(big_circuit) - if len(new_circuits): - for circuit in new_circuits: big_circuits.remove(circuit) - new_circuits.append(small_circuit) - new_circuit = reduce(lambda a, b: a.merge(b), new_circuits) - big_circuits.append(new_circuit) - else: - big_circuits.append(small_circuit) - circuits = sorted( - big_circuits, key=lambda x: len(x.points), reverse=True + all: list[Circuit] = [] + for (_, circuit) in distances[:1000]: + connected = [ + a + for a in all + if circuit & a + ] + all = [a for a in all if a not in connected] + all.append(Circuit.union(circuit, *connected)) + all = sorted( + all, key=lambda x: len(x), reverse=True ) - return prod(len(c.points) for c in circuits[:3]) + return prod(len(c) for c in all[:3]) def distance(p1: tuple[int, int, int], p2: tuple[int, int, int]): diff --git a/day8/part2.py b/day8/part2.py index d7c86c0..2a3e968 100644 --- a/day8/part2.py +++ b/day8/part2.py @@ -1,51 +1,41 @@ -from functools import reduce from math import prod, sqrt from pathlib import Path from typing import TypeAlias Point: TypeAlias = tuple[int, int, int] +Circuit: TypeAlias = set[Point] FILE = "input.txt" -class Circuit: - def __init__(self, points: set[Point]) -> None: - self.points: set[Point] = points - - def __contains__(self, other: Circuit) -> bool: - for p in other.points: - if p in self.points: return True - return False - - def merge(self, other: Circuit) -> Circuit: - return Circuit(self.points.union(other.points)) - def main(): lines = Path(FILE).read_text().splitlines() points: list[Point] = [parse_point(line) for line in lines] distances = sorted([ - (distance(p1, p2), Circuit({p1, p2})) + (distance(p1, p2), Circuit([p1, p2])) for i, p1 in enumerate(points) for p2 in points[i+1:] ], key=lambda x: x[0]) - big_circuits: list[Circuit] = [] - last = None - for (_, small_circuit) in distances: - last = small_circuit - new_circuits: list[Circuit] = [] - for big_circuit in big_circuits: - if small_circuit in big_circuit: - new_circuits.append(big_circuit) - if len(new_circuits): - for circuit in new_circuits: big_circuits.remove(circuit) - new_circuits.append(small_circuit) - new_circuit = reduce(lambda a, b: a.merge(b), new_circuits) - big_circuits.append(new_circuit) - else: - big_circuits.append(small_circuit) - if len(big_circuits) == 1 and len(big_circuits[0].points) == len(points): - break - assert last is not None - return prod(p[0] for p in last.points) + return prod( + p[0] + for p in last_circuit( + [c for _, c in distances], len(points) + ) + ) + + +def last_circuit(circuits: list[Circuit], total: int) -> Circuit: + all: list[Circuit] = [] + for circuit in circuits: + connected = [ + a + for a in all + if circuit & a + ] + all = [a for a in all if a not in connected] + all.append(Circuit.union(circuit, *connected)) + if len(all) == 1 and len(all[0]) == total: + return circuit + assert False, "unreachable" def distance(p1: tuple[int, int, int], p2: tuple[int, int, int]):