1use super::matrix::Matrix;
5use crate::directed::bfs::bfs_reach;
6use crate::directed::dfs::dfs_reach;
7use crate::utils::constrain;
8use crate::FxIndexSet;
9use num_traits::ToPrimitive;
10use std::collections::BTreeSet;
11use std::fmt;
12use std::iter::FusedIterator;
13use std::ops::Sub;
14
15#[derive(Clone)]
16pub struct Grid {
91 pub width: usize,
93 pub height: usize,
95 diagonal_mode: bool,
96 dense: bool,
100 exclusions: FxIndexSet<(usize, usize)>,
101}
102
103impl Grid {
104 #[must_use]
107 pub fn new(width: usize, height: usize) -> Self {
108 Self {
109 width,
110 height,
111 diagonal_mode: false,
112 dense: false,
113 exclusions: FxIndexSet::default(),
114 }
115 }
116
117 #[inline]
120 #[must_use]
121 pub const fn is_inside(&self, vertex: (usize, usize)) -> bool {
122 vertex.0 < self.width && vertex.1 < self.height
123 }
124
125 pub fn enable_diagonal_mode(&mut self) {
128 self.diagonal_mode = true;
129 }
130
131 pub fn disable_diagonal_mode(&mut self) {
134 self.diagonal_mode = false;
135 }
136
137 pub fn resize(&mut self, width: usize, height: usize) -> bool {
140 let mut truncated = false;
141 if width < self.width {
142 truncated |=
143 (width..self.width).any(|c| (0..self.height).any(|r| self.has_vertex((c, r))));
144 }
145 if height < self.height {
146 truncated |=
147 (0..self.width).any(|c| (height..self.height).any(|r| self.has_vertex((c, r))));
148 }
149 self.exclusions.retain(|&(x, y)| x < width && y < height);
150 if self.dense {
151 for c in self.width..width {
152 for r in 0..height {
153 self.exclusions.insert((c, r));
154 }
155 }
156 for c in 0..self.width.min(width) {
157 for r in self.height..height {
158 self.exclusions.insert((c, r));
159 }
160 }
161 }
162 self.width = width;
163 self.height = height;
164 self.rebalance();
165 truncated
166 }
167
168 #[must_use]
170 pub const fn size(&self) -> usize {
171 self.width * self.height
172 }
173
174 #[must_use]
176 pub fn vertices_len(&self) -> usize {
177 if self.dense {
178 self.size() - self.exclusions.len()
179 } else {
180 self.exclusions.len()
181 }
182 }
183
184 pub fn add_vertex(&mut self, vertex: (usize, usize)) -> bool {
188 if !self.is_inside(vertex) {
189 return false;
190 }
191 let r = if self.dense {
192 self.exclusions.swap_remove(&vertex)
193 } else {
194 self.exclusions.insert(vertex)
195 };
196 self.rebalance();
197 r
198 }
199
200 pub fn remove_vertex(&mut self, vertex: (usize, usize)) -> bool {
203 if !self.is_inside(vertex) {
204 return false;
205 }
206 let r = if self.dense {
207 self.exclusions.insert(vertex)
208 } else {
209 self.exclusions.swap_remove(&vertex)
210 };
211 self.rebalance();
212 r
213 }
214
215 fn borders(&self) -> impl Iterator<Item = (usize, usize)> {
218 let width = self.width;
219 let height = self.height;
220 (0..width)
221 .flat_map(move |x| vec![(x, 0), (x, height - 1)].into_iter())
222 .chain((1..height - 1).flat_map(move |y| vec![(0, y), (width - 1, y)].into_iter()))
223 }
224
225 pub fn add_borders(&mut self) -> usize {
227 if self.width == 0 || self.height == 0 {
228 return 0;
229 }
230 let count = if self.dense {
231 self.borders()
232 .filter(|v| self.exclusions.swap_remove(v))
233 .count()
234 } else {
235 self.borders()
236 .filter(|v| self.exclusions.insert(*v))
237 .count()
238 };
239 self.rebalance();
240 count
241 }
242
243 pub fn remove_borders(&mut self) -> usize {
245 if self.width == 0 || self.height == 0 {
246 return 0;
247 }
248 let count = if self.dense {
249 self.borders()
250 .filter(|v| self.exclusions.insert(*v))
251 .count()
252 } else {
253 self.borders()
254 .filter(|v| self.exclusions.swap_remove(v))
255 .count()
256 };
257 self.rebalance();
258 count
259 }
260
261 fn rebalance(&mut self) {
262 if self.exclusions.len() > self.width * self.height / 2 {
263 self.exclusions = (0..self.width)
264 .flat_map(|c| (0..self.height).map(move |r| (c, r)))
265 .filter(|v| !self.exclusions.contains(v))
266 .collect();
267 self.dense = !self.dense;
268 }
269 }
270
271 pub fn clear(&mut self) -> bool {
274 let r = !self.is_empty();
275 self.dense = false;
276 self.exclusions.clear();
277 r
278 }
279
280 pub fn fill(&mut self) -> bool {
283 let r = !self.is_full();
284 self.clear();
285 self.invert();
286 r
287 }
288
289 #[must_use]
291 pub fn is_empty(&self) -> bool {
292 if self.dense {
293 self.exclusions.len() == self.size()
294 } else {
295 self.exclusions.is_empty()
296 }
297 }
298
299 #[must_use]
302 pub fn is_full(&self) -> bool {
303 if self.dense {
304 self.exclusions.is_empty()
305 } else {
306 self.exclusions.len() == self.size()
307 }
308 }
309
310 pub fn invert(&mut self) {
314 self.dense = !self.dense;
315 }
316
317 #[must_use]
319 pub fn has_vertex(&self, vertex: (usize, usize)) -> bool {
320 self.is_inside(vertex) && (self.exclusions.contains(&vertex) ^ self.dense)
321 }
322
323 #[must_use]
325 pub fn has_edge(&self, v1: (usize, usize), v2: (usize, usize)) -> bool {
326 if !self.has_vertex(v1) || !self.has_vertex(v2) {
327 return false;
328 }
329 let x = v1.0.abs_diff(v2.0);
330 let y = v1.1.abs_diff(v2.1);
331 x + y == 1 || (x == 1 && y == 1 && self.diagonal_mode)
332 }
333
334 #[must_use]
336 pub const fn edges(&self) -> EdgesIterator {
337 EdgesIterator {
338 grid: self,
339 x: 0,
340 y: 0,
341 i: 0,
342 }
343 }
344
345 #[must_use]
349 pub fn neighbours(&self, vertex: (usize, usize)) -> Vec<(usize, usize)> {
350 if !self.has_vertex(vertex) {
351 return vec![];
352 }
353 let (x, y) = vertex;
354 let mut candidates = Vec::with_capacity(8);
355 if x > 0 {
356 candidates.push((x - 1, y));
357 if self.diagonal_mode {
358 if y > 0 {
359 candidates.push((x - 1, y - 1));
360 }
361 if y + 1 < self.height {
362 candidates.push((x - 1, y + 1));
363 }
364 }
365 }
366 if x + 1 < self.width {
367 candidates.push((x + 1, y));
368 if self.diagonal_mode {
369 if y > 0 {
370 candidates.push((x + 1, y - 1));
371 }
372 if y + 1 < self.height {
373 candidates.push((x + 1, y + 1));
374 }
375 }
376 }
377 if y > 0 {
378 candidates.push((x, y - 1));
379 }
380 if y + 1 < self.height {
381 candidates.push((x, y + 1));
382 }
383 candidates.retain(|&v| self.has_vertex(v));
384 candidates
385 }
386
387 pub fn bfs_reachable<P>(
399 &self,
400 start: (usize, usize),
401 mut predicate: P,
402 ) -> BTreeSet<(usize, usize)>
403 where
404 P: FnMut((usize, usize)) -> bool,
405 {
406 bfs_reach(start, |&n| {
407 self.neighbours(n)
408 .into_iter()
409 .filter(|&n| predicate(n))
410 .collect::<Vec<_>>()
411 })
412 .collect()
413 }
414
415 pub fn dfs_reachable<P>(
427 &self,
428 start: (usize, usize),
429 mut predicate: P,
430 ) -> BTreeSet<(usize, usize)>
431 where
432 P: FnMut((usize, usize)) -> bool,
433 {
434 dfs_reach(start, |&n| {
435 self.neighbours(n)
436 .into_iter()
437 .filter(|&n| predicate(n))
438 .collect::<Vec<_>>()
439 })
440 .collect()
441 }
442
443 #[must_use]
445 pub fn iter(&self) -> GridIterator {
446 self.into_iter()
447 }
448
449 #[must_use]
453 pub fn distance(&self, a: (usize, usize), b: (usize, usize)) -> usize {
454 let (dx, dy) = (a.0.abs_diff(b.0), a.1.abs_diff(b.1));
455 if self.diagonal_mode {
456 dx.max(dy)
457 } else {
458 dx + dy
459 }
460 }
461
462 pub fn from_coordinates<T>(points: &[(T, T)]) -> Option<Self>
483 where
484 T: Ord + Sub<Output = T> + Copy + Default + ToPrimitive,
485 {
486 let (min_x, min_y) = (
487 points
488 .iter()
489 .map(|(x, _)| x)
490 .min()
491 .copied()
492 .unwrap_or_default(),
493 points
494 .iter()
495 .map(|(_, y)| y)
496 .min()
497 .copied()
498 .unwrap_or_default(),
499 );
500 points
501 .iter()
502 .map(|(x, y)| Some(((*x - min_x).to_usize()?, (*y - min_y).to_usize()?)))
503 .collect()
504 }
505
506 #[must_use]
519 pub const fn constrain(&self, vertex: (isize, isize)) -> (usize, usize) {
520 (
521 constrain(vertex.0, self.width),
522 constrain(vertex.1, self.height),
523 )
524 }
525}
526
527impl FromIterator<(usize, usize)> for Grid {
528 fn from_iter<T>(iter: T) -> Self
529 where
530 T: IntoIterator<Item = (usize, usize)>,
531 {
532 let vertices = iter.into_iter().collect();
533 let mut width = 0;
534 let mut height = 0;
535 for &(x, y) in &vertices {
536 if x + 1 > width {
537 width = x + 1;
538 }
539 if y + 1 > height {
540 height = y + 1;
541 }
542 }
543 let mut grid = Self {
544 width,
545 height,
546 diagonal_mode: false,
547 dense: false,
548 exclusions: vertices,
549 };
550 grid.rebalance();
551 grid
552 }
553}
554
555pub struct GridIntoIterator {
557 grid: Grid,
558 x: usize,
559 y: usize,
560}
561
562impl Iterator for GridIntoIterator {
563 type Item = (usize, usize);
564
565 fn next(&mut self) -> Option<Self::Item> {
566 if self.grid.dense {
567 loop {
568 if self.y == self.grid.height {
569 return None;
570 }
571 let r = (self.grid.has_vertex((self.x, self.y))).then_some((self.x, self.y));
572 self.x += 1;
573 if self.x == self.grid.width {
574 self.x = 0;
575 self.y += 1;
576 }
577 if r.is_some() {
578 return r;
579 }
580 }
581 } else {
582 self.grid.exclusions.pop()
583 }
584 }
585}
586
587impl FusedIterator for GridIntoIterator {}
588
589impl IntoIterator for Grid {
590 type Item = (usize, usize);
591 type IntoIter = GridIntoIterator;
592
593 #[must_use]
594 fn into_iter(self) -> Self::IntoIter {
595 GridIntoIterator {
596 grid: self,
597 x: 0,
598 y: 0,
599 }
600 }
601}
602
603pub struct GridIterator<'a> {
605 grid: &'a Grid,
606 x: usize,
607 y: usize,
608}
609
610impl Iterator for GridIterator<'_> {
611 type Item = (usize, usize);
612
613 fn next(&mut self) -> Option<Self::Item> {
614 if self.grid.dense {
615 loop {
616 if self.y == self.grid.height {
617 return None;
618 }
619 let r = (self.grid.has_vertex((self.x, self.y))).then_some((self.x, self.y));
620 self.x += 1;
621 if self.x == self.grid.width {
622 self.x = 0;
623 self.y += 1;
624 }
625 if r.is_some() {
626 return r;
627 }
628 }
629 } else {
630 self.grid
631 .exclusions
632 .get_index(self.x)
633 .inspect(|_| {
634 self.x += 1;
635 })
636 .copied()
637 }
638 }
639}
640
641impl FusedIterator for GridIterator<'_> {}
642
643impl<'a> IntoIterator for &'a Grid {
644 type Item = (usize, usize);
645 type IntoIter = GridIterator<'a>;
646
647 #[must_use]
648 fn into_iter(self) -> Self::IntoIter {
649 GridIterator {
650 grid: self,
651 x: 0,
652 y: 0,
653 }
654 }
655}
656
657pub struct EdgesIterator<'a> {
659 grid: &'a Grid,
660 x: usize,
661 y: usize,
662 i: usize,
663}
664
665impl Iterator for EdgesIterator<'_> {
666 type Item = ((usize, usize), (usize, usize));
667
668 fn next(&mut self) -> Option<Self::Item> {
669 loop {
670 if self.y == self.grid.height {
671 return None;
672 }
673 let x = self.x;
674 let y = self.y;
675 let other = match self.i {
676 0 => (x + 1, y),
677 1 => (x, y + 1),
678 2 => (x + 1, y + 1),
679 _ => (x - 1, y + 1),
680 };
681 self.i += 1;
682 if (x == 0 && self.i == 3) || self.i == 4 {
683 self.i = 0;
684 self.x += 1;
685 if self.x == self.grid.width {
686 self.x = 0;
687 self.y += 1;
688 }
689 }
690 if self.grid.has_edge((x, y), other) {
691 return Some(((x, y), other));
692 }
693 }
694 }
695}
696
697impl FusedIterator for EdgesIterator<'_> {}
698
699impl fmt::Debug for Grid {
700 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
701 let (present, absent) = if f.alternate() {
702 ('▓', '░')
703 } else {
704 ('#', '.')
705 };
706 let lines: Vec<_> = if f.sign_minus() {
707 (0..self.height).rev().collect()
708 } else {
709 (0..self.height).collect()
710 };
711 let last = *lines.last().unwrap();
712 for y in lines {
713 for x in 0..self.width {
714 write!(
715 f,
716 "{}",
717 if self.has_vertex((x, y)) {
718 present
719 } else {
720 absent
721 }
722 )?;
723 }
724 if y != last {
725 writeln!(f)?;
726 }
727 }
728 Ok(())
729 }
730}
731
732impl From<&Matrix<bool>> for Grid {
733 fn from(matrix: &Matrix<bool>) -> Self {
734 let mut grid = Self::new(matrix.columns, matrix.rows);
735 for ((r, c), &v) in matrix.items() {
736 if v {
737 grid.add_vertex((c, r));
738 }
739 }
740 grid
741 }
742}
743
744impl From<Matrix<bool>> for Grid {
745 fn from(matrix: Matrix<bool>) -> Self {
746 Self::from(&matrix)
747 }
748}
749
750impl PartialEq for Grid {
751 fn eq(&self, other: &Self) -> bool {
752 self.vertices_len() == other.vertices_len()
753 && self.iter().zip(other.iter()).all(|(a, b)| a == b)
754 }
755}
756
757impl Eq for Grid {}