]> aoc.elinar.fr Git - aoc_2025/commitdiff
day08: part1
authoralex <>
Mon, 8 Dec 2025 17:56:02 +0000 (18:56 +0100)
committeralex <>
Mon, 8 Dec 2025 17:56:02 +0000 (18:56 +0100)
src/day08.rs [new file with mode: 0644]
src/main.rs

diff --git a/src/day08.rs b/src/day08.rs
new file mode 100644 (file)
index 0000000..cdd2abb
--- /dev/null
@@ -0,0 +1,137 @@
+use std::error::Error;
+use std::collections::HashSet;
+
+#[derive(Copy,Clone,Debug)]
+struct Coord {
+    x: i64,
+    y: i64,
+    z: i64,
+}
+
+impl Coord {
+    fn new(x: i64, y: i64, z: i64) -> Self {
+        Self { x, y, z }
+    }
+
+    // Euclidean distance (not square rooted)
+    fn dst(&self, other: Self) -> i64 {
+        (self.x - other.x).pow(2) + (self.y - other.y).pow(2) + (self.z - other.z).pow(2)
+    }
+}
+
+struct Puzzle {
+    boxes: Vec<Coord>,
+}
+
+impl Puzzle {
+    fn new(input: &str) -> Self {
+        let boxes = input.lines()
+            .map(|l| {
+                let coord: Vec<i64> = l.split(',')
+                    .map(|v| v.parse::<i64>().unwrap())
+                    .collect();
+                Coord::new(coord[0], coord[1], coord[2])
+            })
+            .collect();
+        Self { boxes }
+    }
+
+    fn part1(&self, n_shortest: usize) -> usize {
+        let mut connections: Vec<(i64, (usize, usize))> = Vec::new();
+        for i in 0..self.boxes.len() {
+            for j in (i+1)..self.boxes.len() {
+                connections.push((self.boxes[i].dst(self.boxes[j]), (i, j)));
+            }
+        }
+        connections.sort_by(|a, b| a.0.cmp(&b.0));
+
+        let mut connections: Vec<(usize, usize)> = connections.into_iter()
+            .take(n_shortest)
+            .map(|(_, coord)| coord)
+            .collect();
+        connections.sort();
+
+        let mut circuits: Vec<HashSet<usize>> = Vec::new();
+        connections.iter()
+            .for_each(|(b1, b2)| {
+                if let Some(i) = circuits.iter().position(|s| s.contains(b1)) {
+                    if let Some(j) = circuits.iter().position(|s| s.contains(b2)) {
+                        circuits.push( circuits[i].union(&circuits[j]).map(|v| *v).collect() );
+                        circuits.remove(i.max(j));
+                        if i != j {
+                            circuits.remove(i.min(j));
+                        }
+                    } else {
+                        circuits[i].insert(*b2);
+                    }
+                } else if let Some(i) = circuits.iter().position(|s| s.contains(b2)) {
+                    if let Some(j) = circuits.iter().position(|s| s.contains(b1)) {
+                        circuits.push( circuits[i].union(&circuits[j]).map(|v| *v).collect() );
+                        circuits.remove(i.max(j));
+                        if i != j {
+                            circuits.remove(i.min(j));
+                        }
+                    } else {
+                        circuits[i].insert(*b1);
+                    }
+                } else {
+                    let mut s: HashSet<usize> = HashSet::new();
+                    s.insert(*b1);
+                    s.insert(*b2);
+                    circuits.push(s);
+                }
+                circuits.sort_by(|a, b| b.len().cmp(&a.len()));
+                // si b1 est dans un set de circuits
+                //      - si b2 est dans un set de circuits
+                //          -> relier les sets
+                //      - sinon ajouter b2 au set
+                // si b2 est déjà dans un set de circuits
+                //      - si b1 est dans un set de circuits
+                //          -> relier les sets
+                //      - sinon ajouter b1 au set
+                // sinon ajouter set (b1, b2)
+            });
+        let mut circuits: Vec<usize> = circuits.iter().map(|set| set.len()).collect();
+        circuits.sort_by(|a, b| b.cmp(a));
+        circuits.iter().take(3).product()
+    }
+}
+
+pub fn run(input: &str) -> Result<(), Box<dyn Error>> {
+    let p = Puzzle::new(input);
+    println!("part1: {}", p.part1(1000));
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    static TEST_INPUT: &str = "\
+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
+";
+
+    #[test]
+    fn test_part1() {
+        assert_eq!(40, Puzzle::new(TEST_INPUT).part1(10));
+    }
+}
index 8cb86b2fd12930a8398ef974621af7be7234a338..cbdd4554b53cbcc6c1c6a4fe2d48fa122a7e95db 100644 (file)
@@ -11,6 +11,7 @@ pub mod day04;
 pub mod day05;
 pub mod day06;
 pub mod day07;
+pub mod day08;
 
 fn main() {
     let args: Vec<String> = env::args().collect();
@@ -33,6 +34,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box<dyn Error>> {
         "day05" => day05::run(&input)?,
         "day06" => day06::run(&input)?,
         "day07" => day07::run(&input)?,
+        "day08" => day08::run(&input)?,
         _ => return Err(format!("unknown or unimplemented day \"{day}\"").into()),
     }
     Ok(())