diff --git a/src/bin/day8.rs b/src/bin/day8.rs index 5423e2c..bc36ec3 100644 --- a/src/bin/day8.rs +++ b/src/bin/day8.rs @@ -1,9 +1,18 @@ -#![forbid(elided_lifetimes_in_paths, unsafe_code)] +#![forbid(elided_lifetimes_in_paths)] use aoc23::read; use chumsky::prelude::*; -use std::collections::{HashMap, HashSet}; +use std::{ + collections::{HashMap, HashSet}, + sync::{ + atomic::{AtomicBool, Ordering}, + Mutex + }, + thread, + time::Duration +}; +#[derive(Clone, Copy, Debug)] enum Instruction { Left, Right @@ -18,7 +27,7 @@ impl Instruction { } } -#[derive(Debug)] +#[derive(Clone, Debug)] struct Node { left: String, right: String @@ -42,7 +51,7 @@ impl Node { } } -#[derive(Debug)] +#[derive(Clone, Debug)] struct Network { nodes: HashMap } @@ -83,46 +92,103 @@ fn parser() -> impl Parser, Network), Error = Simple>> = Vec::new(); + fn main() -> anyhow::Result<()> { let (instructions, network) = read("inputs/day8.txt", parser())?; - let mut curr_node = "AAA"; - let mut i = 0; - let mut steps = 0; - while curr_node != "ZZZ" { - curr_node = match instructions[i] { - Instruction::Left => network.left(curr_node), - Instruction::Right => network.right(curr_node) - }; - i = (i + 1) % instructions.len(); - steps += 1; - } - println!("{steps}"); + // let mut curr_node = "AAA"; + // let mut i = 0; + // let mut steps = 0; + // while curr_node != "ZZZ" { + // curr_node = match instructions[i] { + // Instruction::Left => network.left(curr_node), + // Instruction::Right => network.right(curr_node) + // }; + // i = (i + 1) % instructions.len(); + // steps += 1; + // } + // println!("{steps}"); - let mut curr_nodes: HashSet<&str> = network + let curr_nodes: HashSet<&str> = network .nodes .keys() .map(|node| node.as_str()) .filter(|node| node.ends_with('A')) .collect(); dbg!(curr_nodes.len()); - let mut i = 0; - let mut steps = 0; - while curr_nodes.iter().any(|node| !node.ends_with('Z')) { - curr_nodes = curr_nodes - .into_iter() - .map(|node| match instructions[i] { - Instruction::Left => network.left(node), - Instruction::Right => network.right(node) - }) - .collect(); - i = (i + 1) % instructions.len(); - steps += 1; - if steps % 10000 == 0 { - dbg!(steps); + + for (thread_index, node) in curr_nodes + .iter() + .map(|node| String::from(*node)) + .enumerate() + { + unsafe { + RESULTS.push(Mutex::new(Vec::new())); + } + let network = network.clone(); + let instructions = instructions.clone(); + thread::spawn(move || { + let mut curr_node = node.as_str(); + let mut i = 0; + let mut steps = 0; + while !STOP.load(Ordering::Relaxed) { + curr_node = match instructions[i] { + Instruction::Left => network.left(curr_node), + Instruction::Right => network.right(curr_node) + }; + i = (i + 1) % instructions.len(); + steps += 1; + if steps % 1_000_000 == 0 { + dbg!(steps); + } + if curr_node.ends_with('Z') { + unsafe { + RESULTS[thread_index].lock().unwrap().push(steps); + } + } + } + }); + } + 'outer: loop { + thread::sleep(Duration::from_secs(1)); + unsafe { + let res0 = RESULTS[0].lock().unwrap(); + 'i: for i in 0 .. res0.len() { + 't: for t in 1 .. RESULTS.len() { + let rest = RESULTS[t].lock().unwrap(); + for j in 0 .. rest.len() { + if res0[i] == rest[j] { + continue 't; + } + } + continue 'i; + } + println!("{}", res0[i]); + STOP.store(true, Ordering::Relaxed); + break 'outer; + } } } - println!("{steps}"); + + // let mut i = 0; + // let mut steps = 0; + // while curr_nodes.iter().any(|node| !node.ends_with('Z')) { + // curr_nodes = curr_nodes + // .into_iter() + // .map(|node| match instructions[i] { + // Instruction::Left => network.left(node), + // Instruction::Right => network.right(node) + // }) + // .collect(); + // i = (i + 1) % instructions.len(); + // steps += 1; + // if steps % 10000 == 0 { + // dbg!(steps); + // } + // } + // println!("{steps}"); Ok(()) }