107 lines
3.7 KiB
Python
Executable file
107 lines
3.7 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
from logging import debug, DEBUG, basicConfig
|
|
from sys import argv
|
|
|
|
|
|
def parse_input(input_filepath: str) -> list[tuple[int, ...]]:
|
|
|
|
with open(file=input_filepath, mode="r") as input_file:
|
|
input_data: list[str] = input_file.readlines()
|
|
|
|
debug(f"RAW INPUT: {input_data}")
|
|
|
|
return [tuple(int(y) for y in x.split(",")) for x in input_data]
|
|
|
|
|
|
def get_distances(positions: list[tuple[int, ...]]) -> list[tuple[float, int, int]]:
|
|
distances: list[tuple[float, int, int]] = []
|
|
for a in range(len(positions)):
|
|
for b in range(a + 1, len(positions)):
|
|
distances.append(
|
|
(
|
|
pow(positions[a][0] - positions[b][0], 2)
|
|
+ pow(positions[a][1] - positions[b][1], 2)
|
|
+ pow(positions[a][2] - positions[b][2], 2),
|
|
a,
|
|
b,
|
|
)
|
|
)
|
|
distances.sort(key=lambda x: x[0])
|
|
return distances
|
|
|
|
|
|
def create_circuits(
|
|
distances: list[tuple[float, int, int]], n: int
|
|
) -> tuple[list[int], tuple[float, int, int]]:
|
|
single_circuits: list[int] = [x for x in range(n)]
|
|
circuits: list[set[int]] = []
|
|
count = 0
|
|
circuits_after_n: list[int] = []
|
|
for d in distances:
|
|
if count == 999:
|
|
circuits_after_n = [len(x) for x in circuits]
|
|
if len(single_circuits) == 0 and len(circuits) == 1:
|
|
break
|
|
count += 1
|
|
debug(f"Current Iteration: {count} | {d} | {circuits}")
|
|
a_in_single_circuits = d[1] in single_circuits
|
|
b_in_single_circuits = d[2] in single_circuits
|
|
if a_in_single_circuits or b_in_single_circuits:
|
|
if a_in_single_circuits and b_in_single_circuits:
|
|
circuits.append(set([d[1], d[2]]))
|
|
single_circuits.remove(d[1])
|
|
single_circuits.remove(d[2])
|
|
continue
|
|
for c in circuits:
|
|
if d[1] in c:
|
|
c.add(d[2])
|
|
single_circuits.remove(d[2])
|
|
break
|
|
if d[2] in c:
|
|
c.add(d[1])
|
|
single_circuits.remove(d[1])
|
|
break
|
|
continue
|
|
circuit_a = circuit_b = set()
|
|
for c in circuits:
|
|
if d[1] in c:
|
|
circuit_a = c
|
|
if d[2] in c:
|
|
circuit_b = c
|
|
if circuit_a == circuit_b:
|
|
continue
|
|
circuits.remove(circuit_a)
|
|
circuits.remove(circuit_b)
|
|
circuits.append(circuit_a.union(circuit_b))
|
|
return (circuits_after_n, distances[count - 1])
|
|
|
|
|
|
def main() -> None:
|
|
input_filepath = "input/junction_boxes.txt"
|
|
junction_boxes = parse_input(input_filepath)
|
|
distances = get_distances(junction_boxes)
|
|
debug(f"DISTANCES BETWEEN BOXES: {distances}")
|
|
circuits_after_n, final_distance = create_circuits(distances, len(junction_boxes))
|
|
debug(f"CIRCUITS CREATED AFTER 1000 ITERATIONS: {circuits_after_n}")
|
|
debug(
|
|
f"FINAL DISTANCE EXAMINED: {final_distance[0]} | {junction_boxes[final_distance[1]]} | {junction_boxes[final_distance[2]]}"
|
|
)
|
|
circuits_after_n.sort(reverse=True)
|
|
product_of_n_largest_circuits = (
|
|
circuits_after_n[0] * circuits_after_n[1] * circuits_after_n[2]
|
|
)
|
|
print(
|
|
f"The product of the three largest circuits after 1000 iterations is: {product_of_n_largest_circuits}"
|
|
)
|
|
print(
|
|
f"The product of the x coordinates of the last two junction boxes connected: {junction_boxes[final_distance[1]][0] * junction_boxes[final_distance[2]][0]}"
|
|
)
|
|
return
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if "-d" in argv or "--debug" in argv:
|
|
basicConfig(filename="debug.log", level=DEBUG)
|
|
main()
|
|
exit(0)
|