From 4d1fdd9cc01166a884f5a0da0958332bf8fbfcfb Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 12 Dec 2021 11:09:14 +0100 Subject: [PATCH] Implement day 12 part 1 --- 2021/inputs/12.txt | 19 ++++++++++ 2021/src/day12.rs | 76 +++++++++++++++++++++++++++++++++++++-- 2021/src/samples/12.1.txt | 7 ++++ 2021/src/samples/12.2.txt | 10 ++++++ 2021/src/samples/12.3.txt | 18 ++++++++++ 5 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 2021/inputs/12.txt create mode 100644 2021/src/samples/12.1.txt create mode 100644 2021/src/samples/12.2.txt create mode 100644 2021/src/samples/12.3.txt diff --git a/2021/inputs/12.txt b/2021/inputs/12.txt new file mode 100644 index 0000000..262ee68 --- /dev/null +++ b/2021/inputs/12.txt @@ -0,0 +1,19 @@ +lg-GW +pt-start +pt-uq +nx-lg +ve-GW +start-nx +GW-start +GW-nx +pt-SM +sx-GW +lg-end +nx-SM +lg-SM +pt-nx +end-ve +ve-SM +TG-uq +end-SM +SM-uq diff --git a/2021/src/day12.rs b/2021/src/day12.rs index 113ba49..3e10ddf 100644 --- a/2021/src/day12.rs +++ b/2021/src/day12.rs @@ -1,9 +1,81 @@ +use std::collections::HashMap; use std::io::Read; -pub fn part1(_input: &mut dyn Read) -> String { - todo!() +use crate::common::LineIter; + +type EdgeMap = HashMap>; + +fn read_edges(input: &mut dyn Read) -> EdgeMap { + let mut reader = LineIter::new(input); + let mut edges = EdgeMap::new(); + + while let Some(line) = reader.next() { + let (from, to) = line.split_once('-').unwrap(); + + edges + .entry(from.to_owned()) + .or_default() + .push(to.to_owned()); + + edges + .entry(to.to_owned()) + .or_default() + .push(from.to_owned()); + } + + edges +} + +fn is_small(cave: &str) -> bool { + cave.chars().all(|c| c.is_ascii_lowercase()) +} + +fn dfs_routes<'a>(edges: &'a EdgeMap, route: &'_ mut Vec<&'a str>, pos: &'a str) -> usize { + if is_small(pos) && route.contains(&pos) { + return 0; + } + + if pos == "end" { + return 1; + } + + route.push(pos); + + let routes = edges[pos] + .iter() + .map(|new_pos| dfs_routes(edges, route, new_pos)) + .sum(); + + route.pop(); + + routes +} + +pub fn part1(input: &mut dyn Read) -> String { + let edges = read_edges(input); + let mut route = Vec::new(); + + dfs_routes(&edges, &mut route, "start").to_string() } pub fn part2(_input: &mut dyn Read) -> String { todo!() } + +#[cfg(test)] +mod tests { + use super::*; + + use crate::test_implementation; + + const SAMPLE1: &[u8] = include_bytes!("samples/12.1.txt"); + const SAMPLE2: &[u8] = include_bytes!("samples/12.2.txt"); + const SAMPLE3: &[u8] = include_bytes!("samples/12.3.txt"); + + #[test] + fn sample_part1() { + test_implementation(part1, SAMPLE1, 10); + test_implementation(part1, SAMPLE2, 19); + test_implementation(part1, SAMPLE3, 226); + } +} diff --git a/2021/src/samples/12.1.txt b/2021/src/samples/12.1.txt new file mode 100644 index 0000000..6fd8c41 --- /dev/null +++ b/2021/src/samples/12.1.txt @@ -0,0 +1,7 @@ +start-A +start-b +A-c +A-b +b-d +A-end +b-end diff --git a/2021/src/samples/12.2.txt b/2021/src/samples/12.2.txt new file mode 100644 index 0000000..62cc714 --- /dev/null +++ b/2021/src/samples/12.2.txt @@ -0,0 +1,10 @@ +dc-end +HN-start +start-kj +dc-start +dc-HN +LN-dc +HN-end +kj-sa +kj-HN +kj-dc diff --git a/2021/src/samples/12.3.txt b/2021/src/samples/12.3.txt new file mode 100644 index 0000000..65f3833 --- /dev/null +++ b/2021/src/samples/12.3.txt @@ -0,0 +1,18 @@ +fs-end +he-DX +fs-he +start-DX +pj-DX +end-zg +zg-sl +zg-pj +pj-he +RW-he +fs-DX +pj-RW +zg-RW +start-pj +he-WI +zg-he +pj-fs +start-RW