diff --git a/binary-tree/Cargo.lock b/binary-tree/Cargo.lock index cb1c306..1afab6e 100644 --- a/binary-tree/Cargo.lock +++ b/binary-tree/Cargo.lock @@ -4,14 +4,25 @@ name = "binary-tree" version = "0.1.0" dependencies = [ - "rand 0.3.23", + "rand", ] [[package]] -name = "fuchsia-cprng" -version = "0.1.1" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] [[package]] name = "libc" @@ -20,70 +31,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] -name = "rand" -version = "0.3.23" +name = "ppv-lite86" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" -dependencies = [ - "libc", - "rand 0.4.6", -] +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.4.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" dependencies = [ - "fuchsia-cprng", "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", + "rand_chacha", + "rand_core", + "rand_hc", ] [[package]] -name = "rand_core" -version = "0.3.1" +name = "rand_chacha" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ - "rand_core 0.4.2", + "ppv-lite86", + "rand_core", ] [[package]] name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rdrand" -version = "0.4.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ - "rand_core 0.3.1", + "getrandom", ] [[package]] -name = "winapi" -version = "0.3.9" +name = "rand_hc" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "rand_core", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/binary-tree/Cargo.toml b/binary-tree/Cargo.toml index 7b3c5a5..98a8962 100644 --- a/binary-tree/Cargo.toml +++ b/binary-tree/Cargo.toml @@ -2,6 +2,7 @@ name = "binary-tree" version = "0.1.0" authors = ["You "] +edition = "2018" [dependencies] -rand = "0.3.14" +rand = "0.8" diff --git a/binary-tree/src/lib.rs b/binary-tree/src/lib.rs index 1692afc..92c51ba 100644 --- a/binary-tree/src/lib.rs +++ b/binary-tree/src/lib.rs @@ -1,18 +1,16 @@ #![allow(dead_code)] -extern crate rand; - // An ordered collection of `T`s. enum BinaryTree { Empty, - NonEmpty(Box>) + NonEmpty(Box>), } // A part of a BinaryTree. struct TreeNode { element: T, left: BinaryTree, - right: BinaryTree + right: BinaryTree, } #[test] @@ -26,37 +24,42 @@ fn binary_tree_size() { } #[test] -fn test_hand_building_tree_of_planets() { +fn build_binary_tree() { use self::BinaryTree::*; let jupiter_tree = NonEmpty(Box::new(TreeNode { element: "Jupiter", left: Empty, - right: Empty + right: Empty, })); + let mercury_tree = NonEmpty(Box::new(TreeNode { element: "Mercury", left: Empty, - right: Empty + right: Empty, })); + let mars_tree = NonEmpty(Box::new(TreeNode { element: "Mars", left: jupiter_tree, - right: mercury_tree + right: mercury_tree, })); + let venus_tree = NonEmpty(Box::new(TreeNode { element: "Venus", left: Empty, - right: Empty + right: Empty, })); + let uranus_tree = NonEmpty(Box::new(TreeNode { element: "Uranus", left: Empty, - right: venus_tree + right: venus_tree, })); + let tree = NonEmpty(Box::new(TreeNode { element: "Saturn", left: mars_tree, - right: uranus_tree + right: uranus_tree, })); assert_eq!(tree.walk(), @@ -80,18 +83,20 @@ impl BinaryTree { impl BinaryTree { fn add(&mut self, value: T) { match *self { - BinaryTree::Empty => + BinaryTree::Empty => { *self = BinaryTree::NonEmpty(Box::new(TreeNode { element: value, left: BinaryTree::Empty, - right: BinaryTree::Empty - })), - BinaryTree::NonEmpty(ref mut node) => + right: BinaryTree::Empty, + })) + } + BinaryTree::NonEmpty(ref mut node) => { if value <= node.element { node.left.add(value); } else { node.right.add(value); } + } } } } @@ -113,18 +118,22 @@ fn test_add_method_2() { let mut tree = BinaryTree::Empty; tree.add("Mercury"); tree.add("Venus"); - for planet in vec!["Mars", "Jupiter", "Saturn", "Uranus"] { + for planet in vec!["Mars", "Jupiter", "Saturn", "Uranus"] { tree.add(planet); } - assert_eq!(tree.walk(), - vec!["Jupiter", "Mars", "Mercury", "Saturn", "Uranus", "Venus"]); + assert_eq!( + tree.walk(), + vec!["Jupiter", "Mars", "Mercury", "Saturn", "Uranus", "Venus"] + ); } +// From chapter 15: Iterators + use self::BinaryTree::*; // The state of an in-order traversal of a `BinaryTree`. -struct TreeIter<'a, T: 'a> { +struct TreeIter<'a, T> { // A stack of references to tree nodes. Since we use `Vec`'s // `push` and `pop` methods, the top of the stack is the end of the // vector. @@ -164,14 +173,13 @@ impl<'a, T> Iterator for TreeIter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option<&'a T> { // Find the node this iteration must produce, - // or finish the iteration. - let node = match self.unvisited.pop() { - None => return None, - Some(n) => n - }; - - // The next node after this one is the leftmost child of - // this node's right child, so push the path from here down. + // or finish the iteration. (Use the `?` operator + // to return immediately if it's `None`.) + let node = self.unvisited.pop()?; + + // After `node`, the next thing we produce must be the leftmost + // child in `node`'s right subtree, so push the path from here + // down. Our helper method turns out to be just what we need. self.push_left_edge(&node.right); // Produce a reference to this node's value. @@ -188,24 +196,40 @@ fn external_iterator() { } // Build a small tree. - let subtree_l = make_node(Empty, "mecha", Empty); - let subtree_rl = make_node(Empty, "droid", Empty); - let subtree_r = make_node(subtree_rl, "robot", Empty); - let tree = make_node(subtree_l, "Jaeger", subtree_r); + let mut tree = BinaryTree::Empty; + tree.add("jaeger"); + tree.add("robot"); + tree.add("droid"); + tree.add("mecha"); // Iterate over it. let mut v = Vec::new(); for kind in &tree { v.push(*kind); } - assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]); + assert_eq!(v, ["droid", "jaeger", "mecha", "robot"]); + assert_eq!(tree.iter() + .map(|name| format!("mega-{}", name)) + .collect::>(), + vec!["mega-droid", "mega-jaeger", + "mega-mecha", "mega-robot"]); + + let mut iterator = (&tree).into_iter(); + assert_eq!(iterator.next(), Some(&"droid")); + assert_eq!(iterator.next(), Some(&"jaeger")); + assert_eq!(iterator.next(), Some(&"mecha")); + assert_eq!(iterator.next(), Some(&"robot")); + assert_eq!(iterator.next(), None); + + // Construct a tree by hand. let left_subtree = make_node(Empty, "mecha", Empty); let right_subtree = make_node(make_node(Empty, "droid", Empty), "robot", Empty); let tree = make_node(left_subtree, "Jaeger", right_subtree); + // Try initializing the iterator ourselves and see if it runs. let mut v = Vec::new(); let mut iter = TreeIter { unvisited: vec![] }; iter.push_left_edge(&tree); @@ -214,33 +238,23 @@ fn external_iterator() { } assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]); + // Iterate by shared reference. let mut v = Vec::new(); for kind in &tree { v.push(*kind); } assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]); + // Iterate, taking ownership. let mut v = Vec::new(); let mut state = tree.into_iter(); while let Some(kind) = state.next() { v.push(*kind); } assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]); - - assert_eq!(tree.iter() - .map(|name| format!("mega-{}", name)) - .collect::>(), - vec!["mega-mecha", "mega-Jaeger", - "mega-droid", "mega-robot"]); - - let mut iterator = tree.into_iter(); - assert_eq!(iterator.next(), Some(&"mecha")); - assert_eq!(iterator.next(), Some(&"Jaeger")); - assert_eq!(iterator.next(), Some(&"droid")); - assert_eq!(iterator.next(), Some(&"robot")); - assert_eq!(iterator.next(), None); } + #[test] fn other_cloned() { use std::collections::BTreeSet; @@ -257,13 +271,12 @@ fn other_cloned() { #[test] fn fuzz() { fn make_random_tree(p: f32) -> BinaryTree { - use rand::{ThreadRng, thread_rng}; - use rand::distributions::range::Range; - use rand::distributions::Sample; + use rand::prelude::*; + use rand::thread_rng; + use rand::rngs::ThreadRng; fn make(p: f32, next: &mut i32, rng: &mut ThreadRng) -> BinaryTree { - let mut range = Range::new(0.0, 1.0); - if range.sample(rng) > p { + if rng.gen_range(0.0 .. 1.0) > p { Empty } else { let left = make(p * p, next, rng);