AoC2019/src/day4.rs

85 lines
2.2 KiB
Rust

use std::io::BufRead;
fn parse_input<F: BufRead> (input: &mut F) -> (u32, u32) {
let mut buf = String::new();
let _num_bytes = input.read_line(&mut buf).expect("Unable to read a line of input file");
let mut it = buf.split("-").map(|s| s.trim().parse::<u32>().unwrap());
let start = it.next().unwrap();
let end = it.next().unwrap();
(start, end)
}
pub fn part1<F: BufRead> (mut input: F) {
let range = parse_input(&mut input);
let passwords = find_passwords(range, verify_password1);
println!("{}", passwords.len());
}
pub fn part2<F: BufRead> (mut input: F) {
let range = parse_input(&mut input);
let passwords = find_passwords(range, verify_password2);
println!("{}", passwords.len());
}
fn find_passwords<P: FnMut(&u32) -> bool>((start, end): (u32, u32), verify_fn: P) -> Vec<u32> {
(start..=end)
.filter(verify_fn)
.collect()
}
fn verify_password1(n: &u32) -> bool {
let v: Vec<u32> = n.to_string()
.chars()
.map(|c| c.to_digit(10).unwrap())
.collect();
v.is_sorted() && v.windows(2).find(|w| w[0] == w[1]).is_some()
}
fn verify_password2(n: &u32) -> bool {
let v: Vec<u32> = n.to_string()
.chars()
.map(|c| c.to_digit(10).unwrap())
.collect();
let mut last_digit = v[0];
let mut group_size = 1;
v.is_sorted() && {
for digit in &v[1..] {
if last_digit == *digit {
group_size += 1;
} else {
if group_size == 2 {
break;
}
group_size = 1;
}
last_digit = *digit;
}
group_size == 2
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_verify_password1() {
assert_eq!(verify_password1(&111111), true);
assert_eq!(verify_password1(&223450), false);
assert_eq!(verify_password1(&123789), false);
}
#[test]
fn test_verify_password2() {
assert!(verify_password2(&112233));
assert!(!verify_password2(&123444));
assert!(verify_password2(&111244));
assert!(!verify_password2(&488884));
assert!(verify_password2(&111122));
}
}