https://adventofcode.com/2021/day/16

Here, we were decoding messages encoded using the AoC "BITS" protocol.

A significant part of the puzzle was about comprehending the somewhat
shiftless protocol specification included in the puzzle.

The approach I found useful was to set up a "test bench" with the
puzzle examples, and have a 'trace' feature enabled so that I could
see all intermediate results when parsing those examples. (I turned
this off for the large puzzle value, because that was considerably
bulkier.)

For part A, it looked like this:

trace=: 1
assert 16= a15 '8A004A801A8002F478'
assert 12= a15 '620080001611562C8802118E34'
assert 23= a15 'C0015000016115A2E0802F182340'
assert 31= a15 'A0016C880162017C3686B18A3D4780'

With that in place, I could relatively quickly compare notes about
examples in the puzzle with what my own code was doing. That said, for
part A we only had to have part of the protocol implemented.

The protocol itself was something of a virtual machine implementation.
And, at this point, having solved part B, my part A solution includes
that virtual machine implementation which was not strictly necessary
for part A.

Anyways... here is what my code which handles part A looks like.
There's some initial waffling about where I attempt to conceptualize
some of the different abstractions the protocol spec uses when talking
about the data. And then I wound up encoding part A specific
mechanisms into my 'unpack' routine. And, the code itself consists of
a 'parse' routine implementing a "core" of the protocol and an
'operator' routine implementing a 'core' of the associated virtual
machine.

require'convert'
hex=: ,toupper hfd i.16

BITS=:{{
  ,2 2 2 2 #: hex i.y -.LF
}}

bits=: {{
  r=. packet{~pos+i.y
  pos=: pos+y
  r
}}

unpack=: {{
  pos=: 0
  packet=: BITS y
  vsum=: 0
  parse ''
}}

operator=: {{
  lentype=. bits 1
  payload=. i.0
  if. lentype do.
    sublen=. #. bits 11
    for. i.sublen do.
      payload=. payload,parse''
    end.
  else.
    bitlen=. #. bits 15
    limit=. pos+bitlen
    while. pos < limit-6 do.
      payload=. payload,parse''
    end.
    assert. pos <: limit
  end.
  if. trace do. echo x,":payload end.
  payload
}}

parse=: {{
   vsum=:vsum+V=. #. bits 3
   ID=. #. bits 3
   payload=. i.0
   select. ID
     case. 0 do. payload=. +/ '+/'operator''
     case. 1 do. payload=. */ '*/'operator''
     case. 2 do. payload=. <./ '<./'operator''
     case. 3 do. payload=. >./ '>./'operator''
     case. 4 do.
       value=. i.0
       while. {. group=. bits 5 do.
         value=. value,}.group
       end.
       payload=. #.x:value,}.group
     case. 5 do. payload=. >/0 0+'>/' operator''
     case. 6 do. payload=. </0 0+'</' operator''
     case. 7 do. payload=. =/0 0+'=/' operator''
   end.
   payload
}}

a15=:{{
  unpack y
  vsum
}}

My part B implementation looks like this:

b15=: unpack

assert  3= b15 'C200B40A82'
assert 54= b15 '04005AC33890'
assert  7= b15 '880086C3E88112'
assert  9= b15 'CE00C43D881120'
assert  1= b15 'D8005AC2A8F0'
assert  0= b15 'F600BC2D8F'
assert  0= b15 '9C005AC2F8F0'
assert  1= b15 '9C0141080250320F1802104A08'

Running this against the puzzle input with trace=: 1 is kind of
amusing, but trace=:0 avoids quite a lot of 'trace spam'.

FYI,

-- 
Raul
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to