108 lines
2.5 KiB
Python
108 lines
2.5 KiB
Python
import itertools
|
|
import math
|
|
|
|
def single_circuit(circuits, num_junctions):
|
|
for circuit in circuits:
|
|
if len(circuit) == num_junctions:
|
|
return True
|
|
return False
|
|
|
|
|
|
def get_circuit(a,circuits):
|
|
if len(circuits) == 0:
|
|
return None
|
|
|
|
for circ in circuits:
|
|
for pos in circ:
|
|
if pos == a:
|
|
return circ
|
|
return None
|
|
|
|
def add_circuit(a,b,circuits):
|
|
circ_a = get_circuit(a,circuits)
|
|
circ_b = get_circuit(b,circuits)
|
|
|
|
if circ_a is None and circ_b is None:
|
|
circuits.append([a,b])
|
|
return True
|
|
|
|
if circ_a is None and not circ_b is None:
|
|
circ_b.append(a)
|
|
return True
|
|
|
|
if not circ_a is None and circ_b is None:
|
|
circ_a.append(b)
|
|
return True
|
|
|
|
if not circ_a is None and not circ_b is None:
|
|
if circ_a == circ_b:
|
|
# Already part of same circuit
|
|
return True
|
|
else:
|
|
# Merge circuits...
|
|
# Copy a to b
|
|
for circ in circ_a:
|
|
circ_b.append(circ)
|
|
|
|
# Empty a
|
|
for _ in range(0, len(circ_a)):
|
|
circ_a.pop()
|
|
return True
|
|
|
|
def get_lowest_distance(junctions_distance, infinite=99999):
|
|
a,b,_ = junctions_distance.pop()
|
|
return a,b
|
|
|
|
|
|
def distance(a,b):
|
|
# https://en.wikipedia.org/wiki/Euclidean_distance
|
|
return math.sqrt( pow((a[0]-b[0]),2) + pow((a[1]-b[1]),2) + pow((a[2]-b[2]),2) )
|
|
|
|
def read_input(filename):
|
|
space = []
|
|
for line in open(filename).read().splitlines():
|
|
x,y,z = line.split(",")
|
|
space.append((int(x), int(y), int(z)))
|
|
return space
|
|
|
|
|
|
# filename = "day08/example_input" # 25272
|
|
filename = "day08/input" # 274150525
|
|
|
|
junctions = read_input(filename)
|
|
|
|
# build list of (unique) combinations
|
|
junctions_comb = itertools.combinations(junctions,2)
|
|
|
|
print("Calculate distances")
|
|
# Add distance to the list
|
|
junctions_distance = []
|
|
for a,b in junctions_comb:
|
|
dist = distance(a,b)
|
|
junctions_distance.append((a,b,dist))
|
|
|
|
# Sort distance list, reversed as then "pop()" will get/remove the shortest distance
|
|
def jd_sort(junc_dist):
|
|
return junc_dist[2]
|
|
junctions_distance.sort(key=jd_sort, reverse=True)
|
|
|
|
|
|
circuits = []
|
|
connections = 0
|
|
dist = 0
|
|
print("Make connections")
|
|
while True:
|
|
a,b = get_lowest_distance(junctions_distance)
|
|
|
|
if add_circuit(a,b,circuits):
|
|
connections += 1
|
|
|
|
if single_circuit(circuits, len(junctions)):
|
|
dist = a[0] * b[0]
|
|
break
|
|
|
|
if connections % 1000 == 0:
|
|
print(f"Connections: {connections}")
|
|
|
|
print(f"Distance junction boxes: {dist}")
|