aboutsummaryrefslogtreecommitdiff
path: root/2023/day-02/src/bin/part1.rs
blob: f49f409fd5fecc0a1001b0cd81e93eb881b7ac68 (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
104
105
106
struct GameSet {
    red: u32,
    green: u32,
    blue: u32
}

impl GameSet {
    fn is_valid(&self) -> bool {
        self.red <= 12 && self.green <= 13 && self.blue <= 14
    }
}

struct Game {
    id: u32,
    sets: Vec<GameSet>
}

fn main() {
    let input = include_str!("./input.txt");
    let output: u32 = input
        .lines()
        .map(|line| {
            process_line(line)
        })
        .filter(|game| {
            game.sets.iter().all(|set: &GameSet| set.is_valid())
        })
        .map(|game| {
            game.id
        }).sum();
    println!("Result {output}")
}

fn gameset_from_pairs(pairs: Vec<(&str, u32)>) -> GameSet {
    let mut red: u32 = 0;
    let mut green: u32 = 0;
    let mut blue: u32 = 0;

    for pair in pairs {
        match pair {
            ("red", x) => { red = x },
            ("green", x) => { green = x },
            ("blue", x) => { blue = x },
            what => panic!("Unknown pair {:?}", what)
        }
    }

    GameSet { red, green, blue }
}

/// Progrss a line
fn process_line(string: &str) -> Game {
    let game_split: Vec<&str> = string.splitn(2, ": ").collect();
    // Get game Id from string "Game 1"
    let game_id = game_split[0].split(" ").last().expect("Expected id").parse::<u32>().expect("Cant parse game id");
    let sets: Vec<_> = game_split[1]
        .split("; ")
        .map(|set_line| {
            set_line.split(", ").collect()
        })
        .map(|gameset: Vec<&str>| {
            let pairs: Vec<(&str, u32)> = gameset.into_iter().map(|s| {
                let split: Vec<&str> = s.split_whitespace().collect();
                (split[1], split[0].parse::<u32>().expect("Cant parse"))
            }).collect();
            gameset_from_pairs(pairs)
        })
        .collect();
    Game {
        id: game_id,
        sets
    }
}


#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_process_simple() {
        let game = process_line("Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green");
        assert_eq!(game.id, 1);
    }

    #[test]
    fn test_input() {
        let input = "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green";
        let output: u32 = input.lines().map(|line| {
            process_line(line)
        })
        .filter(|game| {
            game.sets.iter().all(|set: &GameSet| set.is_valid())
        })
        .map(|game| {
            game.id
        }).sum();

        assert_eq!(output, 8);
    }
}