Complete day 2
This commit is contained in:
parent
c19268deca
commit
b60f6df370
1
day-2/.gitignore
vendored
Normal file
1
day-2/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
78
day-2/Cargo.lock
generated
Normal file
78
day-2/Cargo.lock
generated
Normal file
|
@ -0,0 +1,78 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "day-2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"indoc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8"
|
||||
dependencies = [
|
||||
"indoc-impl",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indoc-impl"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"unindent",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "unindent"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
|
8
day-2/Cargo.toml
Normal file
8
day-2/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day-2"
|
||||
version = "0.1.0"
|
||||
authors = ["Tristan Daniël Maat <tm@tlater.net>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
indoc = "0.3"
|
1000
day-2/input
Normal file
1000
day-2/input
Normal file
File diff suppressed because it is too large
Load diff
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…
Reference in a new issue