1use crate::util::point::*;
28use std::ops::{Index, IndexMut};
29
30#[derive(Clone, PartialEq, Eq, Hash)]
31pub struct Grid<T> {
32 pub width: i32,
33 pub height: i32,
34 pub bytes: Vec<T>,
35}
36
37impl Grid<u8> {
38 #[inline]
39 pub fn parse(input: &str) -> Self {
40 let raw: Vec<_> = input.lines().map(str::as_bytes).collect();
41 let width = raw[0].len() as i32;
42 let height = raw.len() as i32;
43 let mut bytes = Vec::with_capacity((width * height) as usize);
44 raw.iter().for_each(|slice| bytes.extend_from_slice(slice));
45 Grid { width, height, bytes }
46 }
47
48 pub fn print(&self) {
49 for y in 0..self.height {
50 for x in 0..self.width {
51 let point = Point::new(x, y);
52 print!("{}", self[point] as char);
53 }
54 println!();
55 }
56 println!();
57 }
58}
59
60impl<T: Copy + PartialEq> Grid<T> {
61 #[inline]
62 pub fn find(&self, needle: T) -> Option<Point> {
63 let to_point = |index| {
64 let x = (index as i32) % self.width;
65 let y = (index as i32) / self.width;
66 Point::new(x, y)
67 };
68 self.bytes.iter().position(|&h| h == needle).map(to_point)
69 }
70}
71
72impl<T: Copy> Grid<T> {
73 pub fn new(width: i32, height: i32, value: T) -> Grid<T> {
74 Grid { width, height, bytes: vec![value; (width * height) as usize] }
75 }
76}
77
78impl<T> Grid<T> {
79 #[inline]
80 pub fn same_size_with<U: Copy>(&self, value: U) -> Grid<U> {
81 Grid {
82 width: self.width,
83 height: self.height,
84 bytes: vec![value; (self.width * self.height) as usize],
85 }
86 }
87
88 #[inline]
89 pub fn contains(&self, point: Point) -> bool {
90 point.x >= 0 && point.x < self.width && point.y >= 0 && point.y < self.height
91 }
92}
93
94impl<T> Index<Point> for Grid<T> {
95 type Output = T;
96
97 #[inline]
98 fn index(&self, index: Point) -> &Self::Output {
99 &self.bytes[(self.width * index.y + index.x) as usize]
100 }
101}
102
103impl<T> IndexMut<Point> for Grid<T> {
104 #[inline]
105 fn index_mut(&mut self, index: Point) -> &mut Self::Output {
106 &mut self.bytes[(self.width * index.y + index.x) as usize]
107 }
108}