1use utils::prelude::*;
2
3#[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 return allowed;
53 };
54 ip = next_ip;
55 }
56 }
57
58 allowed + u64::from(u32::MAX - ip) + 1
60 }
61}
62
63examples!(Day20 -> (u32, u64) [
64 {
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]);