BST Tree, Search function is giving odd times (measuring of search function) - rust

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
);

Related

Parse http response into tuple vector of (chrono::DateTime, f32)

I send an http get request to a server and receive a response:
let resp = reqwest::blocking::get(req)?.text()?;
resp holds a String like this:
<?xml version=\"1.0\" encoding=\"UTF-8\">\n<Document xmlns=...
<datetime>202207102300</datetime>\n\t\t\t\t\t\t<value>320.08</value>\n\t\t\t\t\t<datetime>202207110000</datetime>\n\t\t\t\t\t\t<value>278.00</value>
...</Document>
What is the best way to get this text parsed into a vector containing tuple elements, as follows:
let mut tuple_items: (chrono::DateTime, f32)
This is my code that I created with the quickxml crate:
use chrono::NaiveDateTime;
use quick_xml::events::Event;
use quick_xml::Reader;
pub struct DatetimeValue {
pub dt: NaiveDateTime,
pub val: f32,
}
pub fn parse_xml_string(&self, xml_string: String) -> Vec<DatetimeValue> {
let mut response_vector: Vec<DatetimeValue> = vec![];
let mut reader = Reader::from_str(&xml_string[..]);
reader.trim_text(true);
let mut val_flag = false;
let mut dt_flag = false;
let mut buf = Vec::new();
let mut count = 0;
let mut actual_dt: NaiveDateTime;
loop {
match reader.read_event(&mut buf) {
Ok(Event::Start(ref e)) => {
if let b"value" = e.name() { val_flag = true }
else if let b"datetime" = e.name() { dt_flag = true }
}
Ok(Event::Text(e)) => {
if dt_flag {
actual_dt = NaiveDateTime::parse_from_str(e
.unescape_and_decode(&reader)
.unwrap(), "%Y%m%d%H%M").unwrap();
dt_flag = false;
}
else if val_flag {
response_vector.push(DatetimeValue {
dt: actual_dt,
val: e
.unescape_and_decode(&reader)
.unwrap()
.parse::<f32>()
.unwrap(),
});
val_flag = false;
}
}
Ok(Event::Eof) => break,
Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
_ => (),
}
buf.clear();
}
response_vector
}

Returning struct with vector

I just began learning Rust and doing some exercises.
Here I'm trying to return the next permutation. But at the end of the next() method it seems to return the wrong vector in the struct.
pub struct Permutation {
p : Vec<u8>,
}
impl Permutation{
pub fn new(length: u8) -> Permutation {
let mut p :Vec<u8> = Vec::new();
for i in 1..length+1 {
p.push(i as u8);
}
Permutation { p }
}
pub fn create(this: Vec<u8>) -> Permutation {
Permutation { p:this }
}
pub fn next(&mut self) -> Option<Permutation> {
let mut pivot :usize = self.p.len() + 1;
for i in (1..self.p.len()).rev() {
if self.p[i-1] < self.p[i] {
pivot = i-1;
break;
}
}
if pivot == self.p.len() + 1 {
return None;
}
let mut swap :usize = pivot + 1;
for i in pivot+1..self.p.len() {
if self.p[i] > self.p[pivot] && self.p[i] < self.p[swap] {
swap = i;
}
}
let temp = self.p[swap];
self.p[swap] = self.p[pivot];
self.p[pivot] = temp;
pivot += 1;
let mut new_perm :Vec<u8> = Vec::new();
for i in 0..pivot {
new_perm.push(self.p[i]);
}
for i in (pivot..self.p.len()).rev() {
new_perm.push(self.p[i]);
}
// Debug
// for e in &new_perm {
// println!("{}", e);
//}
return Some(Permutation{ p: new_perm })
}
}
If I uncomment the println I can see that the new_perm vector is correct, but I seem to be getting the self.p vector returned.
What am I doing wrong here?

Iterate through a singly linked list of Option<Rc<RefCell<Node>>> without increasing strongcount

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));
}
}
}
}

Tic Tac Toe - Minimax

I'm trying to build a tic-tac-toe game using minimax algorithm with rust. And I'm stuck. I tried to write a rust code based on the psudeo code on the wikipedia page. https://en.wikipedia.org/wiki/Minimax. However, it didn't work. Ai always makes the first possible move. I would be glad if you could help me.
In main.rs
fn main() {
let mut g = Game::new();
while g.game_state() == Game_State::Continuous {
g.print();
println!("{}", minimax(&g));
if g.turn == Player::Cross {
g.take_input();
}
else {
g = best_move(&g);
}
}
g.print();
if let Game_State::Win(Player::None) = g.game_state() {
println!("Draw");
}
else {
g.print_winner();
}
}
In ai.rs
pub fn child_nodes(game: &Game) -> Vec<Game> {
let mut children: Vec<Game> = Vec::new();
for r in 0..3 {
for c in 0..3 {
if game.grid[r][c] == Player::None {
let mut child = game.clone();
child.grid[r][c] = game.turn;
child.turn = reverse_player(child.turn);
children.push(child);
}
}
}
return children;
}
pub fn minimax(game: &Game) -> isize {
match game.game_state() {
Game_State::Win(winner) => to_scor(winner),
Game_State::Continuous => {
use std::cmp::{min, max};
let children_vec = child_nodes(&game);
let mut score: isize;
if game.turn == Player::Cross {
score = -2;
for i in &children_vec {
score = max(score, minimax(i));
}
}
else {
score = 2;
for i in &children_vec {
score = min(score, minimax(i));
}
}
return score;
}
}
}
pub fn best_move(game: &Game) -> Game {
let children = child_nodes(game);
let mut values: Vec<isize> = Vec::new();
for i in 0..children.len() {
values.push(minimax(&children[i]));
}
let mut index: usize = 0;
let iter = values.iter().enumerate();
if game.turn == Player::Cross {
if let Option::Some(t) = iter.max() {
index = t.0;
}
}
else if game.turn == Player::Circle {
if let Option::Some(t) = iter.min() {
index = t.0;
}
}
let best_pos = children[index];
best_pos
}
pub fn to_scor(x: Player) -> isize {
match x {
Player::Cross => 1,
Player::Circle => -1,
Player::None => 0
}
}
.enumerate() returns an iterator over tuples, and .max() and .min() on an iterator of tuples will compare the tuples - that is, (1, x) is always considered to be less than (2, y) for any values of x and y. This can be demonstrated with this snippet:
fn main() {
let v = vec![3, 1, 2, 5, 3, 6, 7, 2];
println!("{:?}", v.iter().enumerate().min());
println!("{:?}", v.iter().enumerate().max());
}
which prints:
Some((0, 3))
Some((7, 2))
which are just the first and last elements of the list (and not the minimum or maximum elements).
However, as shown here, you can use max_by to use your own function to compare the tuples.

Can't find crate for `rayon`

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.

Resources