bicycle_book_wordcount_r1k/
lib.rs1use regex::Regex;
2use std::collections::HashMap;
3use std::io::BufRead;
4
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum CountOption {
8 Char,
9 Word,
10 Line,
11}
12
13
14impl Default for CountOption {
15 fn default() -> Self {
16 CountOption::Word
17 }
18}
19
20
21pub fn count(input: impl BufRead, option: CountOption) -> HashMap<String, usize> {
22 let re = Regex::new(r"\w+").unwrap();
23 let mut freqs = HashMap::new();
24
25 for line in input.lines () {
26 let line = line.unwrap();
27 use crate::CountOption::*;
28 match option {
29 Char => {
30 for c in line.chars() {
31 *freqs.entry(c.to_string()).or_insert(0) += 1;
32 }
33 }
34 Word => {
35 for m in re.find_iter(&line) {
36 let word = m.as_str().to_string();
37 *freqs.entry(word).or_insert(0) += 1;
38 }
39 }
40 Line => *freqs.entry(line.to_string()).or_insert(0) += 1,
41 }
42 }
43 freqs
44}
45
46
47
48
49#[cfg(test)]
50mod test {
51 use super::*;
52 use std::io::Cursor;
53
54 #[test]
55 fn word_count_works() {
56 let mut exp = HashMap::new();
57 exp.insert("aa".to_string(), 1);
58 exp.insert("bb".to_string(), 2);
59 exp.insert("cc".to_string(), 1);
60
61 assert_eq!(count(Cursor::new("aa bb cc bb"), CountOption::Word), exp);
62 }
63
64 #[test]
65 fn word_count_fails() {
66 use std::io::Cursor;
67 let mut exp = HashMap::new();
68 exp.insert("aa".to_string(), 1);
69 exp.insert("cc".to_string(), 1);
70 exp.insert("dd".to_string(), 1);
71
72 assert_eq!(count(Cursor::new("aa cc dd"), CountOption::Word), exp);
73 }
74
75 #[test]
76 #[should_panic]
77 fn word_count_invalid_charcode() {
78 use std::io::Cursor;
79
80 count(
81 Cursor::new([
82 b'a',
83 0xf0, 0x90, 0x80, 0xe3, 0x81, 0x82, ]),
86 CountOption::Word,
87 );
88
89 }
90
91 macro_rules! assert_map {
92 ($expr: expr, {$($key: expr => $value:expr),*}) => {
93 $(assert_eq!($expr[$key], $value));*
94 };
95 }
96
97 #[test]
98 fn word_count_works3() {
99 use std::io::Cursor;
100 let freqs = count(Cursor::new("aa cc dd"), CountOption::Word);
101 assert_eq!(freqs.len(), 3);
102 assert_map!(freqs, {"aa" => 1, "cc" => 1, "dd" =>1});
103 }
104}