#lang br/quicklang (require openssl/md5) (provide read-syntax) (define (read-syntax path port) (strip-bindings #`(module mod "lang.rkt" (solve #,(string-trim (port->string port)))))) (provide #%module-begin) (define (solve key) (define-values (part-a-solution part-b-solution) (for*/fold ([part-a empty] [part-b (make-vector 8 #f)]) ([idx (in-naturals 1000000)] [this-key (in-value (format "~a~a" key idx))] #:break (and (= 8 (length part-a)) (andmap string? (vector->list part-b)))) (define this-hash (md5 (open-input-string this-key))) (define next-part-a (if (and (not (= 8 (length part-a))) (string-prefix? this-hash "00000")) (let ([next-str (substring this-hash 5 6)]) (displayln (format "part a progress: ~a" next-str)) (cons next-str part-a)) part-a)) (define next-part-b (let () (when (and (string-prefix? this-hash "00000") (string->number (substring this-hash 5 6)) (<= 0 (string->number (substring this-hash 5 6)) 7) (not (vector-ref part-b (string->number (substring this-hash 5 6))))) (displayln (format "part b progress: idx ~a, hash ~a, ~a at ~a" idx this-hash (substring this-hash 6 7) (substring this-hash 5 6))) (vector-set! part-b (string->number (substring this-hash 5 6)) (substring this-hash 6 7))) part-b)) (values next-part-a next-part-b))) (displayln (format "part a: ~a" (apply string-append (reverse part-a-solution)))) (displayln (format "part b: ~a" (apply string-append (vector->list part-b-solution))))) (provide solve)