Overview
Comment: | Add Day 5 solutions (and false starts) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
c07d620ac0557a32d88774252beef030 |
User & Date: | joel on 2018-12-06 04:02:31 |
Other Links: | manifest | tags |
Context
2018-12-07
| ||
17:09 | Add Day 6 input check-in: b4b3f5 user: joel tags: trunk | |
2018-12-06
| ||
04:02 | Add Day 5 solutions (and false starts) check-in: c07d62 user: joel tags: trunk | |
2018-12-05
| ||
19:21 | Add Day 5 input check-in: c5988d user: joel tags: trunk | |
Changes
Added day05-try1.rkt version [5ccb76].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | #lang racket (require rackunit) (define input (string-trim (file->string "day05-input.txt"))) (define (ascii-vector str) (list->vector (map char->integer (string->list str)))) (define input-vec (ascii-vector input)) (define (ascii-at-pos str i) (char->integer (list-ref (string->list str) i))) ;; The ASCII values of characters of alternating case ("aA" or "Gg") will always differ by 32 ;; Return the first such occurrence or "" if none exists (define (first-alternating-case str) (or (for/first ([i (in-range (sub1 (string-length str)))] #:when (= 32 (abs (- (ascii-at-pos str i) (ascii-at-pos str (add1 i)))))) (substring str i (+ i 2))) "")) ;; Eliminate the first pair of characters that differ only in case (define (next-transformation str) (or (string-replace str (first-alternating-case str) "") str)) ;; Vector versions (define (next-nonzero vec i) (or (for/first ([n (in-range (min (add1 i) (vector-length vec)) (vector-length vec))] #:when (positive? (vector-ref vec n))) n) i)) (define (vec-first-alternating-case vec) (or (for/first ([i (in-range (vector-length vec))] #:when (and (positive? (vector-ref vec i)) (= 32 (abs (- (vector-ref vec i) (vector-ref vec (next-nonzero vec i))))))) (list i (next-nonzero vec i))) '())) (define (vec-next-transform! vec) (define next-pair (vec-first-alternating-case vec)) (cond [(not (empty? next-pair)) (for ([i (in-list next-pair)]) (vector-set! vec i 0)) #t] [else #f])) ;; Keep transforming as above until there's nothing left to do (define (boil str) (for/fold ([last-state ""] [current-state str] #:result current-state) ([x (in-naturals)] #:break (string=? current-state last-state)) (values current-state (next-transformation current-state)))) ;; Let's see if vectors are faster (define (vector-boil vec) (do ([xformed? (vec-next-transform! vec) (vec-next-transform! vec)]) [(not xformed?)] )) ;; I ran this function and started eating a bowl of chili. ;; When I was done with the chili it hadn't completed yet. (define (day01-part1-try1) (string-length (boil input))) (define (ascii-vector->string vec) (list->string (map integer->char (vector->list (vector-filter positive? vec))))) (define (day01-part1-try2) (vector-boil input-vec) (vector-length (vector-filter positive? input-vec))) (module+ test (check-equal? (boil "dabAcCaCBAcCcaDA") "dabCBAcaDA") ;; Takes about 64sec on my laptop (check-equal? (time (day01-part1-try2)) 10584)) ; Correct answer for part one |
Added day05.rkt version [c264ac].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | #lang racket (require rackunit sugar/debug) ;; For efficiency and convenience, I'll be dealing with inputs as ASCII values. (define (ascii-list str) (map char->integer (string->list str))) (define input (ascii-list (string-trim (file->string "day05-input.txt")))) ;; Treating lst as a stack, push an ASCII value on top. ;; If the new value is the same letter as the current top value ;; but differs by upper/lower case, eliminate both values. (define (push-and-react lst val) (cond [(empty? lst) (list val)] [(= 32 (abs (- (car lst) val))) (rest lst)] [else (cons val lst)])) ;; Return a fully "reacted" version of the input list. ;; Reverses the list in the process, but the order of the finished ;; list does not matter for the solution, only the length. (define (boil lst) (for/fold ([output '()]) ([v (in-list lst)]) (push-and-react output v))) ;; There it is: computes in 6msec! (define (day05-part1) (length (boil input))) (module+ test (define example-input (ascii-list "dabAcCaCBAcCcaDA")) (check-equal? (length (boil example-input)) 10) (check-equal? (day05-part1) 10584)) ; Correct answer for part one ;; Given a list and the ASCII value of an uppercase letter, first removes ;; all occurrences of that letter (both upper- and lower-case) then ;; boils the resulting list as above. (define (remove-and-boil lst uc-asciival) (define (keeper? a) (not (member a (list uc-asciival (+ 32 uc-asciival))))) (boil (filter keeper? lst))) ;; For each letter of the alphabet, create a copy of input that first removes that ;; letter, then boils the list. Find the shortest such list. ;; Computes in about 550msec (define (day05-part2) (define uc-letters (range 65 91)) (define boiler (curry remove-and-boil input)) (define boiled (map boiler uc-letters)) (apply min (report (map length boiled)))) (module+ test (check-equal? (day05-part2) 6968)) ;; This next has nothing to do with the solution; I was just curious which is the most ;; common letter in the original input, and if it was the removal of that letter ;; which yields the shortest boiled list. As it turns out: no. (define (most-frequent-letter) (define (count-letter lst a) (count (lambda(c) (member c (list a (+ a 32)))) lst)) (define letter-counts (map (curry count-letter input) (range 65 91))) (integer->char (+ 65 (index-of (report letter-counts) (apply max letter-counts))))) |