summaryrefslogtreecommitdiff
path: root/2024_rust/src/lib.rs
blob: db67f275316e2f5829e645b457d606bb0082941d (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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
pub mod matrix {
    pub type Pos = (usize, usize);
    pub type PosDelta = (isize, isize);

    #[derive(Clone)]
    pub struct Matrix<T> {
        dots: Vec<Vec<T>>,
        pub limit: Pos,
    }

    impl<T> Matrix<T> {
        pub fn new<F>(text: &str, parse: F) -> Self
        where
            F: Fn(char) -> T,
        {
            let dots: Vec<Vec<T>> = text
                .lines()
                .map(|row| row.chars().map(|c| parse(c)).collect())
                .collect();
            let limit = (dots.len(), dots[0].len());
            Self { dots, limit }
        }

        pub fn get(&self, (x, y): Pos) -> &T {
            &self.dots[x][y]
        }

        pub fn set(&mut self, (x, y): Pos, dot: T) {
            self.dots[x][y] = dot;
        }

        pub fn pos_move(&self, (x, y): Pos, (dx, dy): PosDelta) -> Option<Pos> {
            let x2 = x as isize + dx;
            if x2 < 0 || x2 >= self.limit.0 as isize {
                return None;
            }
            let y2 = y as isize + dy;
            if y2 < 0 || y2 >= self.limit.1 as isize {
                return None;
            }
            Some((x2 as usize, y2 as usize))
        }
    }

    use std::fmt;
    impl<T> fmt::Display for Matrix<T>
    where
        T: fmt::Display,
    {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            for row in &self.dots {
                write!(
                    f,
                    "{}\n",
                    row.iter().map(|c| c.to_string()).collect::<String>()
                )?;
            }
            fmt::Result::Ok(())
        }
    }
}

pub fn read_input(day: &str) -> String {
    let input_file = format!("inputs/{day}");
    std::fs::read_to_string(input_file).unwrap()
}

pub fn run_day<S1, S2>(day: &str, p1: S1, p2: S2) -> (String, String)
where
    S1: FnOnce(&str) -> String,
    S2: FnOnce(&str) -> String,
{
    let input = read_input(day);

    let p1r = p1(&input);
    let p2r = p2(&input);

    println!("==== DAY {day}");
    println!("Result (P1): {}", p1r);
    println!("Result (P2): {}", p2r);

    (p1r, p2r)
}