1use crate::adjacency_list::ToAdjacencyList;
2use std::{collections::HashSet, fmt::Debug, hash::Hash};
3
4#[derive(Eq, Hash, PartialEq, Clone, Debug)]
5pub struct Rock(usize, usize);
6
7impl Rock {
8 pub fn x(&self) -> usize {
9 self.0
10 }
11
12 pub fn y(&self) -> usize {
13 self.1
14 }
15
16 pub fn new(x: usize, y: usize) -> Self {
17 Self(x, y)
18 }
19
20 pub fn new_multi(positions: Vec<(usize, usize)>) -> Vec<Rock> {
21 positions
22 .iter()
23 .map(|pos| Rock::new(pos.0, pos.1))
24 .collect()
25 }
26}
27
28pub struct Grid {
29 width: usize,
30 height: usize,
31 rocks: HashSet<Rock>,
32}
33
34impl Grid {
35 pub fn width(&self) -> usize {
36 self.width
37 }
38 pub fn height(&self) -> usize {
39 self.height
40 }
41
42 pub fn new_empty(width: usize, height: usize) -> Self {
43 Self {
44 width,
45 height,
46 ..Default::default()
47 }
48 }
49
50 pub fn new(width: usize, height: usize, rocks: Vec<Rock>) -> Self {
51 let mut grid = Self {
52 width,
53 height,
54 ..Default::default()
55 };
56 let _ = grid.add_rocks(rocks);
57 grid
58 }
59
60 pub fn checked_new(width: usize, height: usize, rocks: Vec<Rock>) -> Result<Self, Vec<Rock>> {
61 let mut grid = Self {
62 width,
63 height,
64 ..Default::default()
65 };
66 let failed = grid.add_rocks(rocks);
67 match failed {
68 None => Ok(grid),
69 Some(failed) => Err(failed),
70 }
71 }
72
73 pub fn add_rocks(&mut self, rocks: Vec<Rock>) -> Option<Vec<Rock>> {
77 let mut failed: Vec<Rock> = Vec::new();
78 for rock in rocks {
79 if rock.x() < self.width() && rock.y() < self.height() {
80 self.rocks.insert(rock);
81 } else {
82 failed.push(rock);
83 }
84 }
85 if failed.len() > 0 {
86 Some(failed)
87 } else {
88 None
89 }
90 }
91
92 pub fn remove_rocks(&mut self, rocks: &Vec<Rock>) {
93 for rock in rocks {
94 self.rocks.remove(rock);
95 }
96 }
97
98 pub fn is_rock(&self, x: usize, y: usize) -> bool {
99 self.rocks.contains(&Rock::new(x, y))
100 }
101
102 pub fn capacity(&self) -> Option<usize> {
103 self.width().checked_mul(self.height())
104 }
105}
106
107impl Default for Grid {
108 fn default() -> Self {
109 Self {
110 width: 10,
111 height: 10,
112 rocks: HashSet::new(),
113 }
114 }
115}
116
117impl<T> ToAdjacencyList<T> for Grid
118where
119 T: PartialOrd + Debug + Eq + Clone + Hash,
120{
121 fn to_adjacency_list(&self) -> crate::adjacency_list::AdjacencyList<T> {
122 todo!();
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn create_grid() {
132 let width = 347;
133 let height = 149;
134 let grid = Grid::new_empty(width, height);
135
136 assert_eq!(width, grid.width());
137 assert_eq!(height, grid.height());
138 }
139
140 #[test]
141 fn create_grid_with_rocks() {
142 let width = 40;
143 let height = 100;
144 let rocks = Rock::new_multi(vec![(1, 0), (2, 0), (3, 0)]);
145 let grid = Grid::new(width, height, rocks.clone());
146 for rock in rocks {
147 assert!(grid.is_rock(rock.x(), rock.y()));
148 }
149 }
150
151 #[test]
152 #[should_panic]
153 fn fail_when_rock_out_of_place() {
154 let width = 1;
155 let height = 1;
156 let rocks = Rock::new_multi(vec![
157 (0, 0),
159 (2, 0),
161 ]);
162 Grid::checked_new(width, height, rocks).unwrap();
163 }
164}