1use std::ops::{Index, IndexMut};
33
34use crate::util::point::*;
35
36#[derive(Clone, Eq, Hash, PartialEq)]
37pub struct Grid<T> {
38 pub width: i32,
39 pub height: i32,
40 pub bytes: Vec<T>,
41}
42
43impl Grid<u8> {
44 #[must_use]
45 pub fn parse(input: &str) -> Self {
46 let raw: Vec<_> = input.lines().map(str::as_bytes).collect();
47
48 let width = raw[0].len() as i32;
49 let height = raw.len() as i32;
50 let bytes = raw.concat();
51
52 Self { width, height, bytes }
53 }
54
55 #[must_use]
56 pub fn parse_with_border(input: &str) -> Self {
57 let width = input.lines().next().unwrap().len() + 1;
63 let height = input.len().div_ceil(width) + 2;
64 let size = width * height + 1;
65 let mut bytes = Vec::with_capacity(size);
66
67 bytes.resize(width + 1, b'\n');
68 bytes.extend_from_slice(input.as_bytes());
69 bytes.resize(size, b'\n');
70
71 Self { width: width as i32, height: height as i32, bytes }
72 }
73
74 pub fn print(&self) {
75 for y in 0..self.height {
76 for x in 0..self.width {
77 let point = Point::new(x, y);
78 print!("{}", self[point] as char);
79 }
80 println!();
81 }
82 println!();
83 }
84}
85
86impl<T: Copy + PartialEq> Grid<T> {
87 #[must_use]
88 pub fn find(&self, needle: T) -> Option<Point> {
89 self.bytes
90 .iter()
91 .position(|&h| h == needle)
92 .map(|index| Point::new(index as i32 % self.width, index as i32 / self.width))
93 }
94}
95
96impl<T: Copy> Grid<T> {
97 #[must_use]
98 pub fn new(width: i32, height: i32, value: T) -> Self {
99 Self { width, height, bytes: vec![value; (width * height) as usize] }
100 }
101
102 #[must_use]
103 pub fn same_size_with<U: Copy>(&self, value: U) -> Grid<U> {
104 Grid::new(self.width, self.height, value)
105 }
106}
107
108impl<T> Grid<T> {
109 #[inline]
110 #[must_use]
111 pub fn contains(&self, point: Point) -> bool {
112 point.x >= 0 && point.x < self.width && point.y >= 0 && point.y < self.height
113 }
114}
115
116impl<T> Index<Point> for Grid<T> {
117 type Output = T;
118
119 #[inline]
120 fn index(&self, index: Point) -> &Self::Output {
121 &self.bytes[(self.width * index.y + index.x) as usize]
122 }
123}
124
125impl<T> IndexMut<Point> for Grid<T> {
126 #[inline]
127 fn index_mut(&mut self, index: Point) -> &mut Self::Output {
128 &mut self.bytes[(self.width * index.y + index.x) as usize]
129 }
130}