year2016/
day20.rs

1use utils::prelude::*;
2
3/// Finding numbers outside a list of ranges.
4#[derive(Clone, Debug)]
5pub struct Day20 {
6    ranges: Vec<(u32, u32)>,
7}
8
9impl Day20 {
10    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
11        let mut ranges = parser::u32()
12            .then(parser::u32().with_prefix("-"))
13            .map_res(|(min, max)| {
14                if min <= max {
15                    Ok((min, max))
16                } else {
17                    Err("end value cannot be less than start")
18                }
19            })
20            .repeat(parser::eol(), 0)
21            .parse_complete(input)?;
22        ranges.sort_unstable();
23        Ok(Self { ranges })
24    }
25
26    #[must_use]
27    pub fn part1(&self) -> u32 {
28        let mut ip = 0;
29        for &(start, end) in &self.ranges {
30            if ip < start {
31                break;
32            }
33            if end >= ip {
34                ip = end.checked_add(1).expect("no allowed IPs");
35            }
36        }
37        ip
38    }
39
40    #[must_use]
41    pub fn part2(&self) -> u64 {
42        let mut allowed = 0;
43        let mut ip = 0;
44        for &(start, end) in &self.ranges {
45            if ip < start {
46                allowed += u64::from(start - ip);
47            }
48
49            if end >= ip {
50                let Some(next_ip) = end.checked_add(1) else {
51                    // Range end is u32::MAX, no allowed IPs after final range to add
52                    return allowed;
53                };
54                ip = next_ip;
55            }
56        }
57
58        // Add on IPs after the end of the final range
59        allowed + u64::from(u32::MAX - ip) + 1
60    }
61}
62
63examples!(Day20 -> (u32, u64) [
64    // Custom examples
65    {
66        input: "0-409354575\n\
67            1005171202-1792978424\n\
68            2396795992-4166223847\n\
69            361276686-3509736453\n\
70            2979588951-3460902073",
71        part1: 4166223848,
72        part2: 128743448
73    },
74    {
75        input: "",
76        part1: 0,
77        part2: 4294967296,
78    },
79    {
80        input: "0-0",
81        part1: 1,
82        part2: 4294967295,
83    },
84    {
85        input: "4294967295-4294967295",
86        part1: 0,
87        part2: 4294967295,
88    },
89    {
90        input: "0-4294967295",
91        part2: 0,
92    },
93]);