use std::collections::HashMap; use std::fmt::Debug; use std::hash::Hash; use std::io::BufRead; use std::io::BufReader; use std::io::Read; use std::iter::FromIterator; use std::str::FromStr; /// Read input line by line and try to parse it into some collection. pub fn from_lines(input: &mut dyn Read) -> T where I: FromStr, E: Debug, T: FromIterator, { let reader = BufReader::new(input); reader .lines() .map(|line| line.unwrap().parse::().unwrap()) .collect() } /// Parse the entire input into a single variable pub fn read_single_input(input: &mut dyn Read) -> T where T: FromStr, ::Err: Debug, { let mut buf = String::new(); input.read_to_string(&mut buf).unwrap(); buf.trim().parse().unwrap() } pub fn read_char_grid(input: &mut dyn Read) -> Vec> { BufReader::new(input) .lines() // filter_map avoids an expensive unwrap and we know our input is valid ascii .filter_map(|s| s.ok().map(String::into_bytes)) .collect() } /// An interface to count elements in particular categories. pub trait GroupingCount { /// The type of the categories under inspection type Type; /// Count the occurrence of all possible values. /// /// This method will return a map from a value to its occurrence rate. fn grouping_count(&mut self) -> HashMap; } impl GroupingCount for T where T: Iterator, T::Item: Eq + Hash, { type Type = T::Item; fn grouping_count(&mut self) -> HashMap { let mut counts = HashMap::new(); for element in self { *counts.entry(element).or_insert(0) += 1; } counts } } #[cfg(test)] mod tests { use super::*; #[test] fn test_grouping_count() { let result = [1, 1, 2, 2, 3, 1].iter().grouping_count(); assert_eq!(3, result[&1]); assert_eq!(2, result[&2]); assert_eq!(1, result[&3]); } }