1use crate::util::iter::*;
3use crate::util::parse::*;
4
5type Tile = [u32; 2];
6
7struct Candidate {
8 x: u32,
9 y: u32,
10 interval: Interval,
11}
12
13#[derive(Clone, Copy)]
15struct Interval {
16 l: u32,
17 r: u32,
18}
19
20impl Interval {
21 fn new(l: u32, r: u32) -> 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: u32) -> bool {
38 self.l <= x && x <= self.r
39 }
40}
41
42pub fn parse(input: &str) -> Vec<Tile> {
43 let mut tiles: Vec<_> = input.iter_unsigned::<u32>().chunk::<2>().collect();
44 tiles.sort_unstable_by_key(|&[x, y]| (y, x));
45 tiles
46}
47
48pub fn part1(tiles: &[Tile]) -> u64 {
49 let (top_left_tiles, top_right_tiles) = get_potential_left_corner_tiles(tiles.iter().copied());
50 let (bottom_left_tiles, bottom_right_tiles) =
51 get_potential_left_corner_tiles(tiles.iter().copied().rev());
52
53 find_largest_from_all_corners(&top_left_tiles, &bottom_right_tiles)
54 .max(find_largest_from_all_corners(&bottom_left_tiles, &top_right_tiles))
55}
56
57fn get_potential_left_corner_tiles(
81 sorted_tiles: impl Iterator<Item = [u32; 2]>,
82) -> (Vec<[u32; 2]>, Vec<[u32; 2]>) {
83 let mut left_tiles = Vec::new();
84 let mut left_tiles_last_x = u32::MAX;
85
86 let mut right_tiles = Vec::new();
87 let mut right_tiles_last_x = u32::MIN;
88
89 let mut it = sorted_tiles.peekable();
90
91 while let Some(first_in_row) = it.next() {
92 let mut last_in_row = first_in_row;
93
94 while let Some(p) = it.next_if(|p| p[1] == first_in_row[1]) {
95 last_in_row = p;
96 }
97
98 let (y, left_x, right_x) = (
99 first_in_row[1],
100 first_in_row[0].min(last_in_row[0]),
101 first_in_row[0].max(last_in_row[0]),
102 );
103
104 if left_x < left_tiles_last_x {
105 left_tiles.push([left_x, y]);
106 left_tiles_last_x = left_x;
107 }
108
109 if right_x > right_tiles_last_x {
110 right_tiles.push([right_x, y]);
111 right_tiles_last_x = right_x;
112 }
113 }
114
115 (left_tiles, right_tiles)
116}
117
118#[inline]
119fn find_largest_from_all_corners(corner: &[[u32; 2]], opposite_corner: &[[u32; 2]]) -> u64 {
120 let mut largest = 0_u64;
121
122 for &p in corner {
123 for &q in opposite_corner {
124 largest =
125 largest.max((p[0].abs_diff(q[0]) + 1) as u64 * (p[1].abs_diff(q[1]) + 1) as u64);
126 }
127 }
128
129 largest
130}
131
132pub fn part2(tiles: &[Tile]) -> u64 {
133 let mut largest_area: u64 = 0;
135
136 let mut candidates: Vec<Candidate> = Vec::with_capacity(512);
139
140 let mut descending_edges: Vec<u32> = vec![];
142 let mut intervals_from_descending_edges = vec![];
143
144 let mut it = tiles.iter();
146
147 while let (Some(&[x0, y]), Some(&[x1, y1])) = (it.next(), it.next()) {
148 debug_assert_eq!(y, y1);
149
150 for x in [x0, x1] {
163 toggle_value_membership_in_ordered_list(&mut descending_edges, x);
164 }
165
166 update_intervals_from_descending_edges(
168 &descending_edges,
169 &mut intervals_from_descending_edges,
170 );
171
172 for candidate in &candidates {
174 for x in [x0, x1] {
175 if candidate.interval.contains(x) {
176 largest_area = largest_area.max(
177 (candidate.x.abs_diff(x) + 1) as u64 * (candidate.y.abs_diff(y) + 1) as u64,
178 );
179 }
180 }
181 }
182
183 candidates.retain_mut(|candidate| {
185 if let Some(intersection_containing_x) =
186 intervals_from_descending_edges.iter().find(|i| i.contains(candidate.x))
187 {
188 candidate.interval = intersection_containing_x.intersection(candidate.interval);
189
190 true
191 } else {
192 false
193 }
194 });
195
196 for x in [x0, x1] {
198 if let Some(&containing) =
199 intervals_from_descending_edges.iter().find(|i| i.contains(x))
200 {
201 candidates.push(Candidate { x, y, interval: containing });
202 }
203 }
204 }
205
206 largest_area
207}
208
209fn toggle_value_membership_in_ordered_list(ordered_list: &mut Vec<u32>, value: u32) {
211 match ordered_list.binary_search(&value) {
212 Ok(i) => {
213 ordered_list.remove(i);
214 }
215 Err(i) => {
216 ordered_list.insert(i, value);
217 }
218 }
219}
220
221#[inline]
224fn update_intervals_from_descending_edges(descending_edges: &[u32], to_update: &mut Vec<Interval>) {
225 debug_assert!(descending_edges.len().is_multiple_of(2));
226
227 to_update.clear();
228
229 let mut it = descending_edges.iter();
230
231 while let (Some(&l), Some(&r)) = (it.next(), it.next()) {
232 to_update.push(Interval::new(l, r));
233 }
234}