Prefer native types to classes

This commit is contained in:
2025-12-15 11:00:04 -08:00
parent 5a70dd3810
commit 8b702185fc
2 changed files with 37 additions and 63 deletions

View File

@@ -1,49 +1,33 @@
from functools import reduce
from math import prod, sqrt from math import prod, sqrt
from pathlib import Path from pathlib import Path
from typing import TypeAlias from typing import TypeAlias
Point: TypeAlias = tuple[int, int, int] Point: TypeAlias = tuple[int, int, int]
Circuit: TypeAlias = set[Point]
FILE = "input.txt" 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(): def main():
lines = Path(FILE).read_text().splitlines() lines = Path(FILE).read_text().splitlines()
points: list[Point] = [parse_point(line) for line in lines] points: list[Point] = [parse_point(line) for line in lines]
distances = sorted([ distances = sorted([
(distance(p1, p2), Circuit({p1, p2})) (distance(p1, p2), Circuit([p1, p2]))
for i, p1 in enumerate(points) for i, p1 in enumerate(points)
for p2 in points[i+1:] for p2 in points[i+1:]
], key=lambda x: x[0]) ], key=lambda x: x[0])
big_circuits: list[Circuit] = [] all: list[Circuit] = []
for (_, small_circuit) in distances[:1000]: for (_, circuit) in distances[:1000]:
new_circuits: list[Circuit] = [] connected = [
for big_circuit in big_circuits: a
if small_circuit in big_circuit: for a in all
new_circuits.append(big_circuit) if circuit & a
if len(new_circuits): ]
for circuit in new_circuits: big_circuits.remove(circuit) all = [a for a in all if a not in connected]
new_circuits.append(small_circuit) all.append(Circuit.union(circuit, *connected))
new_circuit = reduce(lambda a, b: a.merge(b), new_circuits) all = sorted(
big_circuits.append(new_circuit) all, key=lambda x: len(x), reverse=True
else:
big_circuits.append(small_circuit)
circuits = sorted(
big_circuits, key=lambda x: len(x.points), 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]): def distance(p1: tuple[int, int, int], p2: tuple[int, int, int]):

View File

@@ -1,51 +1,41 @@
from functools import reduce
from math import prod, sqrt from math import prod, sqrt
from pathlib import Path from pathlib import Path
from typing import TypeAlias from typing import TypeAlias
Point: TypeAlias = tuple[int, int, int] Point: TypeAlias = tuple[int, int, int]
Circuit: TypeAlias = set[Point]
FILE = "input.txt" 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(): def main():
lines = Path(FILE).read_text().splitlines() lines = Path(FILE).read_text().splitlines()
points: list[Point] = [parse_point(line) for line in lines] points: list[Point] = [parse_point(line) for line in lines]
distances = sorted([ distances = sorted([
(distance(p1, p2), Circuit({p1, p2})) (distance(p1, p2), Circuit([p1, p2]))
for i, p1 in enumerate(points) for i, p1 in enumerate(points)
for p2 in points[i+1:] for p2 in points[i+1:]
], key=lambda x: x[0]) ], key=lambda x: x[0])
big_circuits: list[Circuit] = [] return prod(
last = None p[0]
for (_, small_circuit) in distances: for p in last_circuit(
last = small_circuit [c for _, c in distances], len(points)
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): def last_circuit(circuits: list[Circuit], total: int) -> Circuit:
for circuit in new_circuits: big_circuits.remove(circuit) all: list[Circuit] = []
new_circuits.append(small_circuit) for circuit in circuits:
new_circuit = reduce(lambda a, b: a.merge(b), new_circuits) connected = [
big_circuits.append(new_circuit) a
else: for a in all
big_circuits.append(small_circuit) if circuit & a
if len(big_circuits) == 1 and len(big_circuits[0].points) == len(points): ]
break all = [a for a in all if a not in connected]
assert last is not None all.append(Circuit.union(circuit, *connected))
return prod(p[0] for p in last.points) 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]): def distance(p1: tuple[int, int, int], p2: tuple[int, int, int]):