Skip to content

Commit 4e2262b

Browse files
committed
refactor(14/2016): create md5 tuple struct
1 parent 110996e commit 4e2262b

File tree

1 file changed

+62
-22
lines changed

1 file changed

+62
-22
lines changed

src/solutions/year2016/day14.rs

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ impl Solution for Day14 {
1010
let input = input.trim();
1111
let hash_generator = HashGenerator::new(input.to_string());
1212
let mut count = 0;
13+
let three_tuples = Md5Tuple::new(3);
14+
let five_tuples = Md5Tuple::new(5);
1315

1416
for i in 0usize.. {
1517
let three_hash = hash_generator.get(i);
1618

17-
if let Some(first_three_tuple) = self.find_first_tuple(&three_hash, 3) {
19+
if let Some(first_three_tuple) = three_tuples.find_first_tuple(three_hash) {
1820
for j in i + 1..=i + 1000 {
1921
let five_hash = hash_generator.get(j);
2022

21-
if self.contains_tuple(&five_hash, first_three_tuple, 5) {
23+
if five_tuples.contains_tuple(&five_hash, first_three_tuple) {
2224
count += 1;
2325

2426
if count == 64 {
@@ -67,36 +69,59 @@ impl HashGenerator {
6769
}
6870
}
6971

70-
impl Day14 {
71-
fn find_first_tuple(&self, digest: &str, length: usize) -> Option<u8> {
72-
let mut iter = digest.bytes();
73-
let mut current = iter.next().unwrap();
72+
struct Md5Tuple {
73+
length: usize,
74+
first_tuple_cache: RefCell<HashMap<String, Option<u8>>>,
75+
}
7476

75-
let mut count = 1;
77+
impl Md5Tuple {
78+
fn new(length: usize) -> Md5Tuple {
79+
Self {
80+
length,
81+
first_tuple_cache: RefCell::new(HashMap::new()),
82+
}
83+
}
7684

77-
for c in iter {
78-
if c == current {
79-
count += 1;
85+
fn find_first_tuple(&self, digest: String) -> Option<u8> {
86+
if let Some(cached) = self.first_tuple_cache.borrow().get(&digest.clone()) {
87+
return *cached;
88+
}
89+
90+
let result = {
91+
let str = digest.as_str();
92+
let mut iter = str.bytes();
93+
let mut current = iter.next().unwrap();
8094

81-
if count == length {
82-
return Some(c);
95+
let mut count = 1;
96+
97+
for c in iter {
98+
if c == current {
99+
count += 1;
100+
101+
if count == self.length {
102+
return Some(c);
103+
}
104+
} else {
105+
current = c;
106+
count = 1;
83107
}
84-
} else {
85-
current = c;
86-
count = 1;
87108
}
88-
}
89109

90-
None
110+
None
111+
};
112+
113+
self.first_tuple_cache.borrow_mut().insert(digest, result);
114+
115+
result
91116
}
92117

93-
fn contains_tuple(&self, digest: &str, char_byte: u8, target_len: usize) -> bool {
118+
fn contains_tuple(&self, digest: &str, char_byte: u8) -> bool {
94119
let mut count = 0;
95120

96121
for &byte in digest.as_bytes() {
97122
if byte == char_byte {
98123
count += 1;
99-
if count == target_len {
124+
if count == self.length {
100125
return true;
101126
}
102127
} else {
@@ -121,8 +146,23 @@ mod tests {
121146

122147
#[test]
123148
fn find_all_tuples() {
124-
assert_eq!(b'8', Day14.find_first_tuple("cc38887a5", 3).unwrap());
125-
assert_eq!(b'8', Day14.find_first_tuple("cc38887aaa5", 3).unwrap());
126-
assert_eq!(b'a', Day14.find_first_tuple("aaa", 3).unwrap());
149+
assert_eq!(
150+
b'8',
151+
Md5Tuple::new(3)
152+
.find_first_tuple("cc38887a5".to_string())
153+
.unwrap()
154+
);
155+
assert_eq!(
156+
b'8',
157+
Md5Tuple::new(3)
158+
.find_first_tuple("cc38887aaa5".to_string())
159+
.unwrap()
160+
);
161+
assert_eq!(
162+
b'a',
163+
Md5Tuple::new(3)
164+
.find_first_tuple("aaa".to_string())
165+
.unwrap()
166+
);
127167
}
128168
}

0 commit comments

Comments
 (0)