From: alex <>
Date: Mon, 23 Dec 2024 09:29:26 +0000 (+0100)
Subject: Day23 - part 1
X-Git-Url: https://aoc.elinar.fr/?a=commitdiff_plain;h=fe2ea7665d433eef1b708283119ef268cc8f618c;p=aoc_2024
Day23 - part 1
---
diff --git a/src/day23.rs b/src/day23.rs
new file mode 100644
index 0000000..9b0859c
--- /dev/null
+++ b/src/day23.rs
@@ -0,0 +1,160 @@
+use std::error::Error;
+use std::path::Path;
+use std::collections::{HashMap, HashSet};
+
+#[derive(Copy, Clone, Debug)]
+struct Link {
+ c1: [u8; 2],
+ c2: [u8; 2],
+}
+
+impl Link {
+ pub fn new(link: &str) -> Self {
+ let (c1, c2) = link.split_once("-").unwrap();
+ let c1 = c1.as_bytes()[0..2].try_into().unwrap();
+ let c2 = c2.as_bytes()[0..2].try_into().unwrap();
+ Self { c1, c2 }
+ }
+
+ fn contains(&self, c: &[u8]) -> bool {
+ self.c1 == *c || self.c2 == *c
+ }
+}
+
+struct Puzzle {
+ links: Vec,
+ graph: HashMap<[u8; 2], HashSet<[u8; 2]>>,
+}
+
+impl Puzzle {
+ pub fn new(input: &str) -> Self {
+ let mut links: Vec = Vec::new();
+ let mut graph: HashMap<[u8; 2], HashSet<[u8; 2]>> = HashMap::new();
+ input.lines().for_each(|l| {
+ let link = Link::new(l);
+ links.push(link);
+
+ match graph.get_mut(&link.c1) {
+ Some(c_set) => { c_set.insert(link.c2); },
+ None => {
+ let mut c_set: HashSet<[u8; 2]> = HashSet::new();
+ c_set.insert(link.c2);
+ graph.insert(link.c1, c_set);
+ }
+ }
+
+ match graph.get_mut(&link.c2) {
+ Some(c_set) => { c_set.insert(link.c1); },
+ None => {
+ let mut c_set: HashSet<[u8; 2]> = HashSet::new();
+ c_set.insert(link.c1);
+ graph.insert(link.c2, c_set);
+ }
+ }
+ });
+
+ Self { links, graph }
+ }
+
+ fn cycles_of_size_3(&self) -> Vec> {
+ let mut cycles: Vec> = Vec::new();
+ self.graph.iter().for_each(|(c0, linked)| {
+ linked.iter().for_each(|c1| {
+ linked.iter()
+ .filter(|c2| *c2 != c1)
+ .for_each(|c2| {
+ if let Some(set1) = self.graph.get(c1) {
+ if set1.contains(c2) {
+ let cycle: HashSet<[u8; 2]> = HashSet::from([*c0, *c1, *c2]);
+ if !cycles.contains(&cycle) {
+ cycles.push(cycle);
+ }
+ }
+ }
+ });
+ });
+ });
+ cycles
+ }
+}
+
+fn run_part1(input: &str) -> Result> {
+ println!("Running {} - part 1", get_day());
+
+ let puzzle = Puzzle::new(input);
+ let cycles = puzzle.cycles_of_size_3();
+ let res = cycles.iter()
+ .filter(|s| s.iter().any(|c| c[0] == b't'))
+ .count() as u64;
+ Ok(res)
+}
+
+fn run_part2(input: &str) -> Result> {
+ println!("Running {} - part 2", get_day());
+
+ Ok(0)
+}
+
+pub fn run(input: &str) -> Result<(), Box> {
+ let res = run_part1(input)?;
+ println!("{res}");
+
+ let res = run_part2(input)?;
+ println!("{res}");
+
+ Ok(())
+}
+
+fn get_day() -> String {
+ let filename = file!();
+ Path::new(filename).file_stem().unwrap().to_str().unwrap().to_string()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ static TEXT_INPUT: &str = "\
+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";
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(7, run_part1(TEXT_INPUT).unwrap());
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(0, run_part2(TEXT_INPUT).unwrap());
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 65c8fd2..5bdf7bb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -25,6 +25,7 @@ pub mod day18;
pub mod day19;
pub mod day20;
pub mod day22;
+pub mod day23;
fn main() {
let args: Vec = env::args().collect();
@@ -68,6 +69,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box> {
"day19" => day19::run(&input)?,
"day20" => day20::run(&input)?,
"day22" => day22::run(&input)?,
+ "day23" => day23::run(&input)?,
_ => return Err(format!("unknown or unimplemented day \"{day}\"").into()),
}
Ok(())