I am trying to find the diameter of a BST using parallelization:
extern crate rayon;
use std::cmp::Ordering::*;
use std::ops::Index;
use rayon::prelude::*;
#[derive(Debug)]
struct Node<K> {
left: Option<Box<Node<K>>>,
right: Option<Box<Node<K>>>,
key: K,
}
impl<K> Node<K> {
fn new(k: K) -> Node<K> {
Node {
left: None,
right: None,
key: k,
}
}
}
impl<K: Ord> Node<K> {
fn insert(&mut self, n: Node<K>) {
match n.key.cmp(&self.key) {
Less => {
match self.left {
None => self.left = Some(Box::new(n)),
Some(ref mut l) => l.insert(n),
}
}
Greater => {
match self.right {
None => self.right = Some(Box::new(n)),
Some(ref mut r) => r.insert(n),
}
}
_ => {}
}
}
fn height(&self) -> u32 {
let mut left_he = 1;
if let Some(ref l) = self.left {
left_he = 1 + l.height()
}
let mut right_he = 1;
if let Some(ref r) = self.right {
right_he = 1 + r.height()
}
if left_he > right_he {
return left_he;
}
return right_he;
}
fn rec(&self) -> u32 {
let mut le = 0;
if let Some(ref l) = self.left {
le = l.height()
}
let mut re = 0;
if let Some(ref r) = self.right {
re = r.height()
}
let hei = le + re + 1;
let mut led = 0;
let mut red = 0;
let Some(ref l) = self.left;
let Some(ref r) = self.right;
rayon::join(|| led = l.rec(), || red = r.rec());
let greater_diameter;
if red > led {
greater_diameter = red;
} else {
greater_diameter = led;
}
if hei > greater_diameter {
return hei;
}
return greater_diameter;
}
fn print_recursive(nodes: Vec<&Self>) {
let mut v: Vec<&Self> = vec![];
for n in nodes {
print!("1 ");
match n.left {
None => {}
Some(ref l) => v.push(&*l),
}
match n.right {
None => {}
Some(ref r) => v.push(&*r),
}
}
println!("");
if v.len() > 0 {
Node::print_recursive(v);
}
}
}
#[derive(Debug, Default)]
struct Bst<K> {
root: Option<Box<Node<K>>>,
}
impl<K> Bst<K> {
fn new() -> Bst<K> {
Bst { root: None }
}
}
impl<K: Ord> Bst<K> {
fn insert(&mut self, k: K) {
match self.root {
None => self.root = Some(Box::new(Node::new(k))),
Some(ref mut r) => r.insert(Node::new(k)),
}
}
fn rec(&self) -> u32 {
match self.root {
None => 0,
Some(ref r) => r.rec(),
}
}
fn print(&self) {
match self.root {
None => {}
Some(ref r) => Node::print_recursive(vec![&*r]),
};
}
}
fn main() {
let mut bst1 = Bst::new();
bst1.insert(20);
bst1.insert(21);
bst1.insert(22);
bst1.insert(23);
bst1.insert(24);
bst1.insert(25);
bst1.insert(19);
bst1.insert(18);
bst1.insert(17);
bst1.insert(16);
bst1.insert(15);
bst1.insert(14);
bst1.print();
println!("{}", bst1.rec());
}
When I compile (rustc code.rs), it shows
error: can't find crate for `rayon` [E0463]
My Rust version is rustc 1.8.0 (db2939409 2016-04-11)
You cannot just use an external dependency without telling the compiler where to find it. The easiest way of doing that is to create a Cargo.toml file and then use cargo build to compile your project instead of rustc directly.
To create the Cargo.toml file, you can just go into the project directory and type:
cargo init --bin
This will do two things:
Create the file src/main.rs. You should put your code in here.
Create a Cargo.toml file, which is used by Cargo for storing dependencies and other build information
You can then edit Cargo.toml to add the rayon dependency. The crates.io page for rayon gives you the exact information which you can just paste in there. When you are done, it should look something like this:
[package]
name = "foo"
version = "0.1.0"
authors = ["singh <singh#singh.com>"]
[dependencies]
rayon = "0.3.1"
Once you have this in place, you can build the project with:
cargo build
Or run with:
cargo run
You can get more information in the Cargo guide.
Related
Don't ask why I'm learning Rust using linked lists. I want to mutably iterate down a recursive structure of Option<Rc<RefCell<Node>>> while keeping the ability to swap out nodes and unwrap them. I have a singly-linked list type with a tail pointer to the last node.
pub struct List<T> {
maybe_head: Option<Rc<RefCell<Node<T>>>>,
maybe_tail: Option<Rc<RefCell<Node<T>>>>,
length: usize,
}
struct Node<T> {
value: T,
maybe_next: Option<Rc<RefCell<Node<T>>>>,
}
Let's say we have a constructor and an append function:
impl<T> List<T> {
pub fn new() -> Self {
List {
maybe_head: None,
maybe_tail: None,
length: 0,
}
}
pub fn put_first(&mut self, t: T) -> &mut Self {
let new_node_rc = Rc::new(RefCell::new(Node {
value: t,
maybe_next: mem::replace(&mut self.maybe_head, None),
}));
match self.length == 0 {
true => {
let new_node_rc_clone = new_node_rc.clone();
self.maybe_head = Some(new_node_rc);
self.maybe_tail = Some(new_node_rc_clone);
},
false => {
self.maybe_head = Some(new_node_rc);
},
}
self.length += 1;
self
}
}
I want to remove and return the final node by moving the tail pointer to its predecessor, then returning the old tail. After iterating down the list using RefCell::borrow() and Rc::clone(), the first version of remove_last() below panics when trying to unwrap the tail's Rc. How do I iterate down this recursive structure without incrementing each node's strongcount?
PANICKING VERSION
pub fn remove_last(&mut self) -> Option<T> {
let mut opt: Option<Rc<RefCell<Node<T>>>>;
if let Some(rc) = &self.maybe_head {
opt = Some(Rc::clone(rc))
} else {
return None;
};
let mut rc: Rc<RefCell<Node<T>>>;
let mut countdown_to_penultimate: i32 = self.length as i32 - 2;
loop {
rc = match opt {
None => panic!(),
Some(ref wrapped_rc) => Rc::clone(wrapped_rc),
};
match RefCell::borrow(&rc).maybe_next {
Some(ref next_rc) => {
if countdown_to_penultimate == 0 {
self.maybe_tail = Some(Rc::clone(x));
}
opt = Some(Rc::clone(next_rc));
countdown_to_penultimate -= 1;
},
None => {
let grab_tail = match Rc::try_unwrap(opt.take().unwrap()) {
Ok(something) => {
return Some(something.into_inner().value);
}
Err(_) => panic!(),
};
},
}
}
If all I do during iteration is move the tail pointer and enclose the iteration code in a {...} block to drop cloned references, I can then safely swap out and return the old tail, but this is obviously unsatisfying.
UNSATISFYING WORKING VERSION
pub fn remove_last(&mut self) -> Option<T> {
{let mut opt: Option<Rc<RefCell<Node<T>>>>;
if let Some(rc) = &self.maybe_head {
opt = Some(Rc::clone(rc))
} else {
return None;
};
let mut rc: Rc<RefCell<Node<T>>>;
let mut countdown_to_penultimate: i32 = self.length as i32 - 2;
loop {
rc = match opt {
None => panic!(),
Some(ref wrapped_rc) => Rc::clone(wrapped_rc),
};
match RefCell::borrow(&rc).maybe_next {
Some(ref next_rc) => {
if countdown_to_penultimate == 0 {
self.maybe_tail = Some(Rc::clone(&rc));
}
opt = Some(Rc::clone(next_rc));
countdown_to_penultimate -= 1;
},
None => {
break;
},
}
}}
match self.maybe_tail {
None => panic!(),
Some(ref rc) => {
let tail = mem::replace(&mut RefCell::borrow_mut(rc).maybe_next, None);
return Some(Rc::try_unwrap(tail.unwrap()).ok().unwrap().into_inner().value);
}
};
}
I wrote a List::remove_last() that I can live with, although I'd still like to know what more idiomatic Rust code here might look like. I find that this traversal idiom also extends naturally into things like removing the n-th node or removing the first node that matches some predicate.
fn remove_last(&mut self) -> Option<T> {
let mut opt: Option<Rc<RefCell<Node<T>>>>;
let mut rc: Rc<RefCell<Node<T>>>;
#[allow(unused_must_use)]
match self.length {
0 => {
return None;
}
1 => {
let head = mem::replace(&mut self.maybe_head, None);
mem::replace(&mut self.maybe_tail, None);
self.length -= 1;
return Some(
Rc::try_unwrap(head.unwrap())
.ok()
.unwrap()
.into_inner()
.value,
);
}
_ => {
opt = Some(Rc::clone(self.maybe_head.as_ref().unwrap()));
}
}
loop {
rc = match opt {
None => unreachable!(),
Some(ref wrapped_rc) => Rc::clone(wrapped_rc),
};
let mut borrowed_node = RefCell::borrow_mut(&rc);
let maybe_next = &mut borrowed_node.maybe_next;
match maybe_next {
None => unreachable!(),
Some(_)
if std::ptr::eq(
maybe_next.as_ref().unwrap().as_ptr(),
self.maybe_tail.as_ref().unwrap().as_ptr(),
) =>
{
borrowed_node.maybe_next = None;
let old_tail = self.maybe_tail.replace(Rc::clone(&rc));
self.length -= 1;
return Some(
Rc::try_unwrap(old_tail.unwrap())
.ok()
.unwrap()
.into_inner()
.value,
);
}
Some(ref next_rc) => {
opt = Some(Rc::clone(next_rc));
}
}
}
}
I am trying to measure the time my BST search func takes to search an element in a 100-10,000 elements BST, with sorted & unsorted values.
Link to playground:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d6708d951f80d58cdb77bc5fac1fc514
but I am getting weird results (in nanoseconds)
for 100 items:
BST - sorted: 33ns
BST - unsorted: 46ns
for 1,000 items:
BST - sorted: 10ns
BST - unsorted: 6ns
Seems impossible that the array is 10x times bigger and the time it took was way faster.
BST Search function:
pub fn search(&mut self, val: i32) -> bool {
if val == self.value {
true
} else {
if val <= self.value {
match self.left {
None => false,
Some(ref mut node) => node.search(val),
}
} else {
match self.right {
None => false,
Some(ref mut node) => node.search(val),
}
}
}
}
BST Insert function:
pub fn insert(&mut self, val: i32) {
if val <= self.value {
match self.left {
None => {
self.left = Some(Box::new(BSTNode {
value: val,
left: None,
right: None,
}))
}
Some(ref mut node) => node.insert(val),
}
} else {
match self.right {
None => {
self.right = Some(Box::new(BSTNode {
value: val,
left: None,
right: None,
}))
}
Some(ref mut node) => node.insert(val),
}
}
}
Timing function:
pub fn bst_search_timing(original_arr: &mut Vec<i32>) -> u128 {
let copy_arr: Vec<i32> = original_arr.to_vec();
let mut bst = BSTNode::new(1);
for item in copy_arr {
bst.insert(item);
}
let now = Instant::now();
bst.search(rand::random::<i32>());
let elapsed = now.elapsed();
return elapsed.as_nanos();
}
Main.rs:
let mut step = 100;
let times = 100;
let max = 10000;
while step <= max {
let mut bst_search_sum = 0;
let mut bst_search_unsorted_sum = 0;
let mut sorted_arr: Vec<i32> = vec![];
for x in 0..step {
sorted_arr.push(x);
}
for _ in 0..times {
let mut unsorted_arr: Vec<i32> = sorted_arr.to_vec();
unsorted_arr.shuffle(&mut thread_rng());
bst_search_sum += timing::bst_search_timing(&mut sorted_arr);
bst_search_unsorted_sum += timing::avl_search_timing(&mut sorted_arr);
}
And then I print the average:
println!(
"Average for {} elements: {}ns - BST_SEARCH: SORTED ARR",
step,
bst_search_sum / times
);
println!(
"Average for {} elements: {}ns - BST_SEARCH: UNSORTED ARR",
step,
bst_search_unsorted_sum / times
);
Here is my simplified code. I need to change the pdp_state in a function. but the state remain 'a'. I don't figure out why cloning Rc does not work. I also checked this cloning out side a structure an it worked.
#[derive(Clone,Copy)]
enum PDPStatus{
a,
b
}
struct network{
pdp_state:Rc<RefCell<PDPStatus>>,
}
impl network{
fn set(&mut self){
let mut t = *self.pdp_state.clone().borrow_mut();
match t {
a => {let m1 = self.pdp_state.clone();
let mut a = (*m1).borrow_mut() ;
*a = PDPStatus::b;
println!("a");},
b=> {let m1 = self.pdp_state.clone();m1.replace( PDPStatus::a);
println!("b");},
};
}
}
fn main() {
let mut network1 = network::new();
network1.set();
network1.set();
network1.set();
network1.set();
}
Update:
My set function would look like this. I need two closure that have access to pdp_state. I pass these closures as callbacks. I am sure the these closure wouldn't call together.
fn set(&mut self){
let borrowed_pdp_status = self.pdp_state.borrow().clone();
match borrowed_pdp_status {
PDPStatus::a => {
let mut state = self.pdp_state.clone();
let mut closuree = || state = Rc::new(RefCell::new(PDPStatus::b));
let mut state1 = self.pdp_state.clone();
let mut closuree1 = || state1 = Rc::new(RefCell::new(PDPStatus::b));
closuree();
closuree1();
println!("a");
},
PDPStatus::b => {
let mut closuree = || self.pdp_state = Rc::new(RefCell::new(PDPStatus::a));
closuree();
println!("b");
},
};
}
In the set method, you need to borrow self.pdp_state and then clone() it in a variable, and then match the variable where you cloned it.
Replace the set method with this:
fn set(&mut self) {
let borrowed_pdp_status = self.pdp_state.borrow().clone();
match borrowed_pdp_status {
PDPStatus::a => {
self.pdp_state = Rc::new(RefCell::new(PDPStatus::b));
println!("a");
},
PDPStatus::b => {
self.pdp_state = Rc::new(RefCell::new(PDPStatus::a));
println!("b");
},
};
}
Playground link - https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=426d4cb7db9a92ee4ddcd4f36dbc12f7
This answer was posted after the question was updated:
EDIT
You can use the replace() method from RefCell
fn set(&mut self) {
let borrowed_pdp_status = self.pdp_state.borrow().clone();
match borrowed_pdp_status {
PDPStatus::a => {
let mut closuree = || {
self.pdp_state.replace(PDPStatus::b);
};
let mut closuree1 = || {
self.pdp_state.replace(PDPStatus::b);
};
closuree();
closuree1();
println!("a");
}
PDPStatus::b => {
let mut closuree = || {
self.pdp_state.replace(PDPStatus::a);
};
closuree();
println!("b");
}
};
}
Playground link - https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4af02228d58b2f2c865a525e3f70d6a0
OLD
You could just make the closures take &mut self.pdp_state as an argument, and then update it.
fn set(&mut self) {
let borrowed_pdp_status = self.pdp_state.borrow().clone();
match borrowed_pdp_status {
PDPStatus::a => {
let mut closuree = |local_pdp_state: &mut Rc<RefCell<PDPStatus>>| {
*local_pdp_state = Rc::new(RefCell::new(PDPStatus::b))
};
let mut closuree1 = |local_pdp_state: &mut Rc<RefCell<PDPStatus>>| {
*local_pdp_state = Rc::new(RefCell::new(PDPStatus::b))
};
closuree(&mut self.pdp_state);
closuree1(&mut self.pdp_state);
println!("a");
}
PDPStatus::b => {
let mut closuree = |local_pdp_state: &mut Rc<RefCell<PDPStatus>>| {
*local_pdp_state = Rc::new(RefCell::new(PDPStatus::a))
};
closuree(&mut self.pdp_state);
println!("b");
}
};
}
Playground link - https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4af96385b0446082afdb7d615bb8eecb
I am attempting to implementing delete for a binary tree:
#[derive(Debug)]
struct Binary_Tree<T: PartialOrd + Clone> {
left: Box<Option<Binary_Tree<T>>>,
value: T,
right: Box<Option<Binary_Tree<T>>>,
}
impl<T: PartialOrd + Clone> Binary_Tree<T> {
fn new(value: T) -> Binary_Tree<T> {
Binary_Tree {
left: Box::new(None),
value: value,
right: Box::new(None),
}
}
fn delete(&mut self, value_to_delete: T) -> bool {
use std::mem;
match self {
&mut Binary_Tree {
ref mut left,
ref mut value,
ref mut right,
} => if value_to_delete < *value {
if let None = **left {
return false;
} else {
return (**left).as_mut().unwrap().delete(value_to_delete);
}
} else if value_to_delete > *value {
if let None = **right {
return false;
} else {
return (**right).as_mut().unwrap().delete(value_to_delete);
}
} else {
if let Some(ref mut left_content) = **left {
*value = (*left_content).value.clone();
let temp = (*left_content).value.clone();
return (*left_content).delete(temp);
} else if let Some(ref mut right_content) = **right {
*value = (*right_content).value.clone();
let temp = (*right_content).value.clone();
return (*right_content).delete(temp);
} else {
mem::replace(self, None);
return true;
}
},
}
}
}
The place that is causing trouble is mem::replace(self, None); since self is of Binary_Tree type and not Option.
I implemented another solution but it ran into other issues as well:
fn delete(&mut self, value_to_delete: T) -> bool {
match self {
&mut Binary_Tree {
ref mut left,
ref mut value,
ref mut right,
} => {
if value_to_delete < *value {
if let None = **left {
return false;
} else {
return (**left).as_mut().unwrap().delete(value_to_delete);
}
} else if value_to_delete > *value {
if let None = **right {
return false;
} else {
return (**right).as_mut().unwrap().delete(value_to_delete);
}
} else {
if let Some(ref mut left_content) = **left {
*value = (*left_content).value.clone();
let temp = (*left_content).value.clone();
if let None = *left_content.left {
if let None = *left_content.right {
//**left = None;
return true;
} else {
return (*left_content).delete(temp);
}
} else {
return (*left_content).delete(temp);
}
} else if let Some(ref mut right_content) = **right {
*value = (*right_content).value.clone();
let temp = (*right_content).value.clone();
if let None = *right_content.left {
if let None = *right_content.right {
//**right = None;
return true;
} else {
return (*right_content).delete(temp);
}
} else {
return (*right_content).delete(temp);
}
} else {
// This should never go here
return true;
}
}
}
}
}
The problem with this solution is that both **right = None; and **left = None; are borrowed out to do checks.
I feel like I am missing something important since both solutions should work in other language.
You need to pass tree: &mut Option<Self> instead of &mut self; you cannot call it as a method anymore, but Self::delete(left, value_to_delete) should still work fine.
Your current Tree type should probably be called Node - a Tree can consist of no node, and your current Tree always is at least one node. You should then provide a pub struct Tree(Option<Node>); Option<Node> wouldn't be very user friendly.
I feel like I am missing something important since both solutions should work in other language.
Some languages pass objects always by a shared and nullable pointer. In Rust you need to be explicit about this.
Your comment // This should never go here in the second solution is simply a wrong assumption. You could match *left.take() instead of **left*, thenleft` isn't borrowed (but empty; so you need to restore it if it shouldn't be).
Given that borrow-checking is a rather unique feature it should be obvious that certain patterns don't work in Rust, even if they are safe and would work in other languages.
I have an enum which roughly looks like this simplified example:
use std::collections::BTreeMap;
enum Value {
Null,
Object(BTreeMap<String, Value>)
}
Now I would like to, based on a list of field names, drill down into a Value::Object and initialize it with the given fields. The leaf field should always receive the Value::Null variant.
What I would like to, and am used to, do is the following:
fn set_null_to_how_i_want_it(fields: &[&str], mut v: &mut Value) {
debug_assert!(fields.len() > 0);
for (fid, field) in fields.iter().enumerate() {
v =
match *v {
Value::Object(ref mut map) => {
let val_to_insert =
if fid == fields.len() - 1 {
Value::Null
} else {
Value::Object(Default::default())
};
map.entry(field.to_string()).or_insert(val_to_insert)
}
_ => unreachable!(),
}
}
}
However, the borrow checker will not allow it.
Interestingly, what worked is the following, more complex and probably less performant implementation:
fn set_null_how_borrow_chk_allows_it(fields: &[&str], v: &mut Value) {
let next =
match *v {
Value::Object(ref mut map) => {
let val_to_insert =
if fields.len() == 1 {
Value::Null
} else {
Value::Object(Default::default())
};
map.entry(fields[0].to_string()).or_insert(val_to_insert)
},
_ => unreachable!()
};
if fields.len() > 1 {
set_null_how_borrow_chk_allows_it(&fields[1..], next)
}
}
With the version above, all the following code runs fine:
let mut v = Value::Object(Default::default());
let fields = ["foo", "bar", "baz"];
set_null_how_borrow_chk_allows_it(&fields, &mut v);
let mut map_count = 0;
for (fid, field) in fields.iter().enumerate() {
let next =
match v {
Value::Object(mut map) => {
map_count += 1;
map.remove(&field.to_string()).unwrap()
},
_ => unreachable!()
};
v = next;
}
assert_eq!(map_count, fields.len());
match v {
Value::Null => (),
Value::Object(_) => unreachable!(),
}
Is there a better way to initialize a nested enumeration or to get set_null_to_how_i_want_it(...) to work ?
How to reproduce
You can have a look at the complete example on github, and play around with it as follows:
git clone https://github.com/Byron/depot
cd depot/src/rust/hello
cargo test --test lang
# edit src/rust/hello/tests/lang.rs for testing
Meta
➜ hello git:(master) ✗ rustc --version --verbose
rustc 1.1.0-nightly (4b88e8f63 2015-05-11) (built 2015-05-12)
binary: rustc
commit-hash: 4b88e8f63eeaf557c916a0a1e73150b028c44c52
commit-date: 2015-05-11
build-date: 2015-05-12
host: x86_64-apple-darwin
release: 1.1.0-nightly
The borrow checker works on names, and so some examples like your first approach don’t work; this can be worked around by moving the value v to a different name first and then assigning the new value to v:
fn set_null_to_how_i_want_it(fields: &[&str], mut v: &mut Value) {
debug_assert!(fields.len() > 0);
for (fid, field) in fields.iter().enumerate() {
let tmp = v;
v = match *tmp {
Value::Object(ref mut map) => {
let val_to_insert =
if fid == fields.len() - 1 {
Value::Null
} else {
Value::Object(Default::default())
};
map.entry(field.to_string()).or_insert(val_to_insert)
}
_ => unreachable!(),
};
}
}