From 741fcea09d6b4a886f028e2335177c2b39aae526 Mon Sep 17 00:00:00 2001 From: Abduaziz Kayumov Date: Wed, 27 Sep 2023 20:02:50 +0900 Subject: [PATCH 1/2] added failing tests --- src/access.rs | 2 +- src/lib.rs | 1 + src/link.rs | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src/link.rs diff --git a/src/access.rs b/src/access.rs index 1c60d15..5575e41 100644 --- a/src/access.rs +++ b/src/access.rs @@ -3,7 +3,7 @@ use crate::{ splay::splay, }; -// constructs a path from the root to the node at idx +// constructs a path from a node to the root of the tree pub fn access(forest: &mut Vec, node_idx: usize) { assert!(node_idx < forest.len(), "access: node_idx out of bounds"); splay(forest, node_idx); diff --git a/src/lib.rs b/src/lib.rs index 95ff508..27a8154 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![allow(dead_code, clippy::module_name_repetitions)] // yes, I want to name my structs with the same name as the file mod access; mod connected; +mod link; mod node; mod splay; diff --git a/src/link.rs b/src/link.rs new file mode 100644 index 0000000..2d67b05 --- /dev/null +++ b/src/link.rs @@ -0,0 +1,127 @@ +use crate::{ + access::access, + node::{Node, Parent}, +}; + +pub fn link(forest: &mut Vec, v: usize, w: usize) { + // todo +} + +#[cfg(test)] +mod tests { + use super::link; + use crate::{ + connected::connected, + node::{Node, Parent}, + }; + + fn create_nodes(n: usize) -> Vec { + (0..n).map(|i| Node::new(i, 0.0)).collect() + } + + #[test] + pub fn base_case() { + let mut forest = create_nodes(2); + assert!(!connected(&mut forest, 0, 1)); // not connected yet + super::link(&mut forest, 0, 1); + assert!(connected(&mut forest, 0, 1)); // now connected + } + + #[test] + pub fn already_connected() { + // '2' has a right child '3': + // link(0, 3) should do nothing, and result in: + // 0 3 + // / \ / + // 1 2 => 2 + // \ / + // 3 0 + // / + // 1 + // + let mut forest = create_nodes(4); + forest[0].left = Some(1); + forest[0].right = Some(2); + forest[1].parent = Parent::Node(0); + forest[2].parent = Parent::Node(0); + forest[2].right = Some(3); + forest[3].parent = Parent::Node(2); + link(&mut forest, 0, 3); + assert!(matches!(forest[3].parent, Parent::Root)); + assert_eq!(forest[3].left, Some(2)); + assert_eq!(forest[3].right, None); + assert!(matches!(forest[2].parent, Parent::Node(3))); + assert_eq!(forest[2].left, Some(0)); + assert_eq!(forest[2].right, None); + assert!(matches!(forest[0].parent, Parent::Node(2))); + assert_eq!(forest[0].left, Some(1)); + assert_eq!(forest[0].right, None); + assert!(matches!(forest[1].parent, Parent::Node(0))); + assert_eq!(forest[1].left, None); + assert_eq!(forest[1].right, None); + } + + #[test] + pub fn already_connected_with_path() { + // '3' has a path pointer to '2': + // link(0, 1) should do nothing, and result in: + // 0 2 3 + // / \ / \ / + // 1 2 => 0 3 => 2 + // | / / + // 3 1 0 + // / + // 1 + // + let mut forest = create_nodes(4); + forest[0].left = Some(1); + forest[0].right = Some(2); + forest[1].parent = Parent::Node(0); + forest[2].parent = Parent::Node(0); + forest[3].parent = Parent::Path(2); + link(&mut forest, 0, 3); + assert!(matches!(forest[3].parent, Parent::Root)); + assert_eq!(forest[3].left, Some(2)); + assert_eq!(forest[3].right, None); + assert!(matches!(forest[2].parent, Parent::Node(3))); + assert_eq!(forest[2].left, Some(0)); + assert_eq!(forest[2].right, None); + assert!(matches!(forest[0].parent, Parent::Node(2))); + assert_eq!(forest[0].left, Some(1)); + assert_eq!(forest[0].right, None); + assert!(matches!(forest[1].parent, Parent::Node(0))); + assert_eq!(forest[1].left, None); + assert_eq!(forest[1].right, None); + } + + #[test] + pub fn link_to_leftmost() { + // Given two trees: + // 0 3 + // / \ + // 1 2 + // link(1, 3) should result in a single tree (| denotes a path pointer): + // 1 3 1 + // | | \ + // 0 => 0 3 + // \ \ + // 2 2 + // + let mut forest = create_nodes(4); + forest[0].left = Some(1); + forest[0].right = Some(2); + forest[1].parent = Parent::Node(0); + forest[2].parent = Parent::Node(0); + link(&mut forest, 1, 3); + assert!(matches!(forest[1].parent, Parent::Root)); + assert_eq!(forest[1].right, Some(3)); + assert_eq!(forest[1].left, None); + assert!(matches!(forest[3].parent, Parent::Node(1))); + assert_eq!(forest[3].right, None); + assert_eq!(forest[3].left, None); + assert!(matches!(forest[0].parent, Parent::Path(1))); + assert_eq!(forest[0].right, Some(2)); + assert_eq!(forest[0].left, None); + assert!(matches!(forest[2].parent, Parent::Node(0))); + } +} From 659cb1b9937fb8cfb8e46416e8bf1bdc921b2f41 Mon Sep 17 00:00:00 2001 From: Abduaziz Kayumov Date: Wed, 27 Sep 2023 20:35:32 +0900 Subject: [PATCH 2/2] closes #4 --- src/link.rs | 67 ++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/link.rs b/src/link.rs index 2d67b05..e492a92 100644 --- a/src/link.rs +++ b/src/link.rs @@ -4,7 +4,14 @@ use crate::{ }; pub fn link(forest: &mut Vec, v: usize, w: usize) { - // todo + access(forest, v); + access(forest, w); + if !matches!(forest[v].parent, Parent::Root) || v == w { + return; // already connected + } + assert!(forest[w].right.is_none(), "link: w should be a root!"); + forest[w].right = Some(v); + forest[v].parent = Parent::Node(w); } #[cfg(test)] @@ -30,14 +37,12 @@ mod tests { #[test] pub fn already_connected() { // '2' has a right child '3': - // link(0, 3) should do nothing, and result in: - // 0 3 - // / \ / - // 1 2 => 2 - // \ / - // 3 0 - // / - // 1 + // link(0, 3) should add no link, and result in (| denotes a path pointer): + // 0 0 0 3 + // / \ / | / | / + // 1 2 => 1 2 => 1 3 => 0 + // \ \ / / \ + // 3 3 2 1 2 // let mut forest = create_nodes(4); forest[0].left = Some(1); @@ -48,30 +53,28 @@ mod tests { forest[3].parent = Parent::Node(2); link(&mut forest, 0, 3); assert!(matches!(forest[3].parent, Parent::Root)); - assert_eq!(forest[3].left, Some(2)); + assert_eq!(forest[3].left, Some(0)); assert_eq!(forest[3].right, None); - assert!(matches!(forest[2].parent, Parent::Node(3))); - assert_eq!(forest[2].left, Some(0)); - assert_eq!(forest[2].right, None); - assert!(matches!(forest[0].parent, Parent::Node(2))); + assert!(matches!(forest[0].parent, Parent::Node(3))); assert_eq!(forest[0].left, Some(1)); - assert_eq!(forest[0].right, None); + assert_eq!(forest[0].right, Some(2)); assert!(matches!(forest[1].parent, Parent::Node(0))); assert_eq!(forest[1].left, None); assert_eq!(forest[1].right, None); + assert!(matches!(forest[2].parent, Parent::Node(0))); + assert_eq!(forest[2].left, None); + assert_eq!(forest[2].right, None); } #[test] pub fn already_connected_with_path() { - // '3' has a path pointer to '2': - // link(0, 1) should do nothing, and result in: - // 0 2 3 - // / \ / \ / - // 1 2 => 0 3 => 2 - // | / / - // 3 1 0 - // / - // 1 + // '3' has a path pointer to '2', and '2' has a path pointer to '0': + // link(0, 1) should add no link, and result in (| denotes a path pointer): + // 0 0 0 3 + // / \ / | / | / + // 1 2 => 1 2 => 1 3 => 0 + // | | / / \ + // 3 3 2 1 2 // let mut forest = create_nodes(4); forest[0].left = Some(1); @@ -81,17 +84,17 @@ mod tests { forest[3].parent = Parent::Path(2); link(&mut forest, 0, 3); assert!(matches!(forest[3].parent, Parent::Root)); - assert_eq!(forest[3].left, Some(2)); + assert_eq!(forest[3].left, Some(0)); assert_eq!(forest[3].right, None); - assert!(matches!(forest[2].parent, Parent::Node(3))); - assert_eq!(forest[2].left, Some(0)); - assert_eq!(forest[2].right, None); - assert!(matches!(forest[0].parent, Parent::Node(2))); + assert!(matches!(forest[0].parent, Parent::Node(3))); assert_eq!(forest[0].left, Some(1)); - assert_eq!(forest[0].right, None); + assert_eq!(forest[0].right, Some(2)); assert!(matches!(forest[1].parent, Parent::Node(0))); assert_eq!(forest[1].left, None); assert_eq!(forest[1].right, None); + assert!(matches!(forest[2].parent, Parent::Node(0))); + assert_eq!(forest[2].left, None); + assert_eq!(forest[2].right, None); } #[test] @@ -112,7 +115,7 @@ mod tests { forest[0].right = Some(2); forest[1].parent = Parent::Node(0); forest[2].parent = Parent::Node(0); - link(&mut forest, 1, 3); + link(&mut forest, 3, 1); assert!(matches!(forest[1].parent, Parent::Root)); assert_eq!(forest[1].right, Some(3)); assert_eq!(forest[1].left, None); @@ -123,5 +126,7 @@ mod tests { assert_eq!(forest[0].right, Some(2)); assert_eq!(forest[0].left, None); assert!(matches!(forest[2].parent, Parent::Node(0))); + assert_eq!(forest[2].right, None); + assert_eq!(forest[2].left, None); } }