Prefer native types to classes
This commit is contained in:
@@ -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]):
|
||||||
|
|||||||
@@ -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]):
|
||||||
|
|||||||
Reference in New Issue
Block a user