finish day4, reorg directory
parent
339b2c7d1d
commit
8539c8f9af
@ -1,43 +0,0 @@
|
||||
#lang racket
|
||||
(require rackunit)
|
||||
(provide read-syntax)
|
||||
|
||||
(define (get-dimensions str)
|
||||
(map string->number (regexp-match* #px"\\d+" str)))
|
||||
|
||||
(define (get-faces dimensions)
|
||||
(define half-faces
|
||||
(for*/list ([first-pos (in-range (sub1 (length dimensions)))]
|
||||
[second-pos (in-range (add1 first-pos) (length dimensions))])
|
||||
(list (list-ref dimensions first-pos) (list-ref dimensions second-pos))))
|
||||
(append* (make-list 2 half-faces)))
|
||||
|
||||
(define (str->paper str)
|
||||
(define dimensions (get-dimensions str))
|
||||
(define faces (get-faces dimensions))
|
||||
(define areas (map (curry apply *) faces))
|
||||
(define smallest-area (apply min areas))
|
||||
(apply + smallest-area areas))
|
||||
|
||||
(define (str->ribbon str)
|
||||
(define dimensions (get-dimensions str))
|
||||
(define faces (get-faces dimensions))
|
||||
(define perimeters (map (λ(face) (* 2 (apply + face))) faces))
|
||||
(define smallest-perimeter (apply min perimeters))
|
||||
(define volume (apply * dimensions))
|
||||
(+ smallest-perimeter volume))
|
||||
|
||||
(check-equal? (str->paper "2x3x4") 58)
|
||||
(check-equal? (str->paper "1x1x10") 43)
|
||||
|
||||
(check-equal? (str->ribbon "2x3x4") 34)
|
||||
(check-equal? (str->ribbon "1x1x10") 14)
|
||||
|
||||
(define (read-syntax source-path-string in-port)
|
||||
(with-syntax ([source-str (string-trim (port->string in-port))]
|
||||
[str->paper str->paper]
|
||||
[str->ribbon str->ribbon])
|
||||
#'(module _ racket
|
||||
(define package-strs (string-split 'source-str))
|
||||
(apply + (map str->paper package-strs))
|
||||
(apply + (map str->ribbon package-strs)))))
|
@ -1,47 +0,0 @@
|
||||
#lang racket
|
||||
(require rackunit)
|
||||
(provide read-syntax)
|
||||
|
||||
(define (str->visits str)
|
||||
(define start '(0 0))
|
||||
(define moves (map (λ(move) (case move
|
||||
[("^") '(0 1)]
|
||||
[("v") '(0 -1)]
|
||||
[("<") '(-1 0)]
|
||||
[(">") '(1 0)]))
|
||||
(regexp-match* #rx"." str)))
|
||||
(reverse (for/fold ([visit-acc (list start)])
|
||||
([move (in-list moves)])
|
||||
(cons (map + move (car visit-acc)) visit-acc))))
|
||||
|
||||
(define (str->unique-visits str)
|
||||
(define visits (str->visits str))
|
||||
(length (remove-duplicates visits)))
|
||||
|
||||
(define (str->robosanta str)
|
||||
(define-values (reversed-santa-path reversed-robo-path)
|
||||
(for/fold ([santa-acc empty][robo-acc empty])
|
||||
([c (in-string str)][pos (in-naturals)])
|
||||
(if (even? pos)
|
||||
(values (cons c santa-acc) robo-acc)
|
||||
(values santa-acc (cons c robo-acc)))))
|
||||
(define santa-str (string-append* (map ~a (reverse reversed-santa-path))))
|
||||
(define robo-str (string-append* (map ~a (reverse reversed-robo-path))))
|
||||
(length (remove-duplicates (append (str->visits santa-str) (str->visits robo-str)))))
|
||||
|
||||
|
||||
(check-equal? (str->unique-visits ">") 2)
|
||||
(check-equal? (str->unique-visits "^>v<") 4)
|
||||
|
||||
(check-equal? (str->robosanta "^v") 3)
|
||||
(check-equal? (str->robosanta "^>v<") 3)
|
||||
(check-equal? (str->robosanta "^v^v^v^v^v") 11)
|
||||
|
||||
|
||||
(define (read-syntax source-path-string in-port)
|
||||
(with-syntax ([source-str (string-trim (port->string in-port))]
|
||||
[str->unique-visits str->unique-visits]
|
||||
[str->robosanta str->robosanta])
|
||||
#'(module _ racket
|
||||
(str->unique-visits source-str)
|
||||
(str->robosanta source-str))))
|
@ -0,0 +1 @@
|
||||
iwrupvqb
|
@ -0,0 +1,51 @@
|
||||
#lang scribble/lp2
|
||||
@(require scribble/manual aoc-racket/helper)
|
||||
@(require (for-label openssl/md5))
|
||||
|
||||
@aoc-title[4]
|
||||
|
||||
Our @link-rp["day4-input.txt"]{input} is a string of eight characters that represents part of a key for making an MD5 hash.
|
||||
|
||||
@chunk[<day4>
|
||||
<setup>
|
||||
<q1>
|
||||
<q2>
|
||||
<test>]
|
||||
|
||||
@section{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 @racketmodname[openssl/md5] module and the @racket[md5] function. Then, this puzzle is easy: starting at @racket[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 @secref["day-1"].)
|
||||
|
||||
|
||||
@chunk[<setup>
|
||||
(require racket rackunit openssl/md5)
|
||||
]
|
||||
|
||||
@chunk[<q1>
|
||||
(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)))
|
||||
]
|
||||
|
||||
@section{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.
|
||||
|
||||
@chunk[<q2>
|
||||
(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)))]
|
||||
|
||||
@section{Testing our input}
|
||||
|
||||
@chunk[<test>
|
||||
(module+ test
|
||||
(define input-str (file->string "day4-input.txt"))
|
||||
(check-equal? (q1 input-str) 346386)
|
||||
(check-equal? (q2 input-str) 9958218))]
|
Reference in New Issue