Alpha Chen 8 years ago
parent 2044e43b34
commit 050f7577ec

@ -0,0 +1,104 @@
use std::collections::HashSet;
#[derive(Debug, Eq, PartialEq)]
pub struct Password(String);
impl Password {
pub fn new(s: &str) -> Self {
Password(s.into())
}
pub fn is_valid(&self) -> bool {
self.has_increasing_straight() && !self.has_confusing_chars() &&
self.has_different_nonoverlapping_pairs()
}
pub fn next(&self) -> Self {
StringIncrementor::new(&self.0).map(|x| Self::new(&x)).find(|ref x| {
x.is_valid()
}).unwrap()
}
fn has_increasing_straight(&self) -> bool {
self.0
.chars()
.collect::<Vec<_>>()
.windows(3)
.any(|w| w.windows(2).all(|x| (x[1] as i8) - (x[0] as i8) == 1))
}
fn has_confusing_chars(&self) -> bool {
self.0.chars().any(|c| ['i', 'l', 'o'].contains(&c))
}
fn has_different_nonoverlapping_pairs(&self) -> bool {
let slice = self.0.chars().collect::<Vec<_>>();
slice.windows(2).filter_map(|x| {
if x[0] == x[1] { Some(x[0]) } else { None }
}).collect::<HashSet<_>>().len() > 1
}
}
impl From<Password> for String {
fn from(p: Password) -> String {
p.0
}
}
struct StringIncrementor {
s: String,
}
impl StringIncrementor {
fn new(s: &str) -> Self {
StringIncrementor{s: s.into()}
}
}
impl Iterator for StringIncrementor {
type Item = String;
fn next(&mut self) -> Option<String> {
self.s = self.s.chars()
.rev()
.scan(true, |carry, x| {
if !*carry {
return Some(x);
}
if x == 'z' {
Some('a')
} else {
*carry = false;
Some((x as u8 + 1) as char)
}
})
.collect::<Vec<_>>()
.iter()
.map(|&x| x)
.rev()
.collect();
Some(self.s.clone())
}
}
#[test]
fn test_string_incrementor() {
assert_eq!(StringIncrementor::new("abcdefgh").next(), Some("abcdefgi".into()));
assert_eq!(StringIncrementor::new("az").next(), Some("ba".into()));
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_password() {
assert!(!Password::new("hijklmmn").is_valid());
assert!(!Password::new("abbceffg").is_valid());
assert!(!Password::new("abbcegjk").is_valid());
assert!(!Password::new("ghjaaaaa").is_valid());
assert_eq!(Password::new("abcdefgh").next(), Password::new("abcdffaa"));
assert_eq!(Password::new("ghijklmn").next(), Password::new("ghjaabcc"));
}
}

@ -14,3 +14,4 @@ pub mod day_07;
pub mod day_08;
pub mod day_09;
pub mod day_10;
pub mod day_11;

@ -20,7 +20,8 @@ fn main() {
Some("7") => day_07::solve(&input, "a").to_string(),
Some("8") => day_08::solve(&input).to_string(),
Some("9") => day_09::solve(&input).to_string(),
_ => day_10::solve(&input),
Some("10") => day_10::solve(&input).to_string(),
_ => day_11::Password::new("cqjxjnds").next().into(),
};
println!("{}", solution);

Loading…
Cancel
Save