day23: part 2 - bron kerbosch solution

This commit is contained in:
Keenan Tims 2024-12-23 00:54:13 -08:00
parent 50a197856a
commit d3bade1bdd
Signed by: ktims
GPG Key ID: 11230674D69038D4
3 changed files with 31 additions and 57 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@ -1,6 +1,6 @@
<!-- AOC TILES BEGIN --> <!-- AOC TILES BEGIN -->
<h1 align="center"> <h1 align="center">
2024 - 44 ⭐ - Rust 2024 - 45 ⭐ - Rust
</h1> </h1>
<a href="src/day1.rs"> <a href="src/day1.rs">
<img src=".aoc_tiles/tiles/2024/01.png" width="161px"> <img src=".aoc_tiles/tiles/2024/01.png" width="161px">

View File

@ -1,13 +1,7 @@
use std::{
collections::VecDeque,
fmt::{Debug, Display},
};
use aoc_runner_derive::aoc; use aoc_runner_derive::aoc;
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressIterator};
use itertools::Itertools; use itertools::Itertools;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::fmt::{Debug, Display};
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
struct Node([char; 2]); struct Node([char; 2]);
@ -62,43 +56,37 @@ impl Network {
} }
sets sets
} }
fn node_groups(&self, n: &Node, adjacent_set: FxHashSet<Node>) -> Option<FxHashSet<Node>> { fn bron_kerbosch(
// println!("{:?} {:?}", n, adjacent_set); &self,
let neigh = FxHashSet::from_iter(self.edges.get(n).unwrap().iter().map(|n| *n)); r: FxHashSet<Node>,
let intersection = FxHashSet::from_iter(adjacent_set.intersection(&neigh).map(|n| *n)); mut p: FxHashSet<Node>,
if intersection != adjacent_set { mut x: FxHashSet<Node>,
return Some(adjacent_set); ) -> Vec<FxHashSet<Node>> {
let mut results = Vec::new();
if p.is_empty() && x.is_empty() {
return vec![r];
} }
let mut next_adj_set = adjacent_set.clone(); let p_iter = p.clone(); // so we can modify p
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<Node>, mut p: FxHashSet<Node>, mut x: FxHashSet<Node>) -> FxHashSet<Node> {
if p.is_empty() && r.is_empty() {
return r;
}
let p_iter = p.clone(); // se we can modify p
for node in &p_iter { for node in &p_iter {
let mut new_r = r.clone(); let mut new_r = r.clone();
new_r.insert(*node); 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); p.remove(&node);
x.insert(*node); x.insert(*node);
} }
r results
}
fn maximal_subgraphs(&self) -> Vec<FxHashSet<Node>> {
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)] #[aoc(day23, part2)]
pub fn part2(input: &str) -> String { pub fn part2(input: &str) -> String {
let network = parse(input); let network = parse(input);
let mut best = FxHashSet::default(); let best_sets = network.maximal_subgraphs();
let mut node_queue = network.nodes.clone(); let largest_set = best_sets.iter().max_by(|a, b| a.len().cmp(&b.len())).unwrap();
let progress = ProgressBar::new(network.nodes.len() as u64); let mut largest = largest_set.iter().collect_vec();
while let Some(node) = node_queue.pop() { largest.sort();
progress.inc(1); println!("best: {:?}", largest);
let net = network.node_groups(&node, FxHashSet::default()).unwrap(); largest.iter().join(",")
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()
} }
#[cfg(test)] #[cfg(test)]