Revising binary tree

This commit is contained in:
vandomej 2021-09-30 16:39:30 -07:00
parent 9662155604
commit de4a44c93e
3 changed files with 128 additions and 138 deletions

View file

@ -297,12 +297,13 @@ where
} }
} }
impl<T: fmt::Display> fmt::Display for FileLinked<T> impl<T> fmt::Debug for FileLinked<T>
where where
T: Serialize, T: fmt::Debug
+ Serialize,
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.val) write!(f, "{:?}", self.val)
} }
} }

View file

@ -10,7 +10,6 @@ use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use std::string::ToString;
/// As the bracket tree increases in height, `IterationScaling` can be used to configure the number of iterations that /// As the bracket tree increases in height, `IterationScaling` can be used to configure the number of iterations that
/// a node runs for. /// a node runs for.
@ -37,12 +36,6 @@ use std::string::ToString;
/// # } /// # }
/// # } /// # }
/// # /// #
/// # impl fmt::Display for TestState {
/// # fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// # write!(f, "{}", self.score)
/// # }
/// # }
/// #
/// # impl TestState { /// # impl TestState {
/// # fn new(score: f64) -> TestState { /// # fn new(score: f64) -> TestState {
/// # TestState { score: score } /// # TestState { score: score }
@ -84,7 +77,7 @@ use std::string::ToString;
/// # std::fs::remove_file("./temp").expect("Unable to remove file"); /// # std::fs::remove_file("./temp").expect("Unable to remove file");
/// # } /// # }
/// ``` /// ```
#[derive(Clone, Debug, Serialize, Deserialize, Copy)] #[derive(Clone, Serialize, Deserialize, Copy)]
#[serde(tag = "enumType", content = "enumContent")] #[serde(tag = "enumType", content = "enumContent")]
pub enum IterationScaling { pub enum IterationScaling {
/// Scales the number of simulations linearly with the height of the bracket tree given by `f(x) = mx` where /// Scales the number of simulations linearly with the height of the bracket tree given by `f(x) = mx` where
@ -100,7 +93,7 @@ impl Default for IterationScaling {
} }
} }
impl fmt::Display for IterationScaling { impl fmt::Debug for IterationScaling {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
f, f,
@ -116,7 +109,7 @@ impl fmt::Display for IterationScaling {
/// individuals. /// individuals.
/// ///
/// [`GeneticNode`]: genetic_node::GeneticNode /// [`GeneticNode`]: genetic_node::GeneticNode
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone)]
pub struct Bracket<T> pub struct Bracket<T>
where where
T: genetic_node::GeneticNode, T: genetic_node::GeneticNode,
@ -125,9 +118,10 @@ where
iteration_scaling: IterationScaling, iteration_scaling: IterationScaling,
} }
impl<T: fmt::Display + Serialize> fmt::Display for Bracket<T> impl<T> fmt::Debug for Bracket<T>
where where
T: genetic_node::GeneticNode, T: genetic_node::GeneticNode
+ Serialize
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
@ -141,13 +135,11 @@ where
impl<T> Bracket<T> impl<T> Bracket<T>
where where
T: genetic_node::GeneticNode T: genetic_node::GeneticNode
+ ToString + FromStr
+ FromStr + Default
+ Default + DeserializeOwned
+ fmt::Display + Serialize
+ DeserializeOwned + Clone,
+ Serialize
+ Clone,
{ {
/// Initializes a bracket of type `T` storing the contents to `file_path` /// Initializes a bracket of type `T` storing the contents to `file_path`
/// ///
@ -160,7 +152,7 @@ where
/// # use std::str::FromStr; /// # use std::str::FromStr;
/// # use std::string::ToString; /// # use std::string::ToString;
/// # /// #
/// #[derive(Default, Deserialize, Serialize, Clone)] /// #[derive(Default, Deserialize, Serialize, Debug, Clone)]
/// struct TestState { /// struct TestState {
/// pub score: f64, /// pub score: f64,
/// } /// }
@ -215,9 +207,9 @@ where
/// .expect("Bracket failed to initialize"); /// .expect("Bracket failed to initialize");
/// ///
/// assert_eq!( /// assert_eq!(
/// format!("{}", bracket), /// format!("{:?}", bracket),
/// format!("{{\"tree\":{},\"iteration_scaling\":{{\"enumType\":\"Constant\",\"enumContent\":1}}}}", /// format!("{{\"tree\":{:?},\"iteration_scaling\":{{\"enumType\":\"Constant\",\"enumContent\":1}}}}",
/// btree!(TestState::new(0.0))) /// btree!(TestState{score: 0.0}))
/// ); /// );
/// ///
/// std::fs::remove_file("./temp").expect("Unable to remove file"); /// std::fs::remove_file("./temp").expect("Unable to remove file");
@ -441,11 +433,10 @@ mod tests {
use super::*; use super::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use std::string::ToString; use std::string::ToString;
#[derive(Default, Deserialize, Serialize, Clone)] #[derive(Default, Deserialize, Serialize, Clone, Debug)]
struct TestState { struct TestState {
pub score: f64, pub score: f64,
} }
@ -458,18 +449,6 @@ mod tests {
} }
} }
impl fmt::Display for TestState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.score)
}
}
impl TestState {
fn new(score: f64) -> TestState {
TestState { score: score }
}
}
impl genetic_node::GeneticNode for TestState { impl genetic_node::GeneticNode for TestState {
fn simulate(&mut self, iterations: u64) -> Result<(), String> { fn simulate(&mut self, iterations: u64) -> Result<(), String> {
self.score += iterations as f64; self.score += iterations as f64;
@ -499,9 +478,9 @@ mod tests {
.expect("Bracket failed to initialize"); .expect("Bracket failed to initialize");
assert_eq!( assert_eq!(
format!("{}", bracket), format!("{:?}", bracket),
format!("{{\"tree\":{},\"iteration_scaling\":{{\"enumType\":\"Constant\",\"enumContent\":1}}}}", format!("{{\"tree\":{:?},\"iteration_scaling\":{{\"enumType\":\"Constant\",\"enumContent\":1}}}}",
btree!(TestState::new(0.0))) btree!(TestState{score: 0.0}))
); );
std::fs::remove_file("./temp").expect("Unable to remove file"); std::fs::remove_file("./temp").expect("Unable to remove file");
@ -522,27 +501,27 @@ mod tests {
} }
assert_eq!( assert_eq!(
format!("{}", bracket), format!("{:?}", bracket),
format!("{{\"tree\":{},\"iteration_scaling\":{{\"enumType\":\"Linear\",\"enumContent\":2}}}}", format!("{{\"tree\":{:?},\"iteration_scaling\":{{\"enumType\":\"Linear\",\"enumContent\":2}}}}",
btree!( btree!(
TestState::new(12.0), TestState{score: 12.0},
btree!( btree!(
TestState::new(12.0), TestState{score: 12.0},
btree!(TestState::new(6.0), btree!(TestState{score: 6.0},
btree!(TestState::new(2.0)), btree!(TestState{score: 2.0}),
btree!(TestState::new(2.0))), btree!(TestState{score: 2.0})),
btree!(TestState::new(6.0), btree!(TestState{score: 6.0},
btree!(TestState::new(2.0)), btree!(TestState{score: 2.0}),
btree!(TestState::new(2.0))) btree!(TestState{score: 2.0}))
), ),
btree!( btree!(
TestState::new(12.0), TestState{score: 12.0},
btree!(TestState::new(6.0), btree!(TestState{score: 6.0},
btree!(TestState::new(2.0)), btree!(TestState{score: 2.0}),
btree!(TestState::new(2.0))), btree!(TestState{score: 2.0})),
btree!(TestState::new(6.0), btree!(TestState{score: 6.0},
btree!(TestState::new(2.0)), btree!(TestState{score: 2.0}),
btree!(TestState::new(2.0)))) btree!(TestState{score: 2.0})))
) )
) )
); );

View file

@ -2,25 +2,18 @@
//! //!
//! # Examples //! # Examples
//! //!
//! ```no_run
//! //let mut t = Tree::new(1, None, None);
//! //let t2 = Tree::new(2, Some(Box::new(t)), Some(Box::new(Tree::new(3, None, None))));
//! //let s = format!("{}", t2);
//!
//! //assert_eq!(s, "(2: (1: _|_)|(3: _|_))");
//! //t.left = Some(Box::new(Tree::new(4, None, None)));
//! //assert_eq!(Tree::fmt_node(t.left), 4);
//! //assert_eq!(Tree::from_str(s), t2);
//! ``` //! ```
//! //! use gemla::btree;
//! Additionally the `btree!` macro can be used to conveniently initialize trees: //!
//! //! // Tree with 2 nodes, one root node and one on the left side
//! ```no_run //! let mut t = btree!(1, btree!(2),);
//! //# #[macro_use] extern crate tree; //!
//! //# fn main() { //! assert_eq!(t.height(), 2);
//! //let t1 = btree!(1,btree!(2),btree!(3)) //! assert_eq!(t.left.unwrap().val, 2);
//! //assert_eq!(format!("{}", t1), "(1: (2: _|_)|(3: _|_)") //! assert_eq!(t.right, None);
//! //# } //!
//! t.right = Some(Box::new(btree!(3)));
//! assert_eq!(t.right.unwrap().val, 3);
//! ``` //! ```
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
@ -34,52 +27,62 @@ use std::str::FromStr;
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// //let mut t = Tree::new(1, None, None); /// use gemla::btree;
/// //let t2 = Tree::new(2, Some(Box::new(t)), Some(Box::new(Tree::new(3, None, None)))); ///
/// //let s = format!("{}", t2); /// // Tree with 2 nodes, one root node and one on the left side
/// /// let mut t = btree!(1, btree!(2),);
/// //assert_eq!(s, "(2: (1: _|_)|(3: _|_))"); ///
/// //t.left = Some(Box::new(Tree::new(4, None, None))); /// assert_eq!(t.height(), 2);
/// //assert_eq!(Tree::fmt_node(t.left), 4); /// assert_eq!(t.left.unwrap().val, 2);
/// //assert_eq!(Tree::from_str(s), t2); /// assert_eq!(t.right, None);
///
/// t.right = Some(Box::new(btree!(3)));
/// assert_eq!(t.right.unwrap().val, 3);
/// ``` /// ```
/// #[derive(Default, Serialize, Deserialize, Clone, PartialEq)]
/// Additionally the `btree!` macro can be used to conveniently initialize trees:
///
/// ```
/// //let t1 = btree!(1,btree!(2),btree!(3))
/// //assert_eq!(format!("{}", t1), "(1: (2: _|_)|(3: _|_)")
/// ```
#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct Tree<T> { pub struct Tree<T> {
pub val: T, pub val: T,
pub left: Option<Box<Tree<T>>>, pub left: Option<Box<Tree<T>>>,
pub right: Option<Box<Tree<T>>>, pub right: Option<Box<Tree<T>>>,
} }
/// Used to construct trees in a cleaner manner. `btree!` takes 3 arguments, the first being the /// Short-hand for constructing Trees. `btree!` takes 3 arguments, the first being the
/// value of the root node, and the other two being child nodes. The last two arguments are /// value of the root node, and the other two being child nodes. The last two arguments are
/// optional. /// optional.
/// ///
/// ```no_run /// ```
/// //#[macro_use] /// use gemla::tree::*;
/// //extern crate gemla; /// use gemla::btree;
/// // ///
/// //use gemla::*; /// # fn main() {
/// // /// // A tree with two child nodes.
/// //fn main() { /// let t = btree!(1, btree!(2), btree!(3));
/// // // A tree with two child nodes. /// assert_eq!(t,
/// // let t = btree!(1, Some(btree!(2)), Some(btree!(3))); /// Tree::new(1,
/// // /// Some(Box::new(Tree::new(2, None, None))),
/// // // A tree with only a left node. /// Some(Box::new(Tree::new(3, None, None)))));
/// // let t_left = btree!(1, Some(btree!(2)),); ///
/// // /// // A tree with only a left node.
/// // // A tree with only a right node. /// let t_left = btree!(1, btree!(2),);
/// // let t_right = btree!(1, ,Some(btree!(3))); /// assert_eq!(t_left,
/// // /// Tree::new(1,
/// // // A tree with no children nodes. /// Some(Box::new(Tree::new(2, None, None))),
/// // let t_single = btree!(1); /// None));
/// //} ///
/// // A tree with only a right node.
/// let t_right = btree!(1, , btree!(3));
/// assert_eq!(t_right,
/// Tree::new(1,
/// None,
/// Some(Box::new(Tree::new(3, None, None)))));
///
/// // A tree with no child nodes.
/// let t_single = btree!(1);
/// assert_eq!(t_single,
/// Tree::new(1,
/// None,
/// None));
/// # }
/// ``` /// ```
#[macro_export] #[macro_export]
macro_rules! btree { macro_rules! btree {
@ -98,11 +101,39 @@ macro_rules! btree {
} }
impl<T> Tree<T> { impl<T> Tree<T> {
/// Constructs a new tree object. /// Constructs a new [`Tree`] object
///
/// # Examples
///
/// ```
/// use gemla::tree::*;
///
/// let t = Tree::new(1, None, None);
/// assert_eq!(t, Tree {
/// val: 1,
/// left: None,
/// right: None
/// });
/// ```
pub fn new(val: T, left: Option<Box<Tree<T>>>, right: Option<Box<Tree<T>>>) -> Tree<T> { pub fn new(val: T, left: Option<Box<Tree<T>>>, right: Option<Box<Tree<T>>>) -> Tree<T> {
Tree { val, left, right } Tree { val, left, right }
} }
/// Obtains the height of the longest branch in a [`Tree`]
///
/// # Examples
///
/// ```
/// use gemla::tree::*;
/// use gemla::btree;
///
/// let t =
/// btree!("a",
/// btree!("aa",
/// btree!("aaa"),),
/// btree!("ab"));
/// assert_eq!(t.height(), 3);
/// ```
pub fn height(&self) -> u64 { pub fn height(&self) -> u64 {
match (self.left.as_ref(), self.right.as_ref()) { match (self.left.as_ref(), self.right.as_ref()) {
(Some(l), Some(r)) => max(l.height(), r.height()) + 1, (Some(l), Some(r)) => max(l.height(), r.height()) + 1,
@ -111,19 +142,9 @@ impl<T> Tree<T> {
_ => 1, _ => 1,
} }
} }
pub fn fmt_node(t: &Option<Box<Tree<T>>>) -> String
where
T: fmt::Display,
{
match t {
Some(n) => format!("{}", (*n).val),
_ => String::from("_"),
}
}
} }
impl<T: fmt::Display + Serialize> fmt::Display for Tree<T> { impl<T: fmt::Debug + Serialize> fmt::Debug for Tree<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let result = serde_json::to_string(self); let result = serde_json::to_string(self);
@ -168,7 +189,7 @@ mod tests {
#[test] #[test]
fn test_fmt() { fn test_fmt() {
assert_eq!( assert_eq!(
format!("{}", btree!("foo", btree!("bar"),),), format!("{:?}", btree!("foo", btree!("bar"),),),
"{\"val\":\"foo\",\"left\":{\"val\":\"bar\",\"left\":null,\"right\":null},\"right\":null}" "{\"val\":\"foo\",\"left\":{\"val\":\"bar\",\"left\":null,\"right\":null},\"right\":null}"
); );
} }
@ -179,15 +200,4 @@ mod tests {
assert_eq!(3, btree!(1, btree!(2), btree!(2, btree!(3),)).height()); assert_eq!(3, btree!(1, btree!(2), btree!(2, btree!(3),)).height());
} }
#[test]
fn test_fmt_node() {
let t = btree!(17, btree!(16), btree!(12));
assert_eq!(Tree::fmt_node(&t.left), "16");
assert_eq!(
Tree::fmt_node(&Some(Box::new(btree!(btree!("foo"))))),
"{\"val\":\"foo\",\"left\":null,\"right\":null}"
);
assert_eq!(Tree::<i32>::fmt_node(&None), "_");
}
} }