use std::collections::HashMap; use std::io; use std::io::prelude::*; use common; /// Count the occurrence characters in a string. fn count_chars(word: &str) -> HashMap { let mut counts: HashMap = HashMap::new(); for c in word.chars() { *counts.entry(c).or_insert(0) += 1; } counts } /// Compute the number of different positions between two strings. fn distance(a: &str, b: &str) -> usize { let mut dist = 0; for (a, b) in a.chars().zip(b.chars()) { if a != b { dist += 1; } } dist } #[derive(Default)] pub struct Day02 { } impl Day02 { pub fn new() -> Day02 { Default::default() } } impl common::Solution for Day02 { fn part1(&mut self, input: &mut io::Read) -> String { let reader = io::BufReader::new(input); let mut twos = 0; let mut threes = 0; for line in reader.lines() { let counts = count_chars(&line.unwrap()); if counts.values().any(|&x| x == 2) { twos += 1; } if counts.values().any(|&x| x == 3) { threes += 1; } } return format!("{}", twos * threes); } fn part2(&mut self, input: &mut io::Read) -> String { let mut ids: Vec = io::BufReader::new(input) .lines() .map(|x| x.unwrap()).collect(); ids.sort_unstable(); for id1 in &ids { for id2 in &ids { if id2 > id1 { break; } if distance(id1, id2) == 1 { let mut answer = String::new(); for (a, b) in id1.chars().zip(id2.chars()) { if a == b { answer.push(a); } } return answer; } } } unreachable!("Input does not contain a valid solution."); } } #[cfg(test)] mod tests { use super::*; #[test] fn test_count_letters() { let result = count_chars("abcaba"); assert_eq!(3, *result.get(&'a').unwrap()); assert_eq!(2, *result.get(&'b').unwrap()); assert_eq!(1, *result.get(&'c').unwrap()) } #[test] fn test_distance() { assert_eq!(2, distance("abcde", "axcye")); assert_eq!(1, distance("fghij", "fguij")); } }