adventofcode-2020/day-2/src/main.rs

95 lines
2.5 KiB
Rust

use std::fs;
type PasswordPolicy = (usize, usize, char);
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = fs::read_to_string("input")?;
println!("{}", count_valid_passwords(&input, &validate_password_new));
Ok(())
}
fn parse_password_line(line: &str) -> Result<(PasswordPolicy, &str), Box<dyn std::error::Error>> {
let mut sections = line.split(' ');
let range = sections
.next()
.ok_or("Password line too short")?
.split('-')
.map(|c| c.parse::<usize>())
.collect::<Result<Vec<usize>, _>>()?;
let character = sections
.next()
.ok_or("Password line too short")?
.chars()
.next()
.ok_or("Password line too short")?;
let password = sections.next().ok_or("Password line too short")?;
Ok(((range[0], range[1], character), password))
}
fn validate_password_old(policy: &PasswordPolicy, password: &str) -> bool {
let (start, end, character) = policy;
let occurrences = password.chars().filter(|c| c == character).count();
*start <= occurrences && occurrences <= *end
}
fn validate_password_new(policy: &PasswordPolicy, password: &str) -> bool {
let (position1, position2, character) = policy;
let position1_is_character = password
.chars()
.nth(position1 - 1)
.expect("Password too short")
== *character;
let position2_is_character = password
.chars()
.nth(position2 - 1)
.expect("Password too short")
== *character;
(position1_is_character || position2_is_character)
&& (!position1_is_character || !position2_is_character)
}
fn count_valid_passwords(input: &str, validate: &dyn Fn(&PasswordPolicy, &str) -> bool) -> usize {
input
.lines()
.filter(|line| {
if let Ok((policy, password)) = parse_password_line(line) {
validate(&policy, password)
} else {
false
}
})
.count()
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
#[test]
fn test_simple() {
let example = indoc!(
"1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc"
);
assert_eq!(count_valid_passwords(&example, &validate_password_old), 2);
}
#[test]
fn test_simple2() {
let example = indoc!(
"1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc"
);
assert_eq!(count_valid_passwords(&example, &validate_password_new), 1);
}
}