aboutsummaryrefslogtreecommitdiff
path: root/2021/day-16/day-16.rkt
blob: c860e27b0371d5e192f8b977c733d9c02cdbc9fc (plain)
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
#lang racket
(require "../../jj-aoc.rkt"
         bitsyntax
         threading)

(struct packet (version id type value size)
  #: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 (overflow l w)
  (define extra (modulo l 4))
  (if (= extra 0) 0 (- w extra)))

(define (get-literal-contents bitstr)
  (for/fold ([assembled (bit-string)]
             [remaining bitstr]
             [total-length 6]
             [complete? #f]
             #:result (list (bit-string->integer assembled #t #f)
                            total-length
                            remaining))
            ([_ (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)
                       (ignored :: bits (overflow (+ total-length 5) 4))
                       (remaining :: binary)]
                      (values (bit-string-append assembled (integer->bit-string number 4 #t))
                              remaining
                              (+ total-length 5)
                              #t)))))

(define (identify-next-packet bitstr)
  (bit-string-case bitstr
                   ([(packet-version :: bits 3)
                     (= 4 :: bits 3)
                     (remaining :: binary)]
                    (match-define (list n packet-length next-bitstr) (get-literal-contents remaining))
                    (list (packet packet-version
                                  4
                                  'literal
                                  n
                                  packet-length)
                          next-bitstr))
                   ([(packet-version :: bits 3)
                     (type-id :: bits 3)
                     (= 0 :: bits 1)
                     (subpacket-length :: bits 15)
                     (remaining :: binary)]
                    (list (packet packet-version type-id 'type-0-operator 0 0) remaining))
                   ([(packet-version :: bits 3)
                     (type-id :: bits 3)
                     (= 1 :: bits 1)
                     (subpacket-count :: bits 11)
                     (remaining :: binary)]
                    (list (packet packet-version type-id 'type-1-operator 0 0) remaining))))

(identify-next-packet (BITS->bitstring "D2FE28"))