-
Notifications
You must be signed in to change notification settings - Fork 9
/
day04.rs
91 lines (78 loc) · 2.63 KB
/
day04.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
//! # Secure Container
//!
//! We speed things up by only checking numbers that have digits in non-decreasing order for pairs.
//! These numbers become rapidly less dense as the password value increases and there
//! are only 3003 total of these numbers with 6 digits.
use crate::util::parse::*;
use crate::util::slice::*;
pub fn parse(input: &str) -> Vec<u32> {
input.iter_unsigned().collect()
}
/// Password must contain at least one pair.
pub fn part1(input: &[u32]) -> u32 {
let predicate = |first: bool, second: bool, third: bool, fourth: bool, fifth: bool| {
first || second || third || fourth || fifth
};
passwords(input, predicate)
}
/// Password must contain at least one pair that's not part of a larger group.
pub fn part2(input: &[u32]) -> u32 {
let predicate = |first: bool, second: bool, third: bool, fourth: bool, fifth: bool| {
(first && !second)
|| (!first && second && !third)
|| (!second && third && !fourth)
|| (!third && fourth && !fifth)
|| (!fourth && fifth)
};
passwords(input, predicate)
}
fn passwords(input: &[u32], predicate: impl Fn(bool, bool, bool, bool, bool) -> bool) -> u32 {
let start = input[0];
let end = input[1];
// Split into six digits.
let mut digits = [
start / 100000,
(start / 10000) % 10,
(start / 1000) % 10,
(start / 100) % 10,
(start / 10) % 10,
start % 10,
];
// Increase the starting number to the next number that has all digits in non-decreasing order
// to ensure that the incrementing logic in the search loop works correctly.
// For example 223450 => 223455, 120568 => 122222 and 439999 => 444444.
for i in 1..6 {
if digits[i] < digits[i - 1] {
for j in i..6 {
digits[j] = digits[i - 1];
}
break;
}
}
let mut n = 0;
let mut count = 0;
while n <= end {
// Check current number
let first = digits[0] == digits[1];
let second = digits[1] == digits[2];
let third = digits[2] == digits[3];
let fourth = digits[3] == digits[4];
let fifth = digits[4] == digits[5];
if predicate(first, second, third, fourth, fifth) {
count += 1;
}
// Find the next number with all digits in non-decreasing order.
let mut i = 5;
while digits[i] == 9 {
i -= 1;
}
let next = digits[i] + 1;
while i <= 5 {
digits[i] = next;
i += 1;
}
// Convert number to `u32`.
n = digits.fold_decimal();
}
count
}