grid/
lib.rs

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    // todo can this be done similar to how vec uses deref<target=[t]>?
83    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//pub struct LinearIter<'a, T: 'a> {
137//    pub inner: &'a Grid<T>,
138//    pub row: usize,
139//    pub col: usize,
140//}
141//
142//impl<'a, T> Iterator for LinearIter<'a, T> {
143//    type Item = &'a T;
144//
145//    fn next(&mut self) -> Option<Self::Item> {
146//        if self.row < self.inner.rows && self.col < self.inner.cols {
147//            let ret = Some(self.inner.cells.get(self.row).unwrap()
148//                                           .get(self.col).unwrap());
149//            self.col += 1;
150//            if self.col == self.inner.cols {
151//                self.col = 0;
152//                self.row += 1;
153//            }
154//            return ret
155//        }
156//        None
157//    }
158//}
159
160#[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}