use std::collections::HashMap;
pub fn part1(lines: &[&str]) -> u32 {
let mut twice = 0;
let mut thrice = 0;
for line in lines {
let (two, three) = repeated(*line);
if two {
twice += 1;
}
if three {
thrice += 1;
}
}
(twice * thrice)
}
pub fn part2(lines: &[&str]) -> String {
for a in lines {
for b in lines {
if let Some(id) = extract(a, b) {
return id;
}
}
}
unreachable!()
}
pub fn extract(a: &str, b: &str) -> Option<String> {
debug_assert!(a.len() == b.len());
match a.chars().zip(b.chars()).filter(|x| x.0 != x.1).count() {
1 => Some(
a.chars()
.zip(b.chars())
.filter(|x| x.0 == x.1)
.map(|x| x.0)
.collect(),
),
_ => None,
}
}
pub fn repeated(line: &str) -> (bool, bool) {
let mut counts = HashMap::new();
line.chars()
.for_each(|c| *counts.entry(c).or_insert(0) += 1);
let twice = counts.iter().any(|e| *e.1 == 2);
let thrice = counts.iter().any(|e| *e.1 == 3);
(twice, thrice)
}
pub fn read(line: &str) -> Vec<&str> {
line.lines()
.map(str::trim)
.filter(|s| !s.is_empty())
.collect()
}
#[test]
fn examples() {
let one = read(
r"
abcdef
bababc
abbcde
abcccd
aabcdd
abcdee
ababab
",
);
let two = read(
r"
abcde
fghij
klmno
pqrst
fguij
axcye
wvxyz
",
);
assert_eq!(part1(&one), 12);
assert_eq!(part2(&two), String::from("fgij"));
}
#[test]
fn solution() {
let input: Vec<&str> = read(include_str!("input/2"));
assert_eq!(part1(&input), 7192);
assert_eq!(part2(&input), "mbruvapghxlzycbhmfqjonsie");
}