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