-
-
Save Dr-Emann/3b943279f719420b27779bd19fb533b6 to your computer and use it in GitHub Desktop.
Rust code shared from the playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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