From 05b76ae3658332b685982a1cb62697d9016a873e Mon Sep 17 00:00:00 2001 From: Adrian Groh Date: Tue, 10 Dec 2024 09:31:51 +0100 Subject: [PATCH] Add day10 --- day10/Cargo.lock | 7 +++++ day10/Cargo.toml | 6 ++++ day10/src/main.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 day10/Cargo.lock create mode 100644 day10/Cargo.toml create mode 100644 day10/src/main.rs diff --git a/day10/Cargo.lock b/day10/Cargo.lock new file mode 100644 index 0000000..6b69a8f --- /dev/null +++ b/day10/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "day10" +version = "0.1.0" diff --git a/day10/Cargo.toml b/day10/Cargo.toml new file mode 100644 index 0000000..3c916ef --- /dev/null +++ b/day10/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day10" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/day10/src/main.rs b/day10/src/main.rs new file mode 100644 index 0000000..9b4f02a --- /dev/null +++ b/day10/src/main.rs @@ -0,0 +1,78 @@ +use std::collections::HashSet; + +fn parse(input: &str) -> Vec> { + input + .lines() + .map(|line| line.chars().map(|c| c.to_digit(10).unwrap_or(10)).collect()) + .collect() +} + +fn get_score(pos: &(usize, usize), prev: &isize, map: &[Vec]) -> HashSet<(usize, usize)> { + let mut res = HashSet::new(); + let Some(Some(val)) = map.get(pos.0).map(|x| x.get(pos.1)) else { + return res; + }; + if *val != (prev + 1) as u32 { + return res; + } + if val == &9 && prev == &8 { + res.insert(*pos); + return res; + } + res.extend(get_score( + &(pos.0.overflowing_sub(1).0, pos.1), + &(*val as isize), + map, + )); + res.extend(get_score(&(pos.0 + 1, pos.1), &(*val as isize), map)); + res.extend(get_score( + &(pos.0, pos.1.overflowing_sub(1).0), + &(*val as isize), + map, + )); + res.extend(get_score(&(pos.0, pos.1 + 1), &(*val as isize), map)); + res +} + +fn get_rating(pos: &(usize, usize), prev: &isize, map: &[Vec]) -> usize { + let Some(Some(val)) = map.get(pos.0).map(|x| x.get(pos.1)) else { + return 0; + }; + if *val != (prev + 1) as u32 { + return 0; + } + if val == &9 && prev == &8 { + return 1; + } + get_rating(&(pos.0.overflowing_sub(1).0, pos.1), &(*val as isize), map) + + get_rating(&(pos.0 + 1, pos.1), &(*val as isize), map) + + get_rating(&(pos.0, pos.1.overflowing_sub(1).0), &(*val as isize), map) + + get_rating(&(pos.0, pos.1 + 1), &(*val as isize), map) +} + +fn part12(input: &[Vec], part1: bool) -> usize { + let trailheads: Vec<_> = input + .iter() + .enumerate() + .flat_map(|(l_idx, l)| { + l.iter() + .enumerate() + .filter(|(_, c)| c == &&0) + .map(move |(c_idx, _)| (l_idx, c_idx)) + }) + .collect(); + if part1 { + trailheads + .iter() + .flat_map(|t| get_score(t, &-1, input)) + .count() + } else { + trailheads.iter().map(|t| get_rating(t, &-1, input)).sum() + } +} + +fn main() { + let input = parse(include_str!("../input.txt")); + println!("{}", part12(&input, true)); + println!("{}", part12(&input, false)); +}