Solve day8
This commit is contained in:
1000
day8/input.txt
Normal file
1000
day8/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
61
day8/part1.py
Normal file
61
day8/part1.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
from functools import reduce
|
||||||
|
from math import prod, sqrt
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TypeAlias
|
||||||
|
|
||||||
|
Point: TypeAlias = tuple[int, int, int]
|
||||||
|
|
||||||
|
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}))
|
||||||
|
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
|
||||||
|
)
|
||||||
|
return prod(len(c.points) for c in circuits[:3])
|
||||||
|
|
||||||
|
|
||||||
|
def distance(p1: tuple[int, int, int], p2: tuple[int, int, int]):
|
||||||
|
x1, y1, z1 = p1
|
||||||
|
x2, y2, z2 = p2
|
||||||
|
return sqrt((x2-x1)**2+(y2-y1)**2+(z2-z1)**2)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_point(line: str) -> Point:
|
||||||
|
x, y, z = line.split(",")
|
||||||
|
return (int(x), int(y), int(z))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(main())
|
||||||
63
day8/part2.py
Normal file
63
day8/part2.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
from functools import reduce
|
||||||
|
from math import prod, sqrt
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TypeAlias
|
||||||
|
|
||||||
|
Point: TypeAlias = tuple[int, int, int]
|
||||||
|
|
||||||
|
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}))
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
def distance(p1: tuple[int, int, int], p2: tuple[int, int, int]):
|
||||||
|
x1, y1, z1 = p1
|
||||||
|
x2, y2, z2 = p2
|
||||||
|
return sqrt((x2-x1)**2+(y2-y1)**2+(z2-z1)**2)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_point(line: str) -> Point:
|
||||||
|
x, y, z = line.split(",")
|
||||||
|
return (int(x), int(y), int(z))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(main())
|
||||||
20
day8/test.txt
Normal file
20
day8/test.txt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
162,817,812
|
||||||
|
57,618,57
|
||||||
|
906,360,560
|
||||||
|
592,479,940
|
||||||
|
352,342,300
|
||||||
|
466,668,158
|
||||||
|
542,29,236
|
||||||
|
431,825,988
|
||||||
|
739,650,466
|
||||||
|
52,470,668
|
||||||
|
216,146,977
|
||||||
|
819,987,18
|
||||||
|
117,168,530
|
||||||
|
805,96,715
|
||||||
|
346,949,466
|
||||||
|
970,615,88
|
||||||
|
941,993,340
|
||||||
|
862,61,35
|
||||||
|
984,92,344
|
||||||
|
425,690,689
|
||||||
Reference in New Issue
Block a user