day 8 part 2 multi-threaded bruteforce attempt

This commit is contained in:
Dominic 2023-12-08 21:28:48 +01:00
parent 1c8b2b3179
commit 40b252e393
Signed by: msrd0
GPG key ID: DCC8C247452E98F9

View file

@ -1,9 +1,18 @@
#![forbid(elided_lifetimes_in_paths, unsafe_code)] #![forbid(elided_lifetimes_in_paths)]
use aoc23::read; use aoc23::read;
use chumsky::prelude::*; 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 { enum Instruction {
Left, Left,
Right Right
@ -18,7 +27,7 @@ impl Instruction {
} }
} }
#[derive(Debug)] #[derive(Clone, Debug)]
struct Node { struct Node {
left: String, left: String,
right: String right: String
@ -42,7 +51,7 @@ impl Node {
} }
} }
#[derive(Debug)] #[derive(Clone, Debug)]
struct Network { struct Network {
nodes: HashMap<String, Node> nodes: HashMap<String, Node>
} }
@ -83,46 +92,103 @@ fn parser() -> impl Parser<char, (Vec<Instruction>, Network), Error = Simple<cha
.then_ignore(end()) .then_ignore(end())
} }
static STOP: AtomicBool = AtomicBool::new(false);
static mut RESULTS: Vec<Mutex<Vec<usize>>> = Vec::new();
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let (instructions, network) = read("inputs/day8.txt", parser())?; let (instructions, network) = read("inputs/day8.txt", parser())?;
let mut curr_node = "AAA"; // let mut curr_node = "AAA";
let mut i = 0; // let mut i = 0;
let mut steps = 0; // let mut steps = 0;
while curr_node != "ZZZ" { // while curr_node != "ZZZ" {
curr_node = match instructions[i] { // curr_node = match instructions[i] {
Instruction::Left => network.left(curr_node), // Instruction::Left => network.left(curr_node),
Instruction::Right => network.right(curr_node) // Instruction::Right => network.right(curr_node)
}; // };
i = (i + 1) % instructions.len(); // i = (i + 1) % instructions.len();
steps += 1; // steps += 1;
} // }
println!("{steps}"); // println!("{steps}");
let mut curr_nodes: HashSet<&str> = network let curr_nodes: HashSet<&str> = network
.nodes .nodes
.keys() .keys()
.map(|node| node.as_str()) .map(|node| node.as_str())
.filter(|node| node.ends_with('A')) .filter(|node| node.ends_with('A'))
.collect(); .collect();
dbg!(curr_nodes.len()); dbg!(curr_nodes.len());
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 i = 0;
let mut steps = 0; let mut steps = 0;
while curr_nodes.iter().any(|node| !node.ends_with('Z')) { while !STOP.load(Ordering::Relaxed) {
curr_nodes = curr_nodes curr_node = match instructions[i] {
.into_iter() Instruction::Left => network.left(curr_node),
.map(|node| match instructions[i] { Instruction::Right => network.right(curr_node)
Instruction::Left => network.left(node), };
Instruction::Right => network.right(node)
})
.collect();
i = (i + 1) % instructions.len(); i = (i + 1) % instructions.len();
steps += 1; steps += 1;
if steps % 10000 == 0 { if steps % 1_000_000 == 0 {
dbg!(steps); dbg!(steps);
} }
if curr_node.ends_with('Z') {
unsafe {
RESULTS[thread_index].lock().unwrap().push(steps);
} }
println!("{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;
}
}
}
// 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(()) Ok(())
} }