day 8 part 2 multi-threaded bruteforce attempt
This commit is contained in:
parent
1c8b2b3179
commit
40b252e393
1 changed files with 98 additions and 32 deletions
130
src/bin/day8.rs
130
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<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(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue