On this page:
<day04>
4.1 What is the lowest-numbered MD5 hash starting with five zeroes?
<day04-setup>
<day04-q1>
4.2 How about six zeroes?
<day04-q2>
4.3 Testing Day 4
<day04-test>
7.1

4 Day 4

 (require aoc-racket/day04) package: aoc-racket

The puzzle. Our input is a string of eight characters that represents part of a key for making an MD5 hash.

4.1 What is the lowest-numbered MD5 hash starting with five zeroes?

We’re asked to create an MD5 hash from an input key that consists of our eight-character input joined to a decimal number. The puzzle asks us to find the lowest decimal number that, when joined to our input, produces an MD5 hash that starts with five zeroes.

Whether or not you already know what an MD5 hash is, you can search the Racket docs and will soon find the openssl/md5 module and the md5 function. Then, this puzzle is easy: starting at 0, make new input keys with each integer, and stop when we find one that results in the MD5 hash we want. (The approach is similar to the second part of Day 1.)

(require racket rackunit openssl/md5)
(provide (all-defined-out))

(define (q1 str)
  (for/or ([i (in-naturals)])
          (define md5-key (string-append str (~a i)))
          (define md5-hash (md5 (open-input-string md5-key)))
          (and (string-prefix? md5-hash "00000") i)))

4.2 How about six zeroes?

Exactly the same, except we test for a string of six zeroes. It is likely, however, to take quite a bit longer to run, as the sixth zero essentially makes the criterion 10 times more stringent.

(define (q2 str)
  (for/or ([i (in-naturals)])
          (define md5-key (string-append str (~a i)))
          (define md5-hash (md5 (open-input-string md5-key)))
          (and (string-prefix? md5-hash "000000") i)))

4.3 Testing Day 4

(module+ test
  (define input-str (file->string "day04-input.txt"))
  (check-equal? (q1 input-str) 346386)
  (check-equal? (q2 input-str) 9958218))