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 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<String, Node>
}
@ -83,46 +92,103 @@ fn parser() -> impl Parser<char, (Vec<Instruction>, Network), Error = Simple<cha
.then_ignore(end())
}
static STOP: AtomicBool = AtomicBool::new(false);
static mut RESULTS: Vec<Mutex<Vec<usize>>> = 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(())
}