Guest User

Untitled

a guest
Jan 23rd, 2018
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.13 KB | None | 0 0
  1. #!/usr/bin/env run-cargo-script
  2.  
  3. use std::env;
  4. use std::fs::File;
  5. use std::io::{BufReader, BufRead};
  6. use std::collections::HashMap;
  7. use std::vec::Vec;
  8. use std::iter::FromIterator;
  9.  
  10. fn main()
  11. {
  12. let file_name = env::args().nth(1).expect("First argument should be a file");
  13. let file = File::open(file_name).expect("A File must exist");
  14. let reader = BufReader::new(file);
  15.  
  16. let mut analysers: Vec<Box<Analyser>> = vec![
  17. Box::new(Total { count: 0 }),
  18. Box::new(NonAlnumPositionHistogram { hists: HashMap::new() }),
  19. ];
  20.  
  21. for line in reader.lines() {
  22. let line = line.expect("Invalid line");
  23.  
  24. for analyser in &mut analysers {
  25. analyser.feed(&line);
  26. }
  27. }
  28.  
  29. for analyser in &mut analysers {
  30. println!("=============================================");
  31. analyser.print();
  32. }
  33. }
  34.  
  35. trait Analyser {
  36. fn feed(&mut self, line: &str);
  37. fn print(&self);
  38. }
  39.  
  40. struct Total {
  41. count: i32
  42. }
  43.  
  44. impl Analyser for Total {
  45. fn feed(&mut self, line: &str) {
  46. self.count += 1;
  47. }
  48. fn print(&self) {
  49. println!("Total: ");
  50. println!("{}", self.count);
  51. }
  52. }
  53.  
  54. const BINS: usize = 40;
  55. struct Hist {
  56. count: i32,
  57. bins: [f64; BINS]
  58. }
  59. impl Hist {
  60. fn new() -> Hist {
  61. Hist {
  62. count: 0,
  63. bins: [0.0; BINS]
  64. }
  65. }
  66. fn update(&mut self, length: i32, index: i32) {
  67. self.count += 1;
  68.  
  69. let lower = BINS as i32 * index / length;
  70. let upper = {
  71. let x = BINS as i32 * (index + 1) / length;
  72. if x == lower {
  73. x+1
  74. } else {
  75. x
  76. }
  77. };
  78.  
  79. let weight = 1.0 / (upper - lower) as f64;
  80. for i in lower as usize..upper as usize {
  81. self.bins[i] += weight;
  82. }
  83. }
  84. }
  85. struct NonAlnumPositionHistogram
  86. {
  87. hists: HashMap<char, Hist>
  88. }
  89. impl Analyser for NonAlnumPositionHistogram
  90. {
  91. fn feed(&mut self, line: &str) {
  92. let length = line.chars().count();
  93. for (idx, ch) in line.chars().enumerate() {
  94. if ch.is_alphanumeric() { continue; }
  95. let hist = self.hists.entry(ch).or_insert_with(&Hist::new);
  96. hist.update(length as i32, idx as i32);
  97. }
  98. }
  99. fn print(&self) {
  100. let keys = {
  101. let mut keys = Vec::from_iter(self.hists.iter());
  102. keys.sort_by(|&(_, u), &(_, v)| v.count.cmp(&u.count)); // reverse
  103. Vec::from_iter(keys.iter().map(|&(k, v)| k))
  104. };
  105. println!("Histogram: ");
  106. let height = 10;
  107. for key in &keys {
  108. let hist = &self.hists[key];
  109.  
  110. let max = hist.bins.iter().max_by(|x, y| x.partial_cmp(y).unwrap()).unwrap();
  111. let bins = hist.bins;
  112. for h in (0..height).rev() {
  113. println!("");
  114. for i in 0..BINS {
  115. if bins[i] >= max * h as f64 / height as f64 {
  116. print!("*");
  117. } else {
  118. print!(" ");
  119. }
  120. }
  121. }
  122. println!("");
  123. println!("{}: {}", key, hist.count);
  124. }
  125. }
  126. }
Add Comment
Please, Sign In to add comment