Skip to content

Instantly share code, notes, and snippets.

@GoldsteinE
Created August 13, 2019 23:46
Show Gist options
  • Save GoldsteinE/82869a7aa7c255a77e3e5853e96beefa to your computer and use it in GitHub Desktop.
Save GoldsteinE/82869a7aa7c255a77e3e5853e96beefa to your computer and use it in GitHub Desktop.
#![feature(core_intrinsics)]
use std::fmt;
use std::io::{self, Write};
use std::intrinsics::likely;
const WINDOW_SIZE: usize = 10;
const UPPER_BOUND: usize = 10;
struct FloatingWindow {
data: [usize; WINDOW_SIZE],
start_index: usize,
current_size: usize,
curr_sum: usize,
counter: [usize; UPPER_BOUND]
}
impl FloatingWindow {
pub fn new() -> Self {
Self {
start_index: 0,
current_size: 0,
data: [0; WINDOW_SIZE],
curr_sum: 0,
counter: [0; UPPER_BOUND],
}
}
pub fn at(&self, idx: usize) -> usize {
self.data[(self.start_index + idx) % WINDOW_SIZE]
}
pub fn push(&mut self, value: usize) {
let old_value = self.at(self.current_size);
self.curr_sum -= old_value;
self.curr_sum += value;
unsafe {
if likely(self.counter[old_value] != 0) {
self.counter[old_value] -= 1;
}
}
self.counter[value] += 1;
self.data[(self.start_index + self.current_size) % WINDOW_SIZE] = value;
if self.current_size < WINDOW_SIZE {
self.current_size += 1;
} else {
self.start_index += 1;
}
}
pub fn sum(&self) -> usize {
return self.curr_sum;
}
pub fn avg(&self) -> Option<usize> {
if self.current_size != 0 {
Some(self.curr_sum / (self.current_size))
} else {
None
}
}
pub fn most_common(&self) -> usize {
let mut num = 0;
for (idx, &value) in self.counter.iter().enumerate() {
if value > self.counter[num] {
num = idx;
}
}
num
}
}
impl fmt::Debug for FloatingWindow {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"FloatingWindow {{ {:?}, sum: {:?}, avg: {:?}, most_common: {:?} }}",
self.into_iter().collect::<Vec<usize>>(),
self.sum(),
self.avg(),
self.most_common()
)
}
}
struct FloatingWindowIterator<'a> {
window: &'a FloatingWindow,
curr_index: usize,
}
impl<'a> IntoIterator for &'a FloatingWindow {
type Item = usize;
type IntoIter = FloatingWindowIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
FloatingWindowIterator::new(self)
}
}
impl<'a> FloatingWindowIterator<'a> {
pub fn new(window: &'a FloatingWindow) -> Self {
Self {
window,
curr_index: 0,
}
}
}
impl<'a> Iterator for FloatingWindowIterator<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.curr_index < self.window.current_size {
self.curr_index += 1;
Some(self.window.at(self.curr_index - 1))
} else {
None
}
}
}
fn main() {
let stdin = io::stdin();
let mut stdout = io::stdout();
let mut user_input = String::new();
let mut window = FloatingWindow::new();
loop {
print!("> ");
stdout.flush().expect("I/O error");
user_input.truncate(0);
stdin.read_line(&mut user_input).expect("I/O error");
if user_input == "" || user_input == "q\n" {
break;
}
user_input = user_input.trim().to_string();
if user_input == "" {
continue;
}
if user_input == "p" {
println!("{:?}", window);
} else {
match user_input.parse() {
Ok(num) => {
if num >= UPPER_BOUND {
eprintln!("num must be less than {}", UPPER_BOUND);
} else {
window.push(num);
}
}
Err(err) => eprintln!("Error parsing number: {}", err),
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment