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)

We are hiring! Do you want to be our Senior Platform Engineer? Forem is hiring a Senior Platform Engineer

If you're interested in ops and site reliability and capable of dipping in to our Linux stack, we'd love your help shoring up our systems!