From b8afb81c16748e6b58e67c545b143335473d5198 Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Wed, 15 Dec 2021 23:37:10 -0800 Subject: [PATCH] Day 16. --- input/16.txt | 1 + lib.rkt | 4 +++ src/16.rkt | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 input/16.txt create mode 100644 src/16.rkt diff --git a/input/16.txt b/input/16.txt new file mode 100644 index 0000000..439607a --- /dev/null +++ b/input/16.txt @@ -0,0 +1 @@ +220D700071F39F9C6BC92D4A6713C737B3E98783004AC0169B4B99F93CFC31AC4D8A4BB89E9D654D216B80131DC0050B20043E27C1F83240086C468A311CC0188DB0BA12B00719221D3F7AF776DC5DE635094A7D2370082795A52911791ECB7EDA9CFD634BDED14030047C01498EE203931BF7256189A593005E116802D34673999A3A805126EB2B5BEEBB823CB561E9F2165492CE00E6918C011926CA005465B0BB2D85D700B675DA72DD7E9DBE377D62B27698F0D4BAD100735276B4B93C0FF002FF359F3BCFF0DC802ACC002CE3546B92FCB7590C380210523E180233FD21D0040001098ED076108002110960D45F988EB14D9D9802F232A32E802F2FDBEBA7D3B3B7FB06320132B0037700043224C5D8F2000844558C704A6FEAA800D2CFE27B921CA872003A90C6214D62DA8AA9009CF600B8803B10E144741006A1C47F85D29DCF7C9C40132680213037284B3D488640A1008A314BC3D86D9AB6492637D331003E79300012F9BDE8560F1009B32B09EC7FC0151006A0EC6082A0008744287511CC0269810987789132AC600BD802C00087C1D88D05C001088BF1BE284D298005FB1366B353798689D8A84D5194C017D005647181A931895D588E7736C6A5008200F0B802909F97B35897CFCBD9AC4A26DD880259A0037E49861F4E4349A6005CFAD180333E95281338A930EA400824981CC8A2804523AA6F5B3691CF5425B05B3D9AF8DD400F9EDA1100789800D2CBD30E32F4C3ACF52F9FF64326009D802733197392438BF22C52D5AD2D8524034E800C8B202F604008602A6CC00940256C008A9601FF8400D100240062F50038400970034003CE600C70C00F600760C00B98C563FB37CE4BD1BFA769839802F400F8C9CA79429B96E0A93FAE4A5F32201428401A8F508A1B0002131723B43400043618C2089E40143CBA748B3CE01C893C8904F4E1B2D300527AB63DA0091253929E42A53929E420 diff --git a/lib.rkt b/lib.rkt index 935059e..3e825de 100644 --- a/lib.rkt +++ b/lib.rkt @@ -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)) diff --git a/src/16.rkt b/src/16.rkt new file mode 100644 index 0000000..4633926 --- /dev/null +++ b/src/16.rkt @@ -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))) \ No newline at end of file