Add 9 first days

This commit is contained in:
2021-01-08 23:41:37 +11:00
parent 4846e7c811
commit 2fd73ae5d1
49 changed files with 9734 additions and 0 deletions

1
2-password_philosophy/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

70
2-password_philosophy/Cargo.lock generated Normal file
View 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"

View 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"

File diff suppressed because it is too large Load Diff

View 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(),
)
)
}
}