diff --git a/2021/day12/day12_rs/Cargo.toml b/2021/day12/day12_rs/Cargo.toml new file mode 100644 index 0000000..76bc485 --- /dev/null +++ b/2021/day12/day12_rs/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day12_rs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2021/day12/day12_rs/src/main.rs b/2021/day12/day12_rs/src/main.rs new file mode 100644 index 0000000..5a92c54 --- /dev/null +++ b/2021/day12/day12_rs/src/main.rs @@ -0,0 +1,59 @@ +#![warn(clippy::pedantic)] +use std::{ + collections::{HashMap, HashSet}, + io::{stdin, BufRead}, +}; + +type Point<'a> = &'a str; + +fn walk<'a>( + connections: &HashMap, HashSet>>, + visited: &[Point<'a>], + extra_cave: Option>, + from: Point<'a>, +) -> usize { + let mut res = 0; + + let mut visited = Vec::from(visited); + visited.push(from); + + for target in &connections[from] { + if *target == "end" { + res += 1; + continue; + } + + let is_uppercase = target.chars().all(|c| c.is_ascii_uppercase()); + let was_visited = visited.contains(target); + + if is_uppercase || !was_visited { + res += walk(connections, &visited, extra_cave, target); + } else if extra_cave.is_none() { + res += walk(connections, &visited, Some(target), target); + } + } + + res +} + +fn main() { + let lines: Vec<_> = stdin().lock().lines().collect::>().unwrap(); + + let connections: HashMap> = + lines.iter().fold(HashMap::new(), |mut map, line| { + let mut parts = line.split('-'); + let p1 = parts.next().unwrap(); + let p2 = parts.next().unwrap(); + + if p2 != "start" { + map.entry(p1).or_default().insert(p2); + } + if p2 != "end" { + map.entry(p2).or_default().insert(p1); + } + map + }); + + println!("{}", walk(&connections, &[], Some(""), "start")); + println!("{}", walk(&connections, &[], None, "start")); +}