diff --git a/.aoc_tiles/tiles/2024/23.png b/.aoc_tiles/tiles/2024/23.png index e8f4326..bc4cac9 100644 Binary files a/.aoc_tiles/tiles/2024/23.png and b/.aoc_tiles/tiles/2024/23.png differ diff --git a/README.md b/README.md index f23874d..c3d691c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- 2024 - 44 ⭐ - Rust + 2024 - 45 ⭐ - Rust

diff --git a/src/day23.rs b/src/day23.rs index 0dd08c8..8829984 100644 --- a/src/day23.rs +++ b/src/day23.rs @@ -1,13 +1,7 @@ -use std::{ - collections::VecDeque, - fmt::{Debug, Display}, -}; - use aoc_runner_derive::aoc; -use indicatif::{ParallelProgressIterator, ProgressBar, ProgressIterator}; use itertools::Itertools; -use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rustc_hash::{FxHashMap, FxHashSet}; +use std::fmt::{Debug, Display}; #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] struct Node([char; 2]); @@ -62,43 +56,37 @@ impl Network { } sets } - fn node_groups(&self, n: &Node, adjacent_set: FxHashSet) -> Option> { - // println!("{:?} {:?}", n, adjacent_set); - let neigh = FxHashSet::from_iter(self.edges.get(n).unwrap().iter().map(|n| *n)); - let intersection = FxHashSet::from_iter(adjacent_set.intersection(&neigh).map(|n| *n)); - if intersection != adjacent_set { - return Some(adjacent_set); + fn bron_kerbosch( + &self, + r: FxHashSet, + mut p: FxHashSet, + mut x: FxHashSet, + ) -> Vec> { + let mut results = Vec::new(); + if p.is_empty() && x.is_empty() { + return vec![r]; } - let mut next_adj_set = adjacent_set.clone(); - next_adj_set.insert(*n); - neigh - .iter() - .filter(|neigh_n| !next_adj_set.contains(neigh_n)) - .filter_map(|neigh_n| self.node_groups(neigh_n, next_adj_set.clone())) - .max_by(|a, b| a.len().cmp(&b.len())) - } - fn born_kerbosch(&self, r: FxHashSet, mut p: FxHashSet, mut x: FxHashSet) -> FxHashSet { - if p.is_empty() && r.is_empty() { - return r; - } - let p_iter = p.clone(); // se we can modify p + let p_iter = p.clone(); // so we can modify p for node in &p_iter { let mut new_r = r.clone(); new_r.insert(*node); - let new_p = FxHashSet::from_iter( - p.intersection(&FxHashSet::from_iter(self.edges.get(&node).unwrap().iter().map(|n| *n))) - .map(|n| *n), - ); - let new_x = FxHashSet::from_iter( - x.intersection(&FxHashSet::from_iter(self.edges.get(&node).unwrap().iter().map(|n| *n))) - .map(|n| *n), - ); - self.born_kerbosch(new_r, new_p, new_x); + let neighbours = FxHashSet::from_iter(self.edges.get(&node).unwrap().iter().map(|n| *n)); + let new_p = FxHashSet::from_iter(p.intersection(&neighbours).map(|n| *n)); + let new_x = FxHashSet::from_iter(x.intersection(&neighbours).map(|n| *n)); + + results.extend(self.bron_kerbosch(new_r, new_p, new_x).into_iter()); p.remove(&node); x.insert(*node); } - r + results + } + fn maximal_subgraphs(&self) -> Vec> { + self.bron_kerbosch( + FxHashSet::default(), + FxHashSet::from_iter(self.nodes.iter().map(|n| *n)), + FxHashSet::default(), + ) } } @@ -143,26 +131,12 @@ pub fn part1(input: &str) -> i64 { #[aoc(day23, part2)] pub fn part2(input: &str) -> String { let network = parse(input); - let mut best = FxHashSet::default(); - let mut node_queue = network.nodes.clone(); - let progress = ProgressBar::new(network.nodes.len() as u64); - while let Some(node) = node_queue.pop() { - progress.inc(1); - let net = network.node_groups(&node, FxHashSet::default()).unwrap(); - println!("NODE {} best: {:?}", node, net); - for checked in &net { - if let Some(idx) = node_queue.iter().position(|to_remove| to_remove == checked) { - node_queue.remove(idx); - progress.inc(1); - } - } - if net.len() > best.len() { - best = net; - } - } - // println!("{:?}", network.node_groups(&Node(['k', 'a']), FxHashSet::default())); - println!("best: {:?}", best); - String::new() + let best_sets = network.maximal_subgraphs(); + let largest_set = best_sets.iter().max_by(|a, b| a.len().cmp(&b.len())).unwrap(); + let mut largest = largest_set.iter().collect_vec(); + largest.sort(); + println!("best: {:?}", largest); + largest.iter().join(",") } #[cfg(test)]