Last active
January 13, 2018 12:29
-
-
Save foriequal0/a64ad9b2ab54f1ac7bcafbc2b2234a3e to your computer and use it in GitHub Desktop.
비밀번호 특수문자 위치 히스토그램
This file contains hidden or 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
#!/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); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment