DEV Community

Marco Servetto
Marco Servetto

Posted on

Advent of code day 16

Ok, here it is.
I hate this even more than the Bingo. In particular, the text was very unclear about padding. Padding can basically be ignored in this exercise.

reuse []
Fs = Load:{reuse[]}

Decoder = {
  Map = val=I.List)

  class method I.List(S that) =

  L={class method I.List (S that)=\()(
    for c in that.split() \add(I(string=c)))}

  @Cache.Lazy class method Map map()=\[
    key=S"0" val=L(S"0000");
    key=S"1" val=L(S"0001");
    key=S"2" val=L(S"0010");
    key=S"3" val=L(S"0011");
    key=S"4" val=L(S"0100");
    key=S"5" val=L(S"0101");
    key=S"6" val=L(S"0110");
    key=S"7" val=L(S"0111");
    key=S"8" val=L(S"1000");
    key=S"9" val=L(S"1001");
    key=S"A" val=L(S"1010");
    key=S"B" val=L(S"1011");
    key=S"C" val=L(S"1100");
    key=S"D" val=L(S"1101");
    key=S"E" val=L(S"1110");
    key=S"F" val=L(S"1111");

Input = Data:{
  mut I.List that
  var I removed = 0I
  mut method I b() = (
  read method Bool isPadding() = 
    \that.size()<4I ||
    \that.val(0I)+\that.val(1I)+\that.val(2I) ==0I
Packet = Data.AddList:Data:{ List = {}
  I v,I t,Num val,List sub
ParsePacket = {
  class method Packet (mut Input that) = {
    v   = \val(that,bits=3I)
    t   = \val(that,bits=3I)
    if t==4I return \(v=v,t=t,val=this.vals(that),sub=\())
    size = ( if that.b()==0I 15I else 11I )
    psSize = \val(that,bits=size)
    (removed) = that
    if size==11I return \(v=v,t=t,val=Num(psSize),sub=\()(
      for i in Range(psSize) \add(ParsePacket(that))
    return \(v=v,t=t,val=Num(psSize),sub=\()(
      while that.removed()-removed<psSize \add(ParsePacket(that))
  class method I val(mut Input that, I bits) = 0I.acc()(
    for i in Range(bits) \val((\val*2I)+that.b()) 
  class method Num vals(mut Input that) = {
    (b0,b1,b2,b3,b4)= that
    res = Num((b1*8I)+(b2*4I)+(b3*2I)+b4)
    if b0==0I return res
    pre = that.removed()
    rec = \vals(that)
    var seen = that.removed() - pre
    mul = 1Num.acc()(while seen>3I (seen-=5I, \times(16Num)))
    return (res*mul)+rec
Versions={class method I (Packet that) = 
  that.v().acc()(for p in that.sub() \add(This(p)))
Part2 = {class method Num (Packet that) = {
  if that.t()==0I return 0Num.acc()(for p in that.sub() \add(This(p)))
  if that.t()==1I return 1Num.acc()(for p in that.sub() \times(This(p)))
  if that.t()==2I return This(that.sub().left()).acc()(for p in that.sub() \val(\val.min(This(p))))
  if that.t()==3I return 0Num.acc()(for p in that.sub() \val(\val.max(This(p))))
  if that.t()==4I return that.val()
  (left,right) = that.sub()
  if that.t()==5I return if This(left)>This(right) 1Num else 0Num
  if that.t()==6I return if This(left)<This(right) 1Num else 0Num
  if that.t()==7I return if This(left)==This(right) 1Num else 0Num
  error X" unrecognized packet type"
Main = (
  input = Fs.Real.#$of().read(\"input").trim()
  parsed = Input(\()(for c in input.split() for e in Decoder(c) \add(e)))
  ps = Packet.List()(while !parsed.isPadding() \add(ParsePacket(parsed)))
  Debug(Part2(ps.left())) //144595909277
Enter fullscreen mode Exit fullscreen mode

Note this funky code :-P

(left,removeLeft) = \#that
Enter fullscreen mode Exit fullscreen mode

I'm not sure what to think about it. It is a cool way to go next after reading left, but it also feel like an abuse of the 'object decomposition' syntax.. any idea about it?
The more I use that pattern the more it feels ok... but I'm I just getting use to the anti-pattern, or is it actually a good way to express stuff?

Consider this other use of the same idea:

(b0,b1,b2,b3,b4) = that
Enter fullscreen mode Exit fullscreen mode

Here I extract 5 bits from the input. This is nice and readable, and uses the same pattern of the 'removeLeft' above.

Top comments (0)