Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env run-cargo-script
- use std::env;
- use std::fs::File;
- use std::io::{BufReader, BufRead};
- use std::collections::HashMap;
- use std::vec::Vec;
- use std::iter::FromIterator;
- fn main()
- {
- let file_name = env::args().nth(1).expect("First argument should be a file");
- let file = File::open(file_name).expect("A File must exist");
- let reader = BufReader::new(file);
- let mut analysers: Vec<Box<Analyser>> = vec![
- Box::new(Total { count: 0 }),
- Box::new(NonAlnumPositionHistogram { hists: HashMap::new() }),
- ];
- for line in reader.lines() {
- let line = line.expect("Invalid line");
- for analyser in &mut analysers {
- analyser.feed(&line);
- }
- }
- for analyser in &mut analysers {
- println!("=============================================");
- analyser.print();
- }
- }
- trait Analyser {
- fn feed(&mut self, line: &str);
- fn print(&self);
- }
- struct Total {
- count: i32
- }
- impl Analyser for Total {
- fn feed(&mut self, line: &str) {
- self.count += 1;
- }
- fn print(&self) {
- println!("Total: ");
- println!("{}", self.count);
- }
- }
- const BINS: usize = 40;
- struct Hist {
- count: i32,
- bins: [f64; BINS]
- }
- impl Hist {
- fn new() -> Hist {
- Hist {
- count: 0,
- bins: [0.0; BINS]
- }
- }
- fn update(&mut self, length: i32, index: i32) {
- self.count += 1;
- let lower = BINS as i32 * index / length;
- let upper = {
- let x = BINS as i32 * (index + 1) / length;
- if x == lower {
- x+1
- } else {
- x
- }
- };
- let weight = 1.0 / (upper - lower) as f64;
- for i in lower as usize..upper as usize {
- self.bins[i] += weight;
- }
- }
- }
- struct NonAlnumPositionHistogram
- {
- hists: HashMap<char, Hist>
- }
- impl Analyser for NonAlnumPositionHistogram
- {
- fn feed(&mut self, line: &str) {
- let length = line.chars().count();
- for (idx, ch) in line.chars().enumerate() {
- if ch.is_alphanumeric() { continue; }
- let hist = self.hists.entry(ch).or_insert_with(&Hist::new);
- hist.update(length as i32, idx as i32);
- }
- }
- fn print(&self) {
- let keys = {
- let mut keys = Vec::from_iter(self.hists.iter());
- keys.sort_by(|&(_, u), &(_, v)| v.count.cmp(&u.count)); // reverse
- Vec::from_iter(keys.iter().map(|&(k, v)| k))
- };
- println!("Histogram: ");
- let height = 10;
- for key in &keys {
- let hist = &self.hists[key];
- let max = hist.bins.iter().max_by(|x, y| x.partial_cmp(y).unwrap()).unwrap();
- let bins = hist.bins;
- for h in (0..height).rev() {
- println!("");
- for i in 0..BINS {
- if bins[i] >= max * h as f64 / height as f64 {
- print!("*");
- } else {
- print!(" ");
- }
- }
- }
- println!("");
- println!("{}: {}", key, hist.count);
- }
- }
- }
Add Comment
Please, Sign In to add comment