From 8a2d7323ada56c5d00ece428c98efcb37edd2104 Mon Sep 17 00:00:00 2001 From: Kirill Kleymenov Date: Mon, 23 Dec 2024 12:08:07 +0300 Subject: [PATCH] 23 ok --- data/examples/23.txt | 32 +++++++++++ src/bin/23.rs | 124 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 data/examples/23.txt create mode 100644 src/bin/23.rs diff --git a/data/examples/23.txt b/data/examples/23.txt new file mode 100644 index 0000000..d8576a8 --- /dev/null +++ b/data/examples/23.txt @@ -0,0 +1,32 @@ +kh-tc +qp-kh +de-cg +ka-co +yn-aq +qp-ub +cg-tb +vc-aq +tb-ka +wh-tc +yn-cg +kh-ub +ta-co +de-co +tc-td +tb-wq +wh-td +ta-ka +td-qp +aq-cg +wq-ub +ub-vc +de-ta +wq-aq +wq-vc +wh-yn +ka-de +kh-ta +co-tc +wh-qp +tb-vc +td-yn \ No newline at end of file diff --git a/src/bin/23.rs b/src/bin/23.rs new file mode 100644 index 0000000..c4a3592 --- /dev/null +++ b/src/bin/23.rs @@ -0,0 +1,124 @@ +use std::collections::{HashMap, HashSet}; + +advent_of_code::solution!(23); + +fn build_computers(input: &str) -> HashMap> { + let mut computers: HashMap> = HashMap::new(); + + for line in input.lines() { + let (left, right) = line.split_once("-").unwrap(); + + let ll = computers.entry(left.to_string()).or_insert(HashSet::new()); + ll.insert(right.to_string()); + + let rr = computers.entry(right.to_string()).or_insert(HashSet::new()); + rr.insert(left.to_string()); + } + computers +} + +pub fn part_one(input: &str) -> Option { + let computers = build_computers(input); + let mut triplets: HashSet = HashSet::new(); + + for comp in computers.keys() { + if !comp.starts_with('t') { + continue; + } + + let my_connections = computers.get(comp).unwrap(); + + for conn1 in my_connections.iter() { + if conn1 == comp { + continue; + } + + let c1c = computers.get(conn1).unwrap(); + + for conn2 in my_connections.iter() { + if conn2 == comp || conn2 == conn1 { + continue; + } + + if c1c.contains(conn2) { + let mut connvec: Vec = vec![comp.clone(), conn1.clone(), conn2.clone()]; + connvec.sort(); + + triplets.insert(connvec.join(",")); + } + } + } + } + + Some(triplets.len() as u32) +} + +fn bron_kerbosch( + current: &mut HashSet, + candidates: HashSet, + excluded: HashSet, + graph: &HashMap>, + max_clique: &mut HashSet, +) { + if candidates.is_empty() && excluded.is_empty() { + if current.len() > max_clique.len() { + max_clique.clear(); + max_clique.extend(current.iter().cloned()); + } + return; + } + + let mut c_c = candidates.clone(); + for v in candidates { + let conns = match graph.get(&v) { + Some(v) => v, + None => &HashSet::new(), + }; + + current.insert(v.clone()); + + let n_cand: HashSet<_> = c_c.intersection(conns).cloned().collect(); + let n_ex: HashSet<_> = excluded.intersection(conns).cloned().collect(); + + bron_kerbosch(current, n_cand, n_ex, graph, max_clique); + + current.remove(&v); + c_c.remove(&v); + } +} + +pub fn part_two(input: &str) -> Option { + let computers = build_computers(input); + + let mut max_clique: HashSet = HashSet::new(); + + bron_kerbosch( + &mut HashSet::new(), + computers.keys().cloned().collect(), + HashSet::new(), + &computers, + &mut max_clique, + ); + + let mut vectorized: Vec = max_clique.iter().map(|v| v.clone()).collect(); + vectorized.sort(); + + Some(vectorized.join(",")) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(7)); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some("co,de,ka,ta".to_string())); + } +}