Add 9 first days
This commit is contained in:
1
2-password_philosophy/.gitignore
vendored
Normal file
1
2-password_philosophy/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
||||
70
2-password_philosophy/Cargo.lock
generated
Normal file
70
2-password_philosophy/Cargo.lock
generated
Normal file
@@ -0,0 +1,70 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c0df63cb2955042487fad3aefd2c6e3ae7389ac5dc1beb28921de0b69f779d4"
|
||||
|
||||
[[package]]
|
||||
name = "password_philosophy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[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.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
11
2-password_philosophy/Cargo.toml
Normal file
11
2-password_philosophy/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "password_philosophy"
|
||||
version = "0.1.0"
|
||||
authors = ["Guilhem MARION <gmarion@netc.fr>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.35"
|
||||
thiserror = "1.0.22"
|
||||
1000
2-password_philosophy/data/input.txt
Normal file
1000
2-password_philosophy/data/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
111
2-password_philosophy/src/main.rs
Normal file
111
2-password_philosophy/src/main.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use std::ops::RangeInclusive;
|
||||
use anyhow::Result;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct PasswordPolicy {
|
||||
char: u8,
|
||||
range: RangeInclusive<usize>,
|
||||
}
|
||||
|
||||
impl PasswordPolicy {
|
||||
fn check_password(&self, password: &str) -> bool {
|
||||
self.range.contains(
|
||||
&password
|
||||
.as_bytes()
|
||||
.iter().
|
||||
filter(|&&c| c == self.char)
|
||||
.count()
|
||||
)
|
||||
}
|
||||
|
||||
fn check_password_newpolicy(&self, password: &str) -> bool {
|
||||
(password.chars().nth(self.range.start()-1).unwrap() as u8 == self.char) ^ (password.chars().nth(self.range.end()-1).unwrap() as u8 == self.char)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
enum ParseError {
|
||||
#[error("Expected {0}")]
|
||||
Expected(&'static str)
|
||||
}
|
||||
|
||||
fn parse_line(line: &str) -> Result<(PasswordPolicy,String)> {
|
||||
let (policy_s, password) = {
|
||||
let mut tokens = line.split(": ");
|
||||
(
|
||||
tokens.next().ok_or(ParseError::Expected("Coucou"))?,
|
||||
tokens.next().ok_or(ParseError::Expected("Coincoin"))?,
|
||||
)
|
||||
};
|
||||
let policy = {
|
||||
let (range_s, char_s) = {
|
||||
let mut tokens = policy_s.split(' ');
|
||||
(
|
||||
tokens.next().ok_or(ParseError::Expected("Range"))?,
|
||||
tokens.next().ok_or(ParseError::Expected("Char"))?,
|
||||
)
|
||||
};
|
||||
let (min_s, max_s) = {
|
||||
let mut tokens = range_s.split('-');
|
||||
(
|
||||
tokens.next().ok_or(ParseError::Expected("Min"))?,
|
||||
tokens.next().ok_or(ParseError::Expected("Max"))?,
|
||||
)
|
||||
};
|
||||
PasswordPolicy {
|
||||
char: if char_s.len() == 1 {
|
||||
char_s.as_bytes()[0]
|
||||
} else {
|
||||
// return Err(ParseError::Expected("policy byte to be exactly one byte"));
|
||||
return Err(ParseError::Expected("password policy byte to be exactly 1 byte").into());
|
||||
},
|
||||
range: (min_s.parse()?)..=(max_s.parse()?),
|
||||
}
|
||||
};
|
||||
Ok((policy, password.to_string()))
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let count = include_str!("../data/input.txt")
|
||||
.lines()
|
||||
.map(parse_line)
|
||||
.map(Result::unwrap)
|
||||
.filter(|(policy,password)| policy.check_password(password))
|
||||
.count();
|
||||
println!("{} passes are valid", count);
|
||||
let count_new_policy = include_str!("../data/input.txt")
|
||||
.lines()
|
||||
.map(parse_line)
|
||||
.map(Result::unwrap)
|
||||
.filter(|(policy,password)| policy.check_password_newpolicy(password))
|
||||
.count();
|
||||
println!("{} passes are valid with new policy", count_new_policy);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_is_valid() {
|
||||
let policy = PasswordPolicy{ char: b'b', range: 1..=4 };
|
||||
assert_eq!(policy.check_password("boumbaby"), true);
|
||||
assert_eq!(policy.check_password("b-b-b-boumbaby"), false);
|
||||
assert_eq!(policy.check_password("oumay"), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_line() {
|
||||
assert_eq!(
|
||||
parse_line("1-5 b: boulbi").unwrap(),
|
||||
(
|
||||
PasswordPolicy {
|
||||
char: b'b',
|
||||
range: 1..=5,
|
||||
},
|
||||
"boulbi".to_owned(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user