Complete day 2
This commit is contained in:
parent
c19268deca
commit
b60f6df370
5 changed files with 1181 additions and 0 deletions
day-2/src
94
day-2/src/main.rs
Normal file
94
day-2/src/main.rs
Normal file
|
@ -0,0 +1,94 @@
|
|||
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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue