This commit is contained in:
Jonathan Chan 2021-12-15 23:37:10 -08:00
parent fcb948918e
commit b8afb81c16
3 changed files with 84 additions and 0 deletions

1
input/16.txt Normal file
View File

@ -0,0 +1 @@
220D700071F39F9C6BC92D4A6713C737B3E98783004AC0169B4B99F93CFC31AC4D8A4BB89E9D654D216B80131DC0050B20043E27C1F83240086C468A311CC0188DB0BA12B00719221D3F7AF776DC5DE635094A7D2370082795A52911791ECB7EDA9CFD634BDED14030047C01498EE203931BF7256189A593005E116802D34673999A3A805126EB2B5BEEBB823CB561E9F2165492CE00E6918C011926CA005465B0BB2D85D700B675DA72DD7E9DBE377D62B27698F0D4BAD100735276B4B93C0FF002FF359F3BCFF0DC802ACC002CE3546B92FCB7590C380210523E180233FD21D0040001098ED076108002110960D45F988EB14D9D9802F232A32E802F2FDBEBA7D3B3B7FB06320132B0037700043224C5D8F2000844558C704A6FEAA800D2CFE27B921CA872003A90C6214D62DA8AA9009CF600B8803B10E144741006A1C47F85D29DCF7C9C40132680213037284B3D488640A1008A314BC3D86D9AB6492637D331003E79300012F9BDE8560F1009B32B09EC7FC0151006A0EC6082A0008744287511CC0269810987789132AC600BD802C00087C1D88D05C001088BF1BE284D298005FB1366B353798689D8A84D5194C017D005647181A931895D588E7736C6A5008200F0B802909F97B35897CFCBD9AC4A26DD880259A0037E49861F4E4349A6005CFAD180333E95281338A930EA400824981CC8A2804523AA6F5B3691CF5425B05B3D9AF8DD400F9EDA1100789800D2CBD30E32F4C3ACF52F9FF64326009D802733197392438BF22C52D5AD2D8524034E800C8B202F604008602A6CC00940256C008A9601FF8400D100240062F50038400970034003CE600C70C00F600760C00B98C563FB37CE4BD1BFA769839802F400F8C9CA79429B96E0A93FAE4A5F32201428401A8F508A1B0002131723B43400043618C2089E40143CBA748B3CE01C893C8904F4E1B2D300527AB63DA0091253929E42A53929E420

View File

@ -65,6 +65,10 @@
;; String helpers ;;
;; string-empty? : string? -> boolean?
(define (string-empty? s)
(string=? s ""))
;; string->number* : (or/c string? #f) -> (or/c number? #f)
(define string->number*
(and/c string? string->number))

79
src/16.rkt Normal file
View File

@ -0,0 +1,79 @@
#lang plai
(require "../lib.rkt")
(define-type Packet
[literal (version number?) (value number?)]
[operator (version number?) (ID number?) (subpackets (listof Packet?))])
(define (hex->bits hex)
(match hex
[#\0 "0000"] [#\1 "0001"] [#\2 "0010"] [#\3 "0011"]
[#\4 "0100"] [#\5 "0101"] [#\6 "0110"] [#\7 "0111"]
[#\8 "1000"] [#\9 "1001"] [#\A "1010"] [#\B "1011"]
[#\C "1100"] [#\D "1101"] [#\E "1110"] [#\F "1111"]))
(define input
(for/fold ([bits ""])
([hex (string->list (first (problem-input 16)))])
(string-append bits (hex->bits hex))))
(define (parse-lit version raw)
(let loop ([value ""]
[raw raw])
(if (char=? (string-ref raw 0) #\0)
(let ([value (string-append value (substring raw 1 5))])
(values (literal version (string->binary value))
(substring raw 5)))
(loop (string-append value (substring raw 1 5))
(substring raw 5)))))
(define (parse-op/length version ID raw)
(define len (string->binary (substring raw 0 15)))
(let loop ([packets '()]
[subraw (substring raw 15 (+ len 15))])
(if (string-empty? subraw)
(values (operator version ID (reverse packets))
(substring raw (+ len 15)))
(let-values ([(packet subraw) (parse-packet subraw)])
(loop (cons packet packets) subraw)))))
(define (parse-op/count version ID raw)
(define n (string->binary (substring raw 0 11)))
(for/fold ([packets '()]
[raw (substring raw 11)]
#:result (values (operator version ID (reverse packets)) raw))
([_ (range n)])
(let-values ([(packet raw) (parse-packet raw)])
(values (cons packet packets) raw))))
(define (parse-packet raw)
(define version (string->binary (substring raw 0 3)))
(match (string->binary (substring raw 3 6))
[4 (parse-lit version (substring raw 6))]
[ID
(match (string-ref raw 6)
[#\0 (parse-op/length version ID (substring raw 7))]
[#\1 (parse-op/count version ID (substring raw 7))])]))
(define (version-sum packet)
(type-case Packet packet
[literal (version _) version]
[operator (version _ packets) (+ version (sum (map version-sum packets)))]))
(define (interp-packet packet)
(type-case Packet packet
[literal (version value) value]
[operator (version ID packets)
(define values (map interp-packet packets))
(match ID
[0 (apply + values)]
[1 (apply * values)]
[2 (apply min values)]
[3 (apply max values)]
[5 (if (> (first values) (second values)) 1 0)]
[6 (if (< (first values) (second values)) 1 0)]
[7 (if (= (first values) (second values)) 1 0)])]))
(let-values ([(packet _) (parse-packet input)])
(show-solution (version-sum packet) (interp-packet packet)))