Mine is recursive: parse calls operator, and operator calls parse. That's why I added a trace mechanism (an echo statement showing the string I used to represent what would happen to the value, along with the value itself, for each packet) -- so that I could visualize what was happening.
By the way, re-reading this, I see that my naming convention might have been confusing -- 'operator' was a dyadic verb. I passed in a string showing the operation which would be applied to the result. Also, I could have instead used 128!:2 to implement the operation itself. So I should also have added a "this could have been done better" disclaimer. Thanks, -- Raul On Thu, Jan 6, 2022 at 5:08 AM 'Mike Day' via Programming <[email protected]> wrote: > > I’d forgotten that this day was also pretty hard. My “unpack” function > (snap!) also delivered the goods for both parts. It works through the > message calling either “literal” or “operator”. literal is self-contained, > returning a value and an unused message fragment, while operator calls > unpack in a mode depending on the length-type id. > > So it’s recursive, and I found it very tricky to see what was happening! But > it worked, eventually. Far too ugly to share here. > > It looks at first glance as if you translated the whole message into a J-type > string. Non-recursive, anyway, unless I’ve overlooked something. > > Cheers, > > Mike > > > Sent from my iPad > > > On 6 Jan 2022, at 01:50, Raul Miller <[email protected]> wrote: > > > > 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 > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
