1#[cfg(feature = "prettytable")]
2#[macro_use] extern crate prettytable;
3#[cfg(feature = "prettytable")]
4use prettytable::{Table, Row, Cell};
5use std::fmt::Debug;
6
7#[derive(Copy, Clone, Debug)]
8pub struct GridPt {
9 pub row: usize,
10 pub col: usize
11}
12
13impl GridPt {
14 pub fn new(row: usize, col: usize) -> Self {
15 Self { row, col }
16 }
17
18 pub fn component_dist(pt1: GridPt, pt2: GridPt) -> (usize, usize) {
19 let rows = if pt1.row > pt2.row { pt1.row - pt2.row }
20 else { pt2.row - pt1.row };
21 let cols = if pt1.col > pt2.col { pt1.col - pt2.col }
22 else { pt2.col - pt1.col };
23 (rows, cols)
24 }
25
26 pub fn l1_dist(pt1: GridPt, pt2: GridPt) -> usize {
27 let (rows, cols) = Self::component_dist(pt1, pt2);
28 rows + cols
29 }
30
31 pub fn l2_dist(pt1: GridPt, pt2: GridPt) -> usize {
32 let (rows, cols) = Self::component_dist(pt1, pt2);
33 std::cmp::max(rows, cols)
34 }
35}
36
37#[derive(Debug)]
38pub struct Grid<T> {
39 pub rows: usize,
40 pub cols: usize,
41 pub cells: Vec<Vec<T>>,
42}
43
44impl<T> Grid<T>
45 where T: Debug+Clone
46{
47 pub fn new(rows: usize, cols: usize, default: T) -> Self {
48 Self {
49 rows,
50 cols,
51 cells: vec![vec![default; cols]; rows],
52 }
53 }
54}
55
56impl<T> Grid<T>
57 where T: Debug
58{
59 pub fn new_from(data: Vec<Vec<T>>) -> Self {
60 let rows = data.len();
61 let cols = data[0].len();
62 Self {
63 rows,
64 cols,
65 cells: data,
66 }
67 }
68
69 pub fn iter(&self) -> impl Iterator<Item=&T> {
70 self.cells.iter().flat_map(|row| row.iter())
71 }
72
73 pub fn rows(&self) -> impl Iterator<Item=&Vec<T>> {
74 self.cells.iter()
75 }
76
77 pub fn cols<'a>(&'a self) -> impl Iterator<Item=impl Iterator<Item=&'a T>> {
78 (0..self.cols)
79 .map(move |col_idx| self.cells.iter().map(move |row| &row[col_idx]))
80 }
81
82 pub fn get(&self, row_index: usize, col_index: usize) -> Option<&T> {
84 self.cells.get(row_index).and_then(|r| r.get(col_index))
85 }
86
87 pub fn eight_neighbors<'a>(&'a self, row_origin: usize, col_origin: usize)
88 -> impl Iterator<Item=&'a T>
89 {
90 (-1..2 as i32)
91 .flat_map(|row| std::iter::repeat(row).zip(-1..2 as i32))
92 .filter(|(row, col)| !(*row == 0 && *col == 0))
93 .filter_map(move |(row, col)|
94 self.cells
95 .get((row_origin as i32 + row) as usize)
96 .and_then(|r| r.get((col_origin as i32 + col) as usize)))
97 }
98
99 pub fn l1_dist(&self, pt1: GridPt, pt2: GridPt) -> usize {
100 GridPt::l1_dist(pt1, pt2)
101 }
102
103 pub fn right_from(&self, row: usize, col: usize) -> impl Iterator<Item=&T> {
104 self.cells[row][col+1..].iter()
105 }
106
107 pub fn left_from(&self, row: usize, col: usize) -> impl Iterator<Item=&T> {
108 self.cells[row][..col].iter().rev()
109 }
110
111 pub fn up_from(&self, row: usize, col: usize) -> impl Iterator<Item=&T> {
112 self.cells[..row].iter()
113 .map(move |row_vec| &row_vec[col])
114 .rev()
115 }
116 pub fn down_from(&self, row: usize, col: usize) -> impl Iterator<Item=&T> {
117 self.cells[row+1..].iter()
118 .map(move |row_vec| &row_vec[col])
119 }
120}
121
122#[cfg(feature = "prettytable")]
123impl<T> Grid<T>
124 where T: Clone+Debug+ToString
125{
126 pub fn pretty_table(&self) -> Table {
127 let mut table = Table::new();
128 for row in self.rows() {
129 table.add_row(Row::new(
130 row.iter().map(|cell| Cell::new(&cell.to_string())).collect()));
131 }
132 table
133 }
134}
135
136#[cfg(test)]
161mod tests {
162 #[test]
163 fn gridpt_component_dist() {
164 let pt1 = super::GridPt::new(4, 5);
165 let pt2 = super::GridPt::new(7, 7);
166 assert_eq!((3, 2), super::GridPt::component_dist(pt1, pt2));
167 assert_eq!((3, 2), super::GridPt::component_dist(pt2, pt1));
168 }
169
170 #[test]
171 fn gridpt_l1_dist() {
172 let pt1 = super::GridPt::new(4, 5);
173 let pt2 = super::GridPt::new(7, 7);
174 assert_eq!(5, super::GridPt::l1_dist(pt1, pt2));
175 assert_eq!(5, super::GridPt::l1_dist(pt2, pt1));
176 }
177
178 #[test]
179 fn grid_new() {
180 let rows = 8;
181 let cols = 10;
182 let grid = super::Grid::<Option<usize>>::new(rows, cols, None);
183 assert_eq!(grid.rows, rows);
184 assert_eq!(grid.cols, cols);
185 assert_eq!(grid.cells.len(), rows);
186 assert_eq!(grid.cells[0].len(), cols);
187 }
188
189 #[test]
190 fn grid_new_from() {
191 let data = vec![
192 vec![1, 2, 3, 4],
193 vec![5, 6, 7, 8],
194 vec![9, 10, 11, 12],
195 ];
196 let grid = super::Grid::<usize>::new_from(data);
197 assert_eq!(grid.rows, 3);
198 assert_eq!(grid.cols, 4);
199 assert_eq!(grid.cells.len(), 3);
200 assert_eq!(grid.cells[0].len(), 4);
201 }
202
203 #[test]
204 fn grid_iter() {
205 let rows = 4;
206 let cols = 5;
207 let grid = super::Grid::<usize>::new(rows, cols, 1);
208 assert_eq!(grid.iter().sum::<usize>(), rows*cols);
209 }
210
211 #[test]
212 fn grid_rows() {
213 let data = vec![
214 vec![1, 2, 3, 4],
215 vec![5, 6, 7, 8],
216 vec![9, 10, 11, 12],
217 ];
218 let grid = super::Grid::<usize>::new_from(data);
219 let mut iter = grid.rows();
220 assert_eq!(Some(&vec![1,2,3,4]), iter.next());
221 assert_eq!(Some(&vec![5,6,7,8]), iter.next());
222 assert_eq!(Some(&vec![9,10,11,12]), iter.next());
223 assert_eq!(None, iter.next());
224 }
225
226 #[test]
227 fn grid_cols() {
228 let data = vec![
229 vec![1, 2, 3, 4],
230 vec![5, 6, 7, 8],
231 vec![9, 10, 11, 12],
232 ];
233 let grid = super::Grid::<usize>::new_from(data);
234 let mut iter = grid.cols();
235 assert_eq!(vec![&1, &5, &9], iter.next().unwrap().collect::<Vec<&usize>>());
236 assert_eq!(vec![&2, &6, &10], iter.next().unwrap().collect::<Vec<&usize>>());
237 assert_eq!(vec![&3, &7, &11], iter.next().unwrap().collect::<Vec<&usize>>());
238 assert_eq!(vec![&4, &8, &12], iter.next().unwrap().collect::<Vec<&usize>>());
239 assert!(iter.next().is_none());
240 }
241
242 #[test]
243 fn grid_eight_neighbors() {
244 let rows = 4;
245 let cols = 5;
246 let grid = super::Grid::<usize>::new(rows, cols, 1);
247 assert_eq!(grid.eight_neighbors(0, 0).sum::<usize>(), 3);
248 assert_eq!(grid.eight_neighbors(1, 1).sum::<usize>(), 8);
249 assert_eq!(grid.eight_neighbors(3, 4).sum::<usize>(), 3);
250 assert_eq!(grid.eight_neighbors(10, 10).sum::<usize>(), 0);
251 assert_eq!(grid.eight_neighbors(0, 1).sum::<usize>(), 5);
252 }
253
254 #[test]
255 fn grid_right_from() {
256 let data = vec![
257 vec![1, 2, 3, 4],
258 vec![5, 6, 7, 8],
259 vec![9, 10, 11, 12],
260 ];
261 let grid = super::Grid::<usize>::new_from(data);
262 let mut iter = grid.right_from(2, 1);
263 assert_eq!(Some(&11), iter.next());
264 assert_eq!(Some(&12), iter.next());
265 assert!(iter.next().is_none());
266 }
267
268 #[test]
269 fn grid_left_from() {
270 let data = vec![
271 vec![1, 2, 3, 4],
272 vec![5, 6, 7, 8],
273 vec![9, 10, 11, 12],
274 ];
275 let grid = super::Grid::<usize>::new_from(data);
276 let mut iter = grid.left_from(1, 2);
277 assert_eq!(Some(&6), iter.next());
278 assert_eq!(Some(&5), iter.next());
279 assert!(iter.next().is_none());
280 }
281
282 #[test]
283 fn grid_up_from() {
284 let data = vec![
285 vec![1, 2, 3, 4],
286 vec![5, 6, 7, 8],
287 vec![9, 10, 11, 12],
288 ];
289 let grid = super::Grid::<usize>::new_from(data);
290 let mut iter = grid.up_from(2, 1);
291 assert_eq!(Some(&6), iter.next());
292 assert_eq!(Some(&2), iter.next());
293 assert!(iter.next().is_none());
294 }
295
296 #[test]
297 fn grid_down_from() {
298 let data = vec![
299 vec![1, 2, 3, 4],
300 vec![5, 6, 7, 8],
301 vec![9, 10, 11, 12],
302 ];
303 let grid = super::Grid::<usize>::new_from(data);
304 let mut iter = grid.down_from(0, 2);
305 assert_eq!(Some(&7), iter.next());
306 assert_eq!(Some(&11), iter.next());
307 assert!(iter.next().is_none());
308 }
309}