summaryrefslogtreecommitdiff
path: root/2023/src/bin/day_6.rs
blob: 138843e3cb05f3b112befcab6201b149f591afc1 (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
use nom::{
    bytes::complete::tag,
    character::complete::{line_ending, space1, u64 as nom_u64},
    combinator::map,
    multi::separated_list1,
    sequence::tuple,
    IResult,
};
use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let input = fs::read_to_string("inputs/day_6.txt")?;
    let parsed = RacePlan::multi_parser(&input).unwrap().1;
    for plan in parsed {
        dbg!(&plan.win_count_product());
    }

    Ok(())
}

#[derive(Debug)]
struct RacePlan(Vec<RaceRecord>);

#[derive(Debug)]
struct RaceRecord {
    time: u64,
    distance: u64,
}

impl RacePlan {
    fn multi_parser(input: &str) -> IResult<&str, Vec<Self>> {
        separated_list1(line_ending, RacePlan::parser)(input)
    }

    fn parser(input: &str) -> IResult<&str, Self> {
        map(
            tuple((
                tag("Time:"),
                space1,
                separated_list1(space1, nom_u64),
                line_ending,
                tag("Distance:"),
                space1,
                separated_list1(space1, nom_u64),
            )),
            |(_, _, times, _, _, _, distances)| {
                RacePlan(
                    times
                        .into_iter()
                        .zip(distances.into_iter())
                        .map(|(time, distance)| RaceRecord { time, distance })
                        .collect(),
                )
            },
        )(input)
    }

    fn win_count_product(&self) -> usize {
        self.0.iter().map(|r| r.count_wins()).product()
    }
}

impl RaceRecord {
    fn count_wins(&self) -> usize {
        (1..self.time)
            .map(|charge_time| charge_time * (self.time - charge_time))
            .filter(|distance| *distance > self.distance)
            .count()
    }
}