From 000003103e6f1d4c8343a9a21f15b1567e43cd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Jane=C5=BEi=C4=8D?= Date: Mon, 23 Dec 2024 19:38:23 +0100 Subject: [PATCH] solution: day 23 --- data/examples/23.txt | 32 ++++++++++++++++ src/bin/23.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 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 000000000..3d49766 --- /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 diff --git a/src/bin/23.rs b/src/bin/23.rs new file mode 100644 index 000000000..25afd17 --- /dev/null +++ b/src/bin/23.rs @@ -0,0 +1,88 @@ +use std::collections::BTreeSet; + +use hashbrown::{HashMap, HashSet}; +use itertools::Itertools; + +fn parse_graph(input: &str) -> HashMap<&str, BTreeSet<&str>> { + let nodes: HashSet<_> = input.lines().filter_map(|x| x.split_once('-')).collect(); + let mut graph: HashMap<_, BTreeSet<_>> = HashMap::new(); + for (n1, n2) in nodes.iter().copied() { + graph.entry(n1).or_default().insert(n2); + graph.entry(n2).or_default().insert(n1); + } + + graph +} + +pub fn part_one(input: &str) -> Option { + let graph = parse_graph(input); + + let mut triples = HashSet::new(); + for (n1, neigh) in graph.iter() { + for n2 in neigh.iter().copied() { + for n3 in graph[n2].iter() { + if graph[n3].contains(n1) && n1.starts_with('t') { + let mut triple = [n1, n2, n3]; + triple.sort(); + triples.insert(triple); + } + } + } + } + + triples.len().into() +} + +pub fn part_two(input: &str) -> Option { + let graph = parse_graph(input); + + let p: BTreeSet<_> = graph.keys().copied().collect(); + let r = HashSet::new(); + let x = BTreeSet::new(); + + let mut maximals = HashSet::new(); + + let mut stack = Vec::new(); + stack.push((r, p, x)); + + while let Some((r, mut p, mut x)) = stack.pop() { + if p.is_empty() && x.is_empty() { + let mut password = r.iter().copied().collect_vec(); + password.sort(); + + maximals.insert(password.join(",")); + } + + while let Some(pp) = p.pop_last() { + let mut nr = r.clone(); + nr.insert(pp); + + let np = &p & &graph[pp]; + let nx = &x & &graph[pp]; + + stack.push((nr, np, nx)); + + x.insert(pp); + } + } + + maximals.into_iter().max_by_key(|x| x.len()) +} + +aoc::solution!(23); + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_part_one() { + assert_eq!(part_one(&aoc::template::read_file("examples", 23)), Some(7)); + } + #[test] + fn test_part_two() { + assert_eq!( + part_two(&aoc::template::read_file("examples", 23)), + Some("co,de,ka,ta".to_string()) + ); + } +}