diff --git a/src/common.rs b/src/common.rs index 2b00da5..787a2c9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1 +1,2 @@ +pub mod geometry; pub mod interval; diff --git a/src/common/geometry.rs b/src/common/geometry.rs new file mode 100644 index 0000000..1fc359b --- /dev/null +++ b/src/common/geometry.rs @@ -0,0 +1,10 @@ +#[derive(Hash, PartialEq, Eq)] +pub struct Point3(pub u64, pub u64, pub u64); + +impl Point3 { + pub fn distance_sqr(&self, other: &Self) -> u64 { + self.0.abs_diff(other.0).pow(2) + + self.1.abs_diff(other.1).pow(2) + + self.2.abs_diff(other.2).pow(2) + } +} diff --git a/src/solvers/playground.rs b/src/solvers/playground.rs index b6962a8..a244b75 100644 --- a/src/solvers/playground.rs +++ b/src/solvers/playground.rs @@ -1,3 +1,4 @@ +use crate::common::geometry::Point3; use crate::solvers::Solver; use std::collections::{BTreeMap, HashSet}; use std::io::BufRead; @@ -7,6 +8,8 @@ pub struct Playground { } impl Playground { + const CIRCUITS_TAKE: usize = 3; + pub fn new(connections: Option) -> Playground { Playground { connections: connections.unwrap_or(1000), @@ -14,11 +17,11 @@ impl Playground { } // Collects all junction box coordinates. - fn junction_boxes(reader: R) -> Vec<(u64, u64, u64)> { + fn junction_boxes(reader: R) -> Vec { let mut junction_boxes = Vec::new(); for line in reader.lines().map_while(Result::ok) { let j: Vec = line.split(',').map(|s| s.parse().unwrap()).collect(); - junction_boxes.push((j[0], j[1], j[2])); + junction_boxes.push(Point3(j[0], j[1], j[2])); } junction_boxes } @@ -27,13 +30,13 @@ impl Playground { // connections. fn distances<'a>( &self, - junction_boxes: &'a Vec<(u64, u64, u64)>, - ) -> BTreeMap { + junction_boxes: &'a Vec, + ) -> BTreeMap { let mut distances = BTreeMap::new(); for i in 0..junction_boxes.len() { let (_, right) = junction_boxes.split_at(i + 1); for b in right { - let d = Self::distance_sqr(&junction_boxes[i], b); + let d = junction_boxes[i].distance_sqr(b); distances.insert(d, (&junction_boxes[i], b)); if distances.len() > self.connections { distances.pop_last(); @@ -43,8 +46,9 @@ impl Playground { distances } - fn circuit_sizes(distances: &BTreeMap) -> u64 { - let mut circuits: Vec> = Vec::new(); + // Aggregates all circuits and returns the product of the sizes of the 3 largest ones. + fn circuit_sizes(distances: &BTreeMap) -> u64 { + let mut circuits: Vec> = Vec::new(); for junction_boxes in distances.values() { let index_a = circuits.iter().position(|c| c.contains(&junction_boxes.0)); let index_b = circuits.iter().position(|c| c.contains(&junction_boxes.1)); @@ -74,11 +78,11 @@ impl Playground { } } circuits.sort_by(|a, b| b.len().cmp(&a.len())); - circuits.iter().take(3).map(|c| c.len() as u64).product() - } - - fn distance_sqr(a: &(u64, u64, u64), b: &(u64, u64, u64)) -> u64 { - a.0.abs_diff(b.0).pow(2) + a.1.abs_diff(b.1).pow(2) + a.2.abs_diff(b.2).pow(2) + circuits + .iter() + .take(Self::CIRCUITS_TAKE) + .map(|c| c.len() as u64) + .product() } }