use std::fs::File;
use std::collections::HashMap;
+use std::collections::HashSet;
pub fn run(input_file: &str) -> Result<(), Box<dyn Error>> {
let mut f = File::open(input_file)?;
let mut step = 0;
let mut i = 0;
- let mut found_ZZZ = false;
+ let mut found = false;
let mut node: String = String::from("AAA");
- while !found_ZZZ {
+ while node != "ZZZ" {
if i >= puzzle.instructions.len() {
i = 0;
}
};
node = new_node.to_string();
- if node == "ZZZ".to_string() {
- found_ZZZ = true;
- }
i += 1;
step += 1;
}
Ok(res)
}
-fn run_part2(input: &str) -> Result<u32, Box<dyn Error>> {
+fn factorize(a: u32) -> Vec<u32> {
+ let mut res: Vec<u32> = Vec::new();
+ let mut n = a;
+
+ let mut found = false;
+ while !found {
+ let s: f64 = (n as f64).sqrt().ceil();
+ let s: u32 = s as u32;
+ found = s == 1;
+ for i in 2..=s {
+ if n % i == 0 {
+ res.push(i);
+ n /= i;
+ break;
+ }
+ if i == s {
+ res.push(n);
+ found = true;
+ }
+ }
+ }
+ res
+}
+
+fn run_part2(input: &str) -> Result<u64, Box<dyn Error>> {
println!("Running day08 - part 2");
- let res = 0;
+ let puzzle = Puzzle::new(input);
+
+ // on commence aux nœuds qui finissent par 'A' et on cherche à rejoindre
+ // les nœuds qui finissent par 'Z'
+ //
+ // 1. récupérer le nombre d'étape de chaque chemin
+ // 2. calculer le PPCM de ces nombres d'étapes
+ //
+ // PPCM(a,b,c) = PPCM(PPCM(a,b),c)
+ //
+ // Calcul du PPCM(a,b)
+ // 1. décomposer a et b en facteur premier
+ // 2. le PPCM est égal au produit des facteurs communs et des facteurs non communs
+
+ let start_node: Vec<_> = puzzle.nodes.keys()
+ .filter(|k| k.ends_with('A'))
+ .collect();
+
+ // récupération de la longueur de chaque chemin
+ let steps: Vec<_> = start_node.into_iter()
+ .map(|n| {
+ let mut node = n;
+ let mut i = 0;
+ let mut step = 0;
+ while !node.ends_with('Z') {
+ if i >= puzzle.instructions.len() {
+ i = 0;
+ }
+
+ let new_node = match puzzle.instructions[i] {
+ 'L' => &puzzle.nodes.get(node).unwrap().0,
+ 'R' => &puzzle.nodes.get(node).unwrap().1,
+ _ => unreachable!(),
+ };
+
+ node = new_node;
+ i += 1;
+ step += 1;
+ }
+ step
+ })
+ .collect();
+
+ // décomposition en facteur premier
+ // et on ne conserve chaque facteur qu'une unique fois
+ let mut factor: HashSet<u32> = HashSet::new();
+ steps.into_iter()
+ .for_each(|s| {
+ let f = factorize(s);
+ f.into_iter().for_each(|v| { factor.insert(v); });
+ });
+
+ let res = factor.into_iter()
+ .map(|v| v as u64)
+ .product();
Ok(res)
}
mod tests {
use super::*;
- static TEXT_INPUT: &str = "";
-
#[test]
fn day08_part1_example1() {
let input = "\
#[test]
fn day08_part2() {
- let res = run_part2(TEXT_INPUT);
- assert_eq!(0, res.unwrap());
+ let input = "\
+LR
+
+11A = (11B, XXX)
+11B = (XXX, 11Z)
+11Z = (11B, XXX)
+22A = (22B, XXX)
+22B = (22C, 22C)
+22C = (22Z, 22Z)
+22Z = (22B, 22B)
+XXX = (XXX, XXX)";
+
+ let res = run_part2(&input);
+ assert_eq!(6, res.unwrap());
+ }
+
+ #[test]
+ fn test_factorize() {
+ assert_eq!(factorize(2), [2]);
+ assert_eq!(factorize(3), [3]);
+ assert_eq!(factorize(5), [5]);
+ assert_eq!(factorize(7), [7]);
+ assert_eq!(factorize(4), [2,2]);
+ assert_eq!(factorize(9), [3,3]);
+ assert_eq!(factorize(10), [2,5]);
+ assert_eq!(factorize(32), [2,2,2,2,2]);
}
}