|
| 1 | +//! # Movie Theater |
1 | 2 | use crate::util::iter::*; |
2 | 3 | use crate::util::parse::*; |
3 | 4 |
|
4 | 5 | type Tile = [u64; 2]; |
5 | 6 |
|
| 7 | +struct Candidate { |
| 8 | + x: u64, |
| 9 | + y: u64, |
| 10 | + interval: Interval, |
| 11 | +} |
| 12 | + |
| 13 | +/// The set { x in u64 | l <= x <= r }. |
| 14 | +#[derive(Clone, Copy)] |
| 15 | +struct Interval { |
| 16 | + l: u64, |
| 17 | + r: u64, |
| 18 | +} |
| 19 | + |
| 20 | +impl Interval { |
| 21 | + fn new(l: u64, r: u64) -> Self { |
| 22 | + debug_assert!(l <= r); |
| 23 | + |
| 24 | + Interval { l, r } |
| 25 | + } |
| 26 | + |
| 27 | + fn intersects(self, other: Self) -> bool { |
| 28 | + other.l <= self.r && self.l <= other.r |
| 29 | + } |
| 30 | + |
| 31 | + fn intersection(self, other: Self) -> Self { |
| 32 | + debug_assert!(self.intersects(other)); |
| 33 | + |
| 34 | + Interval::new(self.l.max(other.l), self.r.min(other.r)) |
| 35 | + } |
| 36 | + |
| 37 | + fn contains(self, x: u64) -> bool { |
| 38 | + self.l <= x && x <= self.r |
| 39 | + } |
| 40 | +} |
| 41 | + |
6 | 42 | pub fn parse(input: &str) -> Vec<Tile> { |
7 | 43 | input.iter_unsigned::<u64>().chunk::<2>().collect() |
8 | 44 | } |
@@ -33,12 +69,6 @@ pub fn part2(tiles: &[Tile]) -> u64 { |
33 | 69 |
|
34 | 70 | // Each red tile (`x`, `y`) becomes a candidate for being a top corner of the largest area, and during the |
35 | 71 | // scan the `interval` containing the maximum possible width is updated: |
36 | | - struct Candidate { |
37 | | - x: u64, |
38 | | - y: u64, |
39 | | - interval: Interval, |
40 | | - } |
41 | | - |
42 | 72 | let mut candidates: Vec<Candidate> = Vec::with_capacity(512); |
43 | 73 |
|
44 | 74 | // Maintain an ordered list of descending edges, i.e. [begin_interval_0, end_interval_0, begin_interval_1, end_interval_1, ...]: |
@@ -74,7 +104,7 @@ pub fn part2(tiles: &[Tile]) -> u64 { |
74 | 104 | ); |
75 | 105 |
|
76 | 106 | // Check the rectangles this red tile could be a bottom tile for, with the current candidates: |
77 | | - for candidate in candidates.iter() { |
| 107 | + for candidate in &candidates { |
78 | 108 | for x in [x0, x1] { |
79 | 109 | if candidate.interval.contains(x) { |
80 | 110 | largest_area = largest_area |
@@ -109,35 +139,6 @@ pub fn part2(tiles: &[Tile]) -> u64 { |
109 | 139 | largest_area |
110 | 140 | } |
111 | 141 |
|
112 | | -/// The set { x in u64 | l <= x <= r }. |
113 | | -#[derive(Clone, Copy)] |
114 | | -struct Interval { |
115 | | - l: u64, |
116 | | - r: u64, |
117 | | -} |
118 | | - |
119 | | -impl Interval { |
120 | | - fn new(l: u64, r: u64) -> Self { |
121 | | - debug_assert!(l <= r); |
122 | | - |
123 | | - Interval { l, r } |
124 | | - } |
125 | | - |
126 | | - fn intersects(self, other: Self) -> bool { |
127 | | - other.l <= self.r && self.l <= other.r |
128 | | - } |
129 | | - |
130 | | - fn intersection(self, other: Self) -> Self { |
131 | | - debug_assert!(self.intersects(other)); |
132 | | - |
133 | | - Interval::new(self.l.max(other.l), self.r.min(other.r)) |
134 | | - } |
135 | | - |
136 | | - fn contains(self, x: u64) -> bool { |
137 | | - self.l <= x && x <= self.r |
138 | | - } |
139 | | -} |
140 | | - |
141 | 142 | // Adds `value` if it isn't in `ordered_list`, removes it if it is, maintaining the order. |
142 | 143 | fn toggle_value_membership_in_ordered_list(ordered_list: &mut Vec<u64>, value: u64) { |
143 | 144 | let mut i = 0; |
|
0 commit comments