summaryrefslogtreecommitdiff
path: root/2024/day10.rs
blob: 7c8576df38a67267d6c9a12b8ffa3e44d00c20f4 (plain)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_mut)]
use std::collections::HashSet;
use std::env;
use std::fs::File;
use std::io::Read;

fn dfs(x0: i64, y0: i64, map: &Vec<Vec<i64>>, mut hs: HashSet<(i64, i64)>) -> HashSet<(i64, i64)> {
    //println!("{} {}", x0, y0);
    let h = map.len() as i64;
    let w = map[0].len() as i64;

    let n = map[y0 as usize][x0 as usize];
    if n == 9 {
        hs.insert((y0, x0));
        return hs;
    }

    for (dx, dy) in [(0, 1), (0, -1), (1, 0), (-1, 0)] {
        let x = x0 + dx as i64;
        let y = y0 + dy as i64;
        if (0 <= x) && (x < w) && (0 <= y) && (y < h) {
            if map[y as usize][x as usize] == n + 1 {
                hs = dfs(x, y, map, hs);
            }
        }
    }
    return hs;
}

fn dfs2(
    x0: i64,
    y0: i64,
    map: &Vec<Vec<i64>>,
    mut path: Vec<(i64, i64)>,
    mut hs: HashSet<Vec<(i64, i64)>>,
) -> HashSet<Vec<(i64, i64)>> {
    //println!("{} {}", x0, y0);
    let h = map.len() as i64;
    let w = map[0].len() as i64;

    path.push((x0, y0));

    let n = map[y0 as usize][x0 as usize];
    if n == 9 {
        hs.insert(path);
        return hs;
    }

    for (dx, dy) in [(0, 1), (0, -1), (1, 0), (-1, 0)] {
        let x = x0 + dx as i64;
        let y = y0 + dy as i64;
        if (0 <= x) && (x < w) && (0 <= y) && (y < h) {
            if map[y as usize][x as usize] == n + 1 {
                hs = dfs2(x, y, map, path.clone(), hs);
            }
        }
    }
    return hs;
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let filename = if args.len() == 1 {
        "in/".to_owned() + args[0].split('/').last().unwrap() + ".pzl"
    } else {
        args[1].clone()
    };
    let mut f = File::open(filename).expect("cannot open file");
    let mut content = String::new();
    f.read_to_string(&mut content).expect("cannot read file");
    let lines = content.trim_end().split("\n");

    let mut trailheads: Vec<(i64, i64)> = Vec::new();
    let mut map: Vec<Vec<i64>> = Vec::new();
    for (y, line) in lines.enumerate() {
        let mut l: Vec<i64> = Vec::new();
        for (x, c) in line.chars().enumerate() {
            let n = c.to_digit(10).unwrap() as i64;
            l.push(n);
            if n == 0 {
                trailheads.push((x as i64, y as i64));
            }
        }
        map.push(l);
    }

    let mut res1 = 0;
    let mut res2 = 0;
    for (x0, y0) in trailheads {
        let hs = dfs(x0, y0, &map, HashSet::new());
        res1 += hs.len();

        let hs2 = dfs2(x0, y0, &map, Vec::new(), HashSet::new());
        res2 += hs2.len();
    }

    println!("res1: {}", res1);
    println!("res2: {}", res2);
    assert_eq!(res1, 607);
    assert_eq!(res2, 1384);
}