Skip to content

Commit e65f62b

Browse files
committed
format!() too slow
1 parent 309ec7f commit e65f62b

File tree

1 file changed

+44
-15
lines changed

1 file changed

+44
-15
lines changed

2016/day14/day14.rs

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
//! [Day 14: One-Time Pad](https://adventofcode.com/2016/day/14)
22
33
use rustc_hash::FxHashMap;
4-
// use std::time::Instant;
54

65
/// Solve the day 14 puzzle.
76
fn main() {
87
let args = aoc::parse_args();
98

109
let data = args.input.trim_ascii();
1110

12-
// let now = Instant::now();
13-
14-
println!("{}", solve(data, 0));
15-
println!("{}", solve(data, 2016));
16-
17-
// let micros = now.elapsed().as_micros();
18-
// println!("elapsed: {}.{:06} s", micros / 1_000_000, micros % 1_000_000);
11+
println!("{}", solve(data.as_bytes(), 0));
12+
println!("{}", solve(data.as_bytes(), 2016));
1913
}
2014

15+
const HEX_DIGITS: [u8; 16] = [
16+
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f',
17+
];
18+
2119
/// Triplet for a given index.
2220
#[derive(Debug, Clone, Copy)]
2321
struct TripletHash {
24-
index: usize, // index that produces hash with triplet
22+
index: u32, // index that produces hash with triplet
2523
triplet: u8, // the first triplet of the hash
2624
quintuplet: [u8; 6], // six quintuplets max in 32 digits
2725
}
@@ -30,16 +28,47 @@ impl TripletHash {
3028
/// Find the next index that produces a hash that contains a triplet
3129
/// and search for eventual quintuplets. As quintuplets are also triplets,
3230
/// we cannot miss them.
33-
fn next(index: usize, salt: &str, key_stretching: usize) -> Self {
31+
fn next(index: u32, salt: &[u8], key_stretching: u32) -> Self {
3432
let mut index = index;
3533

34+
let salt_len = salt.len();
35+
let mut hash = [0u8; 32];
36+
37+
hash[..salt_len].copy_from_slice(salt);
38+
3639
loop {
37-
let hash = format!("{salt}{index}");
38-
let mut digest = md5::compute(hash);
40+
// number of digits of index
41+
let mut hash_len = salt_len;
42+
let mut tmp_index = index;
43+
loop {
44+
hash_len += 1;
45+
tmp_index /= 10;
46+
if tmp_index == 0 {
47+
break;
48+
}
49+
}
50+
// write digits of index in hash
51+
let mut tmp_index = index;
52+
let mut i = hash_len;
53+
loop {
54+
i -= 1;
55+
hash[i] = (tmp_index % 10) as u8 + b'0';
56+
tmp_index /= 10;
57+
if tmp_index == 0 {
58+
break;
59+
}
60+
}
61+
62+
let mut digest = md5::compute(&hash[..hash_len]);
3963

4064
// apply key stretching
4165
for _ in 0..key_stretching {
42-
let hex = format!("{digest:x}");
66+
let mut hex = [0u8; 32];
67+
for (i, b) in digest.0.iter().enumerate() {
68+
hex[i * 2] = HEX_DIGITS[usize::from(b >> 4)];
69+
hex[i * 2 + 1] = HEX_DIGITS[usize::from(b & 0xf)];
70+
}
71+
4372
digest = md5::compute(hex);
4473
}
4574

@@ -96,7 +125,7 @@ impl TripletHash {
96125
}
97126

98127
/// Find the 64th key with the given salt and key stretching.
99-
fn solve(salt: &str, key_stretching: usize) -> usize {
128+
fn solve(salt: &[u8], key_stretching: u32) -> u32 {
100129
let mut memoize = FxHashMap::default();
101130

102131
let mut hasher = |index| {
@@ -142,7 +171,7 @@ fn solve(salt: &str, key_stretching: usize) -> usize {
142171

143172
#[test]
144173
fn test_solve1() {
145-
assert_eq!(solve("abc", 0), 22728);
174+
assert_eq!(solve("abc".as_bytes(), 0), 22728);
146175
}
147176

148177
#[test]

0 commit comments

Comments
 (0)