summaryrefslogtreecommitdiff
path: root/2024_rust/src/bin/day10.rs
blob: 4bd49c86d594d5191989047de1c76b9c2bbeae79 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use aoc2024::matrix;
use std::collections::HashSet;

static AROUND_DELTAS: [(isize, isize); 4] = [(-1, 0), (0, -1), (0, 1), (1, 0)];

type Matrix = matrix::Matrix<u32>;
type Trailhead = matrix::Pos;

fn trailheads(m: &Matrix) -> Vec<Trailhead> {
    let mut result: Vec<Trailhead> = vec![];
    for i in 0..m.limit.0 {
        for j in 0..m.limit.1 {
            let pos = (i, j);
            if m.get(pos) == &0 {
                result.push(pos);
            }
        }
    }
    result
}

fn reachable(m: &Matrix, pos: matrix::Pos) -> HashSet<matrix::Pos> {
    let height = m.get(pos);
    AROUND_DELTAS
        .iter()
        .filter_map(|&d| m.pos_move(pos, d))
        .filter(|&p| *m.get(p) == height + 1)
        .collect()
}

fn score1(m: &Matrix, th: Trailhead) -> u32 {
    let mut heads: HashSet<matrix::Pos> = HashSet::new();
    heads.insert(th);
    let mut height = 0;
    while height < 9 {
        heads = heads.into_iter().flat_map(|th| reachable(m, th)).collect();
        height += 1;
    }
    heads.len() as u32
}

fn p1(input: &str) -> String {
    let m: Matrix = matrix::Matrix::new(input, |c| c.to_digit(10).unwrap());
    let result: u32 = trailheads(&m).iter().map(|&th| score1(&m, th)).sum();

    result.to_string()
}

fn score2(m: &Matrix, th: Trailhead) -> u32 {
    let mut heads: Vec<matrix::Pos> = vec![th];
    let mut height = 0;
    while height < 9 {
        heads = heads.into_iter().flat_map(|th| reachable(m, th)).collect();
        height += 1;
    }
    heads.len() as u32
}

fn p2(input: &str) -> String {
    let m: Matrix = matrix::Matrix::new(input, |c| c.to_digit(10).unwrap());
    let result: u32 = trailheads(&m).iter().map(|&th| score2(&m, th)).sum();

    result.to_string()
}

fn main() {
    aoc2024::run_day("10", p1, p2);
}