aboutsummaryrefslogtreecommitdiff
path: root/racket/aoc2021/day-16/day-16.rkt
diff options
context:
space:
mode:
Diffstat (limited to 'racket/aoc2021/day-16/day-16.rkt')
-rw-r--r--racket/aoc2021/day-16/day-16.rkt97
1 files changed, 97 insertions, 0 deletions
diff --git a/racket/aoc2021/day-16/day-16.rkt b/racket/aoc2021/day-16/day-16.rkt
new file mode 100644
index 0000000..86083ef
--- /dev/null
+++ b/racket/aoc2021/day-16/day-16.rkt
@@ -0,0 +1,97 @@
+#lang racket
+(require "../../jj-aoc.rkt"
+ bitsyntax
+ threading)
+
+(struct packet (version type type-id contents len) #:transparent)
+
+(define (BITS->bitstring str)
+ (integer->bit-string (string->number str 16) (* 4 (string-length str)) #true))
+
+(define data (~> (open-day 16 2021) port->string string-trim BITS->bitstring))
+
+(define (get-literal-contents bitstr)
+ (for/fold ([assembled (bit-string)]
+ [remaining bitstr]
+ [total-length 6]
+ [complete? #f]
+ #:result (values (bit-string->integer assembled #t #f) remaining total-length))
+ ([_ (in-naturals)] #:break complete?)
+ (bit-string-case remaining
+ ([(= 1 :: bits 1) (number :: bits 4) (remaining :: binary)]
+ (values (bit-string-append assembled (integer->bit-string number 4 #t))
+ remaining
+ (+ total-length 5)
+ #f))
+ ([(= 0 :: bits 1) (number :: bits 4) (remaining :: binary)]
+ (values (bit-string-append assembled (integer->bit-string number 4 #t))
+ remaining
+ (+ total-length 5)
+ #t)))))
+
+(define (get-type-0-contents cnt bitstr [acc '()] [len 0])
+ (cond
+ [(<= cnt 0) (values (reverse acc) bitstr len)]
+ [else
+ (define-values (packet remaining) (identify-next-packet bitstr))
+ (get-type-0-contents (- cnt (packet-len packet))
+ remaining
+ (cons packet acc)
+ (+ len (packet-len packet)))]))
+
+(define (get-type-1-contents cnt bitstr [acc '()] [len 0])
+ (cond
+ [(= cnt 0) (values (reverse acc) bitstr len)]
+ [else
+ (define-values (packet remaining) (identify-next-packet bitstr))
+ (get-type-1-contents (sub1 cnt) remaining (cons packet acc) (+ len (packet-len packet)))]))
+
+(define (identify-next-packet bitstr)
+ (bit-string-case
+ bitstr
+ ([(packet-version :: bits 3) (= 4 :: bits 3) (remaining :: binary)]
+ (define-values (n now-remaining len) (get-literal-contents remaining))
+ (values (packet packet-version 'literal 4 n len) now-remaining))
+ ([(packet-version :: bits 3)
+ (type-id :: bits 3)
+ (= 0 :: bits 1)
+ (subpacket-length :: bits 15)
+ (remaining :: binary)]
+ (define-values (contents now-remaining sublength)
+ (get-type-0-contents subpacket-length remaining))
+ (values (packet packet-version 'operator type-id contents (+ 22 sublength)) now-remaining))
+ ([(packet-version :: bits 3)
+ (type-id :: bits 3)
+ (= 1 :: bits 1)
+ (subpacket-count :: bits 11)
+ (remaining :: binary)]
+ (define-values (contents now-remaining sublength) (get-type-1-contents subpacket-count remaining))
+ (values (packet packet-version 'operator type-id contents (+ 22 sublength)) now-remaining))))
+
+(match-define-values (outer-packet n) (identify-next-packet data))
+
+;; part 1
+(define (packet-sum-version p)
+ (match p
+ [(packet v 'literal _type-id _contents _len) v]
+ [(packet v 'operator _type-id ps _len) (foldl (λ (p acc) (+ acc (packet-sum-version p))) v ps)]))
+
+(packet-sum-version outer-packet)
+
+;; part 2
+(define packet-f
+ (match-lambda
+ [0 +]
+ [1 *]
+ [2 min]
+ [3 max]
+ [5 (λ (a b) (if (> a b) 1 0))]
+ [6 (λ (a b) (if (< a b) 1 0))]
+ [7 (λ (a b) (if (= a b) 1 0))]))
+
+(define packet-eval
+ (match-lambda
+ [(packet _v 'literal _type-id n _len) n]
+ [(packet _v 'operator type-id ps _len) (~>> ps (map packet-eval) (apply (packet-f type-id)))]))
+
+(packet-eval outer-packet)