This content originally appeared on DEV Community and was authored by Marco Servetto
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 [L42.is/AdamsTowel]
Fs = Load:{reuse[L42.is/FileSystem]}
Decoder = {
Map = Collection.map(key=S val=I.List)
class method I.List(S that) = This.map().val(key=that).val()
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() = (
\removed(\removed+1I)
(left,removeLeft)=\#that
left
)
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))
))
X[that.that().size()>=psSize]
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(Versions(ps.left()))//993
Debug(Part2(ps.left())) //144595909277
)
Note this funky code :-P
(left,removeLeft) = \#that
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
Here I extract 5 bits from the input. This is nice and readable, and uses the same pattern of the 'removeLeft' above.
This content originally appeared on DEV Community and was authored by Marco Servetto

Marco Servetto | Sciencx (2021-12-17T02:58:18+00:00) Advent of code day 16. Retrieved from https://www.scien.cx/2021/12/17/advent-of-code-day-16/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.