1use utils::prelude::*;
2
3#[derive(Clone, Debug)]
5pub struct Day03 {
6 part1: u32,
7 part2: u32,
8}
9
10#[derive(Debug)]
11struct Claim {
12 id: u32,
13 y: usize,
14 height: usize,
15 idx: usize,
16 mask0: u32,
17 mask1: u32,
18}
19
20impl Day03 {
21 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
22 let coordinate = parser::number_range(0usize..=991);
23 let dimension = parser::number_range(1usize..=31);
24
25 let claims: Vec<Claim> = parser::u32()
26 .with_prefix(b'#')
27 .with_suffix(" @ ")
28 .then(coordinate.with_suffix(b','))
29 .then(coordinate.with_suffix(": "))
30 .then(dimension.with_suffix(b'x'))
31 .then(dimension)
32 .map_res(|(id, x, y, width, height)| {
33 if x + width > 1000 || y + height > 1000 {
34 Err("claim out of bounds")
35 } else {
36 let mask = ((1u64 << width) - 1) << (x % 32);
37
38 Ok(Claim {
39 id,
40 y,
41 height,
42 idx: (x / 32),
43 mask0: mask as u32,
44 mask1: (mask >> 32) as u32,
45 })
46 }
47 })
48 .parse_lines(input)?;
49
50 let mut grid = [[0u32; 32]; 1000];
51 let mut overlaps = [[0u32; 32]; 1000];
52 for claim in &claims {
53 assert!(claim.idx + 1 < 32);
55
56 for y in claim.y..claim.y + claim.height {
57 overlaps[y][claim.idx] |= grid[y][claim.idx] & claim.mask0;
58 grid[y][claim.idx] |= claim.mask0;
59
60 overlaps[y][claim.idx + 1] |= grid[y][claim.idx + 1] & claim.mask1;
61 grid[y][claim.idx + 1] |= claim.mask1;
62 }
63 }
64
65 Ok(Self {
66 part1: overlaps.as_flattened().iter().map(|x| x.count_ones()).sum(),
67 part2: claims
68 .iter()
69 .find(|claim| {
70 overlaps[claim.y..claim.y + claim.height].iter().all(|o| {
71 o[claim.idx] & claim.mask0 == 0 && o[claim.idx + 1] & claim.mask1 == 0
72 })
73 })
74 .ok_or_else(|| InputError::new(input, 0, "all claims overlap"))?
75 .id,
76 })
77 }
78
79 #[must_use]
80 pub fn part1(&self) -> u32 {
81 self.part1
82 }
83
84 #[must_use]
85 pub fn part2(&self) -> u32 {
86 self.part2
87 }
88}
89
90examples!(Day03 -> (u32, u32) [
91 {input: "#1 @ 1,3: 4x4\n#2 @ 3,1: 4x4\n#3 @ 5,5: 2x2", part1: 4},
92]);