Skip to content

Commit 002bc91

Browse files
committed
Refactor Day 5 2016 and add MD5 utility class. Extracted common MD5 hashing functionality into a reusable utility class and simplified Day 5 implementation.
1 parent d06f615 commit 002bc91

File tree

2 files changed

+52
-39
lines changed

2 files changed

+52
-39
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.sbaars.adventofcode.common;
2+
3+
import java.nio.charset.StandardCharsets;
4+
import java.security.MessageDigest;
5+
import java.security.NoSuchAlgorithmException;
6+
7+
public class MD5 {
8+
private static final MessageDigest md;
9+
10+
static {
11+
try {
12+
md = MessageDigest.getInstance("MD5");
13+
} catch (NoSuchAlgorithmException e) {
14+
throw new RuntimeException("MD5 algorithm not available", e);
15+
}
16+
}
17+
18+
public static byte[] hash(String input) {
19+
return md.digest(input.getBytes(StandardCharsets.UTF_8));
20+
}
21+
22+
public static boolean hasLeadingZeros(byte[] hash, int numZeros) {
23+
int fullBytes = numZeros / 2;
24+
int remainingNibbles = numZeros % 2;
25+
26+
// Check full bytes
27+
for (int i = 0; i < fullBytes; i++) {
28+
if (hash[i] != 0) return false;
29+
}
30+
31+
// Check remaining nibble if needed
32+
return remainingNibbles == 0 || (hash[fullBytes] & 0xF0) == 0;
33+
}
34+
35+
public static char toHexChar(int nibble) {
36+
return (char) (nibble < 10 ? ('0' + nibble) : ('a' + (nibble - 10)));
37+
}
38+
}
Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package com.sbaars.adventofcode.year16.days;
22

33
import com.sbaars.adventofcode.year16.Day2016;
4+
import com.sbaars.adventofcode.common.MD5;
45

5-
import java.nio.charset.StandardCharsets;
6-
import java.security.MessageDigest;
7-
import java.security.NoSuchAlgorithmException;
86
import java.util.Arrays;
97

108
public class Day5 extends Day2016 {
@@ -23,22 +21,12 @@ public Object part1() {
2321
StringBuilder password = new StringBuilder();
2422
int index = 0;
2523

26-
try {
27-
MessageDigest md = MessageDigest.getInstance("MD5");
28-
while (password.length() < 8) {
29-
byte[] digest = md.digest((doorId + index).getBytes(StandardCharsets.UTF_8));
30-
31-
// Check if first 20 bits (5 hex zeroes) are zero
32-
// digest[0] == 0 && digest[1] == 0 && (digest[2] & 0xF0) == 0
33-
if (digest[0] == 0 && digest[1] == 0 && (digest[2] & 0xF0) == 0) {
34-
// The 6th hex character is the low nibble of digest[2]
35-
int nib5 = digest[2] & 0x0F;
36-
password.append(toHexChar(nib5));
37-
}
38-
index++;
24+
while (password.length() < 8) {
25+
byte[] hash = MD5.hash(doorId + index);
26+
if (MD5.hasLeadingZeros(hash, 5)) {
27+
password.append(MD5.toHexChar(hash[2] & 0x0F));
3928
}
40-
} catch (NoSuchAlgorithmException e) {
41-
throw new RuntimeException(e);
29+
index++;
4230
}
4331
return password.toString();
4432
}
@@ -51,30 +39,17 @@ public Object part2() {
5139
int filled = 0;
5240
int index = 0;
5341

54-
try {
55-
MessageDigest md = MessageDigest.getInstance("MD5");
56-
while (filled < 8) {
57-
byte[] digest = md.digest((doorId + index).getBytes(StandardCharsets.UTF_8));
58-
// Same check as above
59-
if (digest[0] == 0 && digest[1] == 0 && (digest[2] & 0xF0) == 0) {
60-
// 6th hex character is nib5 (low nibble of digest[2]), 7th is nib6 (high nibble of digest[3])
61-
int nib5 = digest[2] & 0x0F; // position
62-
int nib6 = (digest[3] & 0xF0) >>> 4; // actual character
63-
64-
if (nib5 < 8 && password[nib5] == '_') {
65-
password[nib5] = toHexChar(nib6);
66-
filled++;
67-
}
42+
while (filled < 8) {
43+
byte[] hash = MD5.hash(doorId + index);
44+
if (MD5.hasLeadingZeros(hash, 5)) {
45+
int pos = hash[2] & 0x0F;
46+
if (pos < 8 && password[pos] == '_') {
47+
password[pos] = MD5.toHexChar((hash[3] & 0xF0) >>> 4);
48+
filled++;
6849
}
69-
index++;
7050
}
71-
} catch (NoSuchAlgorithmException e) {
72-
throw new RuntimeException(e);
51+
index++;
7352
}
7453
return new String(password);
7554
}
76-
77-
private static char toHexChar(int nibble) {
78-
return (char) (nibble < 10 ? ('0' + nibble) : ('a' + (nibble - 10)));
79-
}
8055
}

0 commit comments

Comments
 (0)