Skip to content

Instantly share code, notes, and snippets.

@Dr-Emann
Forked from anonymous/playground.rs
Created April 27, 2017 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dr-Emann/3b943279f719420b27779bd19fb533b6 to your computer and use it in GitHub Desktop.
Save Dr-Emann/3b943279f719420b27779bd19fb533b6 to your computer and use it in GitHub Desktop.
Rust code shared from the playground
extern crate rand;
use rand::{thread_rng, Rng};
use rand::distributions::{Normal, IndependentSample};
struct SinglePack {
open_block: Vec<f64>,
open_sum: f64,
blocks: Vec<Vec<f64>>,
}
impl SinglePack {
fn add(&mut self, item: f64) {
assert!(item <= 1.0);
if self.open_sum + item > 1.0 {
self.blocks.push(self.open_block.clone());
self.open_block.clear();
self.open_sum = 0.0;
}
self.open_block.push(item);
self.open_sum += item;
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
struct Item {
value: f64,
order: u32,
}
struct DoublePack {
open_blocks: (Vec<Item>, Vec<Item>),
open_sums: (f64, f64),
blocks: Vec<Vec<Item>>,
order: u32,
}
impl DoublePack {
fn add(&mut self, value: f64) {
assert!(value <= 1.0);
let item = Item { value: value, order: self.order };
self.order += 1;
let (ref mut block1, ref mut block2) = self.open_blocks;
let (ref mut sum1, ref mut sum2) = self.open_sums;
let dif1 = *sum1 + value;
let dif2 = *sum2 + value;
{
let (block, sum) = {
if dif1 > 1.0 && dif2 > 1.0 {
if *sum1 > *sum2 {
self.blocks.push(block1.clone());
block1.clear();
*sum1 = 0.0;
(&mut *block1, &mut *sum1)
} else {
self.blocks.push(block2.clone());
block2.clear();
*sum2 = 0.0;
(&mut *block2, &mut *sum2)
}
} else if dif1 > dif2 {
if dif1 <= 1.0 {
(&mut *block1, &mut *sum1)
} else {
(&mut *block2, &mut *sum2)
}
} else {
if dif2 <= 1.0 {
(&mut *block2, &mut *sum2)
} else {
(&mut *block1, &mut *sum1)
}
}
};
block.push(item);
*sum += value;
}
/*if *sum1 > 0.5 && *sum2 > 0.5 {
if *sum1 > *sum2 {
self.blocks.push(block1.clone());
block1.clear();
*sum1 = 0.0;
} else {
self.blocks.push(block2.clone());
block2.clear();
*sum2 = 0.0;
}
}*/
}
}
fn main() {
let mut rng = thread_rng();
let norm = Normal::new(0.8, 0.3);
let mut values = Vec::with_capacity(50000);
while values.len() < 50000 {
let value = norm.ind_sample(&mut rng);
if value < 0.0 || value > 1.0 {
continue;
}
//values.push(0.9);
//values.push(0.01);
values.push(value);
}
let values: Vec<f64> = rng.gen_iter().take(500000).collect();
let mut single = SinglePack { open_block: Vec::new(), open_sum: 0.0, blocks: Vec::new() };
let mut double = DoublePack { open_blocks: (Vec::new(), Vec::new()), open_sums: (0.0, 0.0), blocks: Vec::new(), order: 0 };
for v in values {
single.add(v);
double.add(v);
}
single.blocks.push(single.open_block.clone());
if ! double.open_blocks.0.is_empty() {
double.blocks.push(double.open_blocks.0.clone());
}
if ! double.open_blocks.1.is_empty() {
double.blocks.push(double.open_blocks.1.clone());
}
//println!("single: {:?}", single.blocks);
//println!("double: {:?}", double.blocks);
let mut i = 0;
let mut max_order_diff = 0;
let mut sum_order_diff = 0;
let mut min_block_size = 1.0;
let mut order_diffs = Vec::new();
for block in &double.blocks {
for item in block {
let order_diff = ((item.order as i32) - i).abs();
sum_order_diff += order_diff;
order_diffs.push(order_diff);
if order_diff > max_order_diff {
max_order_diff = order_diff;
}
i += 1;
}
let sum: f64 = block.iter().map(|item| item.value).sum();
if sum < min_block_size {
min_block_size = sum;
}
}
order_diffs.sort_by(|x, y| x.partial_cmp(&y).unwrap());
let mut single_sizes: Vec<f64> = single.blocks.iter().map(|block| block.iter().cloned().sum::<f64>()).collect();
single_sizes.sort_by(|x, y| x.partial_cmp(&y).unwrap());
let min_s_block_size = single_sizes[0];
println!("single {} blocks", single.blocks.len());
println!("double {} blocks", double.blocks.len());
println!("max_order_diff: {}", max_order_diff);
println!("single min block {}", min_s_block_size);
println!("double min block {}", min_block_size);
println!("avg order_diff: {}", sum_order_diff as f64 / i as f64);
println!("median order_diff: {}", order_diffs[order_diffs.len() / 2]);
println!("fraction of first > 0: {}", order_diffs.iter().position(|x| *x > 0).unwrap() as f64 / order_diffs.len() as f64);
println!("fraction of first > 1: {}", order_diffs.iter().position(|x| *x > 1).unwrap() as f64 / order_diffs.len() as f64);
println!("fraction of first > 2: {}", order_diffs.iter().position(|x| *x > 2).unwrap() as f64 / order_diffs.len() as f64);
println!("fraction of first > 3: {}", order_diffs.iter().position(|x| *x > 3).unwrap() as f64 / order_diffs.len() as f64);
println!("fraction of first > 4: {}", order_diffs.iter().position(|x| *x > 4).unwrap() as f64 / order_diffs.len() as f64);
println!("fraction of first > 5: {}", order_diffs.iter().position(|x| *x > 5).unwrap() as f64 / order_diffs.len() as f64);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment