DEVELOPMENT ENVIRONMENT

~liljamo/aoc2024

fe0defd197797ee1ca5b427aebc642c23377d9c9 — Jonni Liljamo a month ago 6aac5b0
feat: day10
3 files changed, 156 insertions(+), 0 deletions(-)

A input/day10/example
A src/day10/mod.rs
M src/main.rs
A input/day10/example => input/day10/example +8 -0
@@ 0,0 1,8 @@
89010123
78121874
87430965
96549874
45678903
32019012
01329801
10456732

A src/day10/mod.rs => src/day10/mod.rs +140 -0
@@ 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)
}

M src/main.rs => src/main.rs +8 -0
@@ 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(())