@@ 0,0 1,140 @@
+use std::{
+ collections::HashMap,
+ fs::File,
+ io::{BufRead, BufReader},
+ path::Path,
+};
+
+pub fn solve(input: &Path) -> anyhow::Result<()> {
+ println!("part one: {}", part_one(input)?);
+ println!("part two: {}", part_two(input)?);
+
+ Ok(())
+}
+
+fn navigate_one(
+ map: &[Vec<u8>],
+ h: u8,
+ p: (&usize, &usize),
+ nines: &mut HashMap<(usize, usize), ()>,
+) {
+ let mut around_us = vec![];
+ if *p.0 > 0 {
+ let (y, x) = (p.0 - 1, *p.1);
+ around_us.push((map[y][x], y, x));
+ }
+ if let Some(row) = map.get(p.0 + 1) {
+ let (y, x) = (p.0 + 1, *p.1);
+ around_us.push((row[x], y, x));
+ }
+ if *p.1 > 0 {
+ let (y, x) = (*p.0, p.1 - 1);
+ around_us.push((map[y][x], y, x));
+ }
+ if let Some(height) = map[*p.0].get(p.1 + 1) {
+ let (y, x) = (*p.0, p.1 + 1);
+ around_us.push((*height, y, x));
+ }
+
+ for (n, y, x) in around_us {
+ if h == 8 && n == 9 {
+ nines.insert((y, x), ());
+ } else if n == h + 1 {
+ navigate_one(map, h + 1, (&y, &x), nines);
+ }
+ }
+}
+
+fn part_one(input: &Path) -> anyhow::Result<usize> {
+ let reader = BufReader::new(File::open(input)?);
+
+ let mut map: Vec<Vec<u8>> = vec![];
+ for line in reader.lines() {
+ map.push(
+ line?
+ .chars()
+ .map(|c| -> u8 { c.to_string().parse().unwrap() })
+ .collect(),
+ );
+ }
+ let trailheads: Vec<(usize, usize)> = map
+ .iter()
+ .enumerate()
+ .flat_map(|(y, row)| -> Vec<(usize, usize)> {
+ row.iter()
+ .enumerate()
+ .filter_map(|(x, n)| if *n == 0 { Some((y, x)) } else { None })
+ .collect()
+ })
+ .collect();
+
+ let mut answer = 0;
+ for (head_y, head_x) in &trailheads {
+ let mut nines: HashMap<(usize, usize), ()> = HashMap::new();
+ navigate_one(&map, 0, (head_y, head_x), &mut nines);
+ answer += nines.len();
+ }
+
+ Ok(answer)
+}
+
+fn navigate_two(map: &[Vec<u8>], h: u8, p: (&usize, &usize)) -> i32 {
+ let mut nines = 0;
+ let mut around_us = vec![];
+ if *p.0 > 0 {
+ let (y, x) = (p.0 - 1, *p.1);
+ around_us.push((map[y][x], y, x));
+ }
+ if let Some(row) = map.get(p.0 + 1) {
+ let (y, x) = (p.0 + 1, *p.1);
+ around_us.push((row[x], y, x));
+ }
+ if *p.1 > 0 {
+ let (y, x) = (*p.0, p.1 - 1);
+ around_us.push((map[y][x], y, x));
+ }
+ if let Some(height) = map[*p.0].get(p.1 + 1) {
+ let (y, x) = (*p.0, p.1 + 1);
+ around_us.push((*height, y, x));
+ }
+
+ for (n, y, x) in around_us {
+ if h == 8 && n == 9 {
+ nines += 1;
+ } else if n == h + 1 {
+ nines += navigate_two(map, h + 1, (&y, &x));
+ }
+ }
+ nines
+}
+
+fn part_two(input: &Path) -> anyhow::Result<i32> {
+ let reader = BufReader::new(File::open(input)?);
+
+ let mut map: Vec<Vec<u8>> = vec![];
+ for line in reader.lines() {
+ map.push(
+ line?
+ .chars()
+ .map(|c| -> u8 { c.to_string().parse().unwrap() })
+ .collect(),
+ );
+ }
+ let trailheads: Vec<(usize, usize)> = map
+ .iter()
+ .enumerate()
+ .flat_map(|(y, row)| -> Vec<(usize, usize)> {
+ row.iter()
+ .enumerate()
+ .filter_map(|(x, n)| if *n == 0 { Some((y, x)) } else { None })
+ .collect()
+ })
+ .collect();
+
+ let mut answer = 0;
+ for (head_y, head_x) in &trailheads {
+ answer += navigate_two(&map, 0, (head_y, head_x));
+ }
+
+ Ok(answer)
+}
@@ 3,6 3,7 @@ use std::path::PathBuf;
use clap::{Parser, Subcommand};
mod day1;
+mod day10;
mod day2;
mod day3;
mod day4;
@@ 56,6 57,10 @@ enum DayArgs {
#[arg(short)]
input: PathBuf,
},
+ Day10 {
+ #[arg(short)]
+ input: PathBuf,
+ },
}
fn main() -> anyhow::Result<()> {
@@ 89,6 94,9 @@ fn main() -> anyhow::Result<()> {
DayArgs::Day9 { input } => {
day9::solve(&input)?;
}
+ DayArgs::Day10 { input } => {
+ day10::solve(&input)?;
+ }
}
Ok(())