-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.rs
105 lines (89 loc) · 2.24 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#![warn(clippy::all, clippy::pedantic)]
use itertools::Itertools;
pub fn main() {
print!("Part 1: ");
print_password(part_one("vzbxkghb"));
print!("Part 2: ");
print_password(part_two("vzbxkghb"));
}
fn part_one(data: &str) -> Password {
let password = new_password(data);
next_valid_password(password)
}
fn part_two(data: &str) -> Password {
let password = new_password(data);
let password = next_valid_password(password);
next_valid_password(password)
}
type Password = [u8; 8];
fn next_valid_password(mut password: Password) -> Password {
next_password(&mut password);
while !is_valid(password) {
next_password(&mut password);
}
password
}
fn print_password(password: Password) {
for elem in password.into_iter().rev() {
if elem != 0 {
let c = char::from_u32(u32::from(elem)).unwrap();
print!("{c}");
}
}
println!();
}
fn new_password(data: &str) -> Password {
let mut password = Password::default();
for (p, b) in password.iter_mut().zip(data.as_bytes().iter().rev()) {
*p = *b;
}
password
}
fn next_password(curr: &mut Password) {
for (i, elem) in curr.iter_mut().enumerate() {
match elem {
b'z' => *elem = b'a',
b'h' | b'k' | b'n' => {
*elem += 2;
for item in curr.iter_mut().take(i) {
*item = b'a';
}
return;
}
_ => {
*elem += 1;
return;
}
}
}
}
fn is_valid(password: Password) -> bool {
contains_straight(password) && two_pairs(password)
}
fn contains_straight(password: Password) -> bool {
for (a, b, c) in password.into_iter().tuple_windows::<(_, _, _)>() {
if a == b + 1 && b == c + 1 {
return true;
}
}
false
}
fn two_pairs(password: Password) -> bool {
password
.into_iter()
.dedup_with_count()
.filter(|(c, _)| c >= &2)
.count()
>= 2
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn one() {
assert_eq!(
[b'a', b'a', b'f', b'f', b'd', b'c', b'b', b'a'],
part_one("abcdefgh")
);
}
}