bicycle_book_wordcount/
lib.rs1#![warn(missing_docs)]
4
5use regex::Regex;
6use std::collections::HashMap;
7use std::io::BufRead;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum CountOption {
12 Char,
14 Word,
16 Line,
18}
19
20impl Default for CountOption {
22 fn default() -> Self {
23 CountOption::Word
24 }
25}
26
27pub fn count(input: impl BufRead, option: CountOption) -> HashMap<String, usize> {
53 let re = Regex::new(r"\w+").unwrap();
54 let mut freqs = HashMap::new(); for line in input.lines() {
57 let line = line.unwrap();
58 use crate::CountOption::*;
59 match option {
60 Char => {
61 for c in line.chars() {
62 *freqs.entry(c.to_string()).or_insert(0) += 1;
63 }
64 }
65 Word => {
66 for m in re.find_iter(&line) {
67 let word = m.as_str().to_string();
68 *freqs.entry(word).or_insert(0) += 1;
69 }
70 }
71 Line => *freqs.entry(line.to_string()).or_insert(0) += 1,
72 }
73 }
74 freqs
75}
76
77#[test]
78fn word_count_works() {
79 use std::io::Cursor;
80
81 let mut exp = HashMap::new();
82 exp.insert("aa".to_string(), 1);
83 exp.insert("bb".to_string(), 2);
84 exp.insert("cc".to_string(), 1);
85
86 assert_eq!(count(Cursor::new("aa bb cc bb"), CountOption::Word), exp);
87}
88
89#[test]
90fn word_count_works2() {
91 use std::io::Cursor;
92
93 let mut exp = HashMap::new();
94 exp.insert("aa".to_string(), 1);
95 exp.insert("cc".to_string(), 1);
96 exp.insert("dd".to_string(), 1);
97
98 assert_eq!(count(Cursor::new("aa cc dd"), CountOption::Word), exp);
99}
100
101#[test]
102#[should_panic]
103fn word_count_do_not_contain_unknown_words() {
104 use std::io::Cursor;
105
106 count(
107 Cursor::new([
108 b'a', 0xf0, 0x90, 0x80, 0xe3, 0x81, 0x82, ]),
112 CountOption::Word,
113 );
114}
115
116#[test]
117fn word_count_works3() {
118 use std::io::Cursor;
119
120 let freqs = count(Cursor::new("aa cc dd"), CountOption::Word);
121
122 assert_eq!(freqs.len(), 3);
123 assert_eq!(freqs["aa"], 1);
124 assert_eq!(freqs["cc"], 1);
125 assert_eq!(freqs["dd"], 1);
126}
127
128#[cfg(test)]
129mod test {
130 use super::*;
131 use std::io::Cursor;
132
133 macro_rules! assert_map {
134 ($expr: expr, {$($key: expr => $value:expr),*}) => {
135 $(assert_eq!($expr[$key], $value));*
136 };
137 }
138
139 #[test]
140 fn word_count_works3() {
141 let freqs = count(Cursor::new("aa cc dd"), CountOption::Word);
142
143 assert_eq!(freqs.len(), 3);
144 assert_map!(freqs, {"aa" => 1, "cc" => 1, "dd" => 1});
145 }
146
147}