From 28f5d3ea1f9a6ad704c3e0182b0bbad1a77ec09c Mon Sep 17 00:00:00 2001 From: hheik <4469778+hheik@users.noreply.github.com> Date: Tue, 5 May 2026 17:24:24 +0300 Subject: [PATCH] get_node() now returns Result> to indicate tiles that are out of bounds. Fixed inconsistent spelling of neighbor -> neighbour --- src/lib.rs | 68 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 41c433a..5b69801 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ -/// A trait for graph-like structures, where you can get a node by a unique value and find its neighbors. +/// A trait for graph-like structures, where you can get a node by a unique value and find its +/// neighbours. /// /// **Node** represents some settled data type. The graph should likely contain `Option` /// elements prepopulated with `None` values. For example `[[None; WIDTH]; HEIGHT]` for a 2D grid. @@ -15,23 +16,33 @@ pub trait GraphLike { /// Used in the default implementation of `full_generation` const MAX_RETRIES: usize = 5; - fn get_node(&self, id: NodeId) -> Option<&Node>; + fn get_node(&self, id: NodeId) -> Result, ()>; fn set_node(&mut self, id: NodeId, node: Option); fn iter_ids(&self) -> impl Iterator; - fn iter_neighbor_ids(&self, id: NodeId) -> impl Iterator; + fn iter_neighbour_ids(&self, id: NodeId) -> impl Iterator; fn iter_nodes<'a>(&'a self) -> impl Iterator)> where Node: 'a, NodeId: Copy, { - self.iter_ids().map(|id| (id, self.get_node(id))) + self.iter_ids().map(|id| { + ( + id, + self.get_node(id) + .expect("GraphLike::iter_ids() should only return valid ids"), + ) + }) } fn iter_empty(&self) -> impl Iterator where NodeId: Copy, { - self.iter_ids().filter(|id| self.get_node(*id).is_none()) + self.iter_ids().filter(|id| { + self.get_node(*id) + .expect("GraphLike::iter_ids() should only return valid ids") + .is_none() + }) } fn iter_neighbour_nodes<'a>( &'a self, @@ -41,7 +52,13 @@ pub trait GraphLike { NodeId: Copy, Node: 'a, { - self.iter_neighbor_ids(id).map(|id| (id, self.get_node(id))) + self.iter_neighbour_ids(id).map(|id| { + ( + id, + self.get_node(id) + .expect("GraphLike::iter_neighbour_ids() should only return valid ids"), + ) + }) } fn single_step( @@ -144,8 +161,11 @@ mod tests { } impl GraphLike for TestGraph { - fn get_node(&self, id: (usize, usize)) -> Option<&u8> { - self.tiles[id.0][id.1].as_ref() + fn get_node(&self, id: (usize, usize)) -> Result, ()> { + if id.0 >= 3 || id.1 >= 3 { + return Err(()); + } + Ok(self.tiles[id.0][id.1].as_ref()) } fn set_node(&mut self, id: (usize, usize), node: Option) { @@ -156,25 +176,25 @@ mod tests { (0..3).flat_map(|i| (0..3).map(move |j| (i, j))) } - fn iter_neighbor_ids(&self, id: (usize, usize)) -> impl Iterator { - let mut neighbors = vec![]; + fn iter_neighbour_ids(&self, id: (usize, usize)) -> impl Iterator { + let mut neighbours = vec![]; if id.0 > 0 { - neighbors.push((id.0 - 1, id.1)); + neighbours.push((id.0 - 1, id.1)); } if id.0 < 2 { - neighbors.push((id.0 + 1, id.1)); + neighbours.push((id.0 + 1, id.1)); } if id.1 > 0 { - neighbors.push((id.0, id.1 - 1)); + neighbours.push((id.0, id.1 - 1)); } if id.1 < 2 { - neighbors.push((id.0, id.1 + 1)); + neighbours.push((id.0, id.1 + 1)); } - neighbors.into_iter() + neighbours.into_iter() } } - /// Entropy is the number of empty neighbors, and choose sets the value to the same value. + /// Entropy is the number of empty neighbours, and choose sets the value to the same value. /// Just for testing. struct TestRuleset; @@ -184,11 +204,11 @@ mod tests { graph: &impl GraphLike, id: (usize, usize), ) -> Option { - let neighbors = graph + let neighbours = graph .iter_neighbour_nodes(id) .filter(|n| n.1.is_some()) .count(); - Some(4_usize.strict_sub(neighbors) as f32) + Some(4_usize.strict_sub(neighbours) as f32) } fn choose( @@ -197,11 +217,11 @@ mod tests { id: (usize, usize), _retry_count: Option, ) -> Option { - let neighbors = graph + let neighbours = graph .iter_neighbour_nodes(id) .filter(|n| n.1.is_some()) .count(); - Some(4_usize.strict_sub(neighbors) as u8) + Some(4_usize.strict_sub(neighbours) as u8) } } @@ -215,8 +235,8 @@ mod tests { [None, None, None], ], }; - assert_eq!(graph.get_node((0, 0)), None); - assert_eq!(graph.get_node((1, 2)), Some(&99)); + assert_eq!(graph.get_node((0, 0)), Ok(None)); + assert_eq!(graph.get_node((1, 2)), Ok(Some(&99))); } #[test] @@ -290,14 +310,14 @@ mod tests { } #[test] - fn iter_neighbor_ids_works() { + fn iter_neighbour_ids_works() { // This really tests that the implementation itself works... let graph = TestGraph { tiles: [[None; 3]; 3], }; assert_eq!( graph - .iter_neighbor_ids((1, 1)) + .iter_neighbour_ids((1, 1)) .collect::>(), vec![(0, 1), (2, 1), (1, 0), (1, 2)] .into_iter()