Hi Everyone! here I show you my solution for Day 10.
It was fun and it allowed me to show an interesting programming pattern, that I do not see around very commonly: We can have a list of possible cases so that we can grow our set of available parenthesis.
In particular, in 42 we can hard code the list and then use metaprogramming at a later stage to update the list with more cases. That is, while executing a specific version of the code we can be certain of the behavior, but when we can sill extend the code behavior on need.
You can also see a video comment on this code here
(https://www.youtube.com/watch?v=F7SZrh4HxsU)
reuse [L42.is/AdamsTowel]
Fs = Load:{reuse [L42.is/FileSystem]}
Split={class method S.List (S that)=\()(
for c in that.replace(S"" with=S",").split(S",")\add(c)
)}
PopMax ={class method Num (mut Num.List that)=(
var i = 0I, var e = 0Num
for ei in that, ii in Range(that.size()) if ei>e ( e:=ei, i:=ii )
that.remove(i)
e
)}
Sort ={class method Num.List (mut Num.List that)=\()(
while !that.isEmpty() \add(PopMax(that))
)}
Par=Organize:{
$ = {interface [HasToS]
class method S open()
class method S close()
method Num points1()
method Num points2()
class method Bool fitsO(S that)
class method Bool fitsC(S that)
method $ next()
method $ push(S that)[$]
class method This ($ that)
}
Round$={[$]}, Square$={[$]}, Curly$={[$]}, Angle$={[$]}
ParB=Data.AddList:Data:{class $ par}
Pars={@Cache.Lazy class method ParB.List() =
\[\(par=Round$);\(par=Square$);\(par=Curly$);\(par=Angle$);]}
ParTrait = Trait:{[$]
method fitsO(that)=that==\open
method fitsC(that)=that==\close
class method This($ next)
method (that)=This(next=that)
method push(that)={
if This.fitsC(that) return \next
for (par) in Pars() (if par.fitsO(that) return par(this))
for (par) in Pars() (if par.fitsC(that) exception par(this))
error X"Unexpected %that"
}
}
Round = Class:Data:ParTrait:{[$]
method open()=S"(",,,method close()=S")"
method points1()=3\,,,method points2()=1\ }
Square = Class:Data:ParTrait:{[$]
method open()=S"[",,,method close()=S"]"
method points1()=57\,,,method points2()=2\ }
Curly = Class:Data:ParTrait:{[$]
method open()=S"{",,,method close()=S"}"
method points1()=1197\,,,method points2()=3\ }
Angle = Class:Data:ParTrait:{[$]
method open()=S"<",,,method close()=S">"
method points1()=25137\,,,method points2()=4\ }
End = Class:Data:ParTrait:{[$]
method open()=S"@",,,method close()=S"@"
method points1()=0\,,,method points2()=0\
class method This($ next)=This()
method next()=this
}
}
Main = (
var points1 = 0Num
ps = Num.List()
for line in Fs.Real.#$of().read(\"input").split(S.nl()) (
var points2 = 0Num
var Par par = Par.End()
for c in Split(line) ( par:= par.push(c) )
catch Par p ( points1+=p.points1() )
while par.points1()!=0Num (
points2:=(points2*5Num)+par.points2()
par:=par.next()
)
ps.add(points2)
)
Debug(S"Part1 %points1")//464991
Debug(S"Part2 %Sort(ps).val(\size/2I)")//3662008566
)
What do you think about this style of coding?
Top comments (0)