summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-12 00:55:59 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-12 00:55:59 -0500
commit7c98fad9cc21b6204454bab4c27f57ffd2a6188a (patch)
tree462bbf57c2bb975ad2602a11c011b49cc48fd36c
parent38b6e54beadfdf4f831b8c08f3b0b6f64a441038 (diff)
downloadadvent-of-code-7c98fad9cc21b6204454bab4c27f57ffd2a6188a.tar.gz
advent-of-code-7c98fad9cc21b6204454bab4c27f57ffd2a6188a.zip
day 12
-rw-r--r--data/2021/12.txt24
-rw-r--r--src/2021/12/mod.rs98
-rw-r--r--src/2021/mod.rs4
3 files changed, 126 insertions, 0 deletions
diff --git a/data/2021/12.txt b/data/2021/12.txt
new file mode 100644
index 0000000..1d5c9fe
--- /dev/null
+++ b/data/2021/12.txt
@@ -0,0 +1,24 @@
+re-js
+qx-CG
+start-js
+start-bj
+qx-ak
+js-bj
+ak-re
+CG-ak
+js-CG
+bj-re
+ak-lg
+lg-CG
+qx-re
+WP-ak
+WP-end
+re-lg
+end-ak
+WP-re
+bj-CG
+qx-start
+bj-WP
+JG-lg
+end-lg
+lg-iw
diff --git a/src/2021/12/mod.rs b/src/2021/12/mod.rs
new file mode 100644
index 0000000..e722c22
--- /dev/null
+++ b/src/2021/12/mod.rs
@@ -0,0 +1,98 @@
+fn small(s: &str) -> bool {
+ s.chars().all(|c| c.is_lowercase())
+}
+
+fn single_small(path: &[String]) -> bool {
+ path.iter().filter(|s| small(s)).count()
+ == path
+ .iter()
+ .filter(|s| small(s))
+ .collect::<std::collections::HashSet<_>>()
+ .len()
+}
+
+fn paths_from1(
+ graph: &std::collections::HashMap<
+ String,
+ std::collections::HashSet<String>,
+ >,
+ path: Vec<String>,
+) -> i64 {
+ let mut total = 0;
+ for neighbor in graph[&path[path.len() - 1]].iter() {
+ if small(neighbor) && path.contains(neighbor) {
+ continue;
+ }
+ if neighbor == "end" {
+ total += 1;
+ } else {
+ let mut path = path.clone();
+ path.push(neighbor.to_string());
+ total += paths_from1(graph, path);
+ }
+ }
+ total
+}
+
+fn paths_from2(
+ graph: &std::collections::HashMap<
+ String,
+ std::collections::HashSet<String>,
+ >,
+ path: Vec<String>,
+) -> i64 {
+ let mut total = 0;
+ for neighbor in graph[&path[path.len() - 1]].iter() {
+ if neighbor == "start" {
+ continue;
+ }
+ if small(neighbor) && path.contains(neighbor) && !single_small(&path)
+ {
+ continue;
+ }
+ if neighbor == "end" {
+ total += 1;
+ } else {
+ let mut path = path.clone();
+ path.push(neighbor.to_string());
+ total += paths_from2(graph, path);
+ }
+ }
+ total
+}
+
+pub fn part1() -> anyhow::Result<i64> {
+ let mut graph = std::collections::HashMap::new();
+ for line in data_lines!()? {
+ let line = line?;
+ let nodes: Vec<String> =
+ line.split('-').map(|s| s.to_string()).collect();
+ let edges = graph
+ .entry(nodes[0].clone())
+ .or_insert_with(std::collections::HashSet::new);
+ edges.insert(nodes[1].clone());
+ let edges = graph
+ .entry(nodes[1].clone())
+ .or_insert_with(std::collections::HashSet::new);
+ edges.insert(nodes[0].clone());
+ }
+ Ok(paths_from1(&graph, vec!["start".to_string()]))
+}
+
+pub fn part2() -> anyhow::Result<i64> {
+ let mut graph = std::collections::HashMap::new();
+ for line in data_lines!()? {
+ let line = line?;
+ let nodes: Vec<String> =
+ line.split('-').map(|s| s.to_string()).collect();
+ let edges = graph
+ .entry(nodes[0].clone())
+ .or_insert_with(std::collections::HashSet::new);
+ edges.insert(nodes[1].clone());
+ let edges = graph
+ .entry(nodes[1].clone())
+ .or_insert_with(std::collections::HashSet::new);
+ edges.insert(nodes[0].clone());
+ }
+ Ok(paths_from2(&graph, vec!["start".to_string()]))
+}
diff --git a/src/2021/mod.rs b/src/2021/mod.rs
index ccac2b0..a829642 100644
--- a/src/2021/mod.rs
+++ b/src/2021/mod.rs
@@ -20,6 +20,8 @@ mod day9;
mod day10;
#[path = "11/mod.rs"]
mod day11;
+#[path = "12/mod.rs"]
+mod day12;
// NEXT MOD
pub fn run(day: u8, puzzle: u8) -> anyhow::Result<i64> {
@@ -46,6 +48,8 @@ pub fn run(day: u8, puzzle: u8) -> anyhow::Result<i64> {
(10, 2) => day10::part2(),
(11, 1) => day11::part1(),
(11, 2) => day11::part2(),
+ (12, 1) => day12::part1(),
+ (12, 2) => day12::part2(),
// NEXT PART
_ => Err(anyhow::anyhow!("unknown puzzle {}-{}", day, puzzle)),
}