1use crate::util::iter::*;
3use crate::util::parse::*;
4
5type Tile = [u64; 2];
6
7struct Candidate {
8 x: u64,
9 y: u64,
10 interval: Interval,
11}
12
13#[derive(Clone, Copy)]
15struct Interval {
16 l: u64,
17 r: u64,
18}
19
20impl 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
42pub fn parse(input: &str) -> Vec<Tile> {
43 input.iter_unsigned::<u64>().chunk::<2>().collect()
44}
45
46pub fn part1(tiles: &[Tile]) -> u64 {
47 let mut area = 0;
48
49 for (i, &[x1, y1]) in tiles.iter().enumerate() {
50 for &[x2, y2] in tiles.iter().skip(i + 1) {
51 let dx = x1.abs_diff(x2) + 1;
52 let dy = y1.abs_diff(y2) + 1;
53 area = area.max(dx * dy);
54 }
55 }
56
57 area
58}
59
60pub fn part2(tiles: &[Tile]) -> u64 {
61 let mut tiles = tiles.to_vec();
62
63 tiles.sort_unstable_by_key(|&[x, y]| (y, x));
64
65 let tiles = tiles;
66
67 let mut largest_area: u64 = 0;
69
70 let mut candidates: Vec<Candidate> = Vec::with_capacity(512);
73
74 let mut descending_edges: Vec<u64> = vec![];
76 let mut intervals_from_descending_edges = vec![];
77
78 let mut it = tiles.into_iter();
80
81 while let (Some([x0, y]), Some([x1, y1])) = (it.next(), it.next()) {
82 debug_assert_eq!(y, y1);
83
84 for x in [x0, x1] {
97 toggle_value_membership_in_ordered_list(&mut descending_edges, x);
98 }
99
100 update_intervals_from_descending_edges(
102 &descending_edges,
103 &mut intervals_from_descending_edges,
104 );
105
106 for candidate in &candidates {
108 for x in [x0, x1] {
109 if candidate.interval.contains(x) {
110 largest_area = largest_area
111 .max((candidate.x.abs_diff(x) + 1) * (candidate.y.abs_diff(y) + 1));
112 }
113 }
114 }
115
116 candidates.retain_mut(|candidate| {
118 if let Some(intersection_containing_x) =
119 intervals_from_descending_edges.iter().find(|i| i.contains(candidate.x))
120 {
121 candidate.interval = intersection_containing_x.intersection(candidate.interval);
122
123 true
124 } else {
125 false
126 }
127 });
128
129 for x in [x0, x1] {
131 if let Some(&containing) =
132 intervals_from_descending_edges.iter().find(|i| i.contains(x))
133 {
134 candidates.push(Candidate { x, y, interval: containing });
135 }
136 }
137 }
138
139 largest_area
140}
141
142fn toggle_value_membership_in_ordered_list(ordered_list: &mut Vec<u64>, value: u64) {
144 let mut i = 0;
145
146 while i < ordered_list.len() && ordered_list[i] < value {
147 i += 1;
148 }
149
150 if i == ordered_list.len() || ordered_list[i] != value {
151 ordered_list.insert(i, value);
152 } else {
153 ordered_list.remove(i);
154 }
155}
156
157#[inline]
160fn update_intervals_from_descending_edges(descending_edges: &[u64], to_update: &mut Vec<Interval>) {
161 debug_assert!(descending_edges.len().is_multiple_of(2));
162
163 to_update.clear();
164
165 let mut it = descending_edges.iter();
166
167 while let (Some(&l), Some(&r)) = (it.next(), it.next()) {
168 to_update.push(Interval::new(l, r));
169 }
170}