use std::{collections::HashSet, fs::read_to_string}; fn main() { let boxes: Vec> = read_to_string("../input.txt") .expect("failed to open input file") .lines() .map(|jbox| { jbox.split(',') .map(|coord| coord.parse().unwrap()) .collect() }) .collect(); let mut distances: Vec<(_, u64)> = boxes .iter() .enumerate() .flat_map(|(i, jbox)| { boxes.iter().enumerate().skip(i + 1).map(move |(j, other)| { ( (i, j), jbox.iter() .zip(other) .map(|(from, to)| from.abs_diff(*to).pow(2)) .sum(), ) }) }) .collect(); distances.sort_unstable_by_key(|(_, distance)| *distance); let mut circuits: Vec> = Vec::new(); for ((from, to), _) in distances.into_iter() { let from_idx = circuits.iter().position(|circuit| circuit.contains(&from)); let to_idx = circuits.iter().position(|circuit| circuit.contains(&to)); match (from_idx, to_idx) { (Some(from_idx), Some(to_idx)) if from_idx == to_idx => {} (Some(from_idx), Some(to_idx)) => { let to_circuit: Vec<_> = circuits[to_idx].drain().collect(); circuits[from_idx].extend(to_circuit); circuits.remove(to_idx); } (Some(from_idx), None) => { circuits[from_idx].insert(to); } (None, Some(to_idx)) => { circuits[to_idx].insert(from); } (None, None) => circuits.push(HashSet::from([from, to])), } if circuits[0].len() == boxes.len() { let result = boxes[from][0] * boxes[to][0]; println!( "The result of multiplying the x co-ordinates of the last two junction boxes is {result}!" ); break; } } }