Marco Servetto

Posted on

# Advent of code 4; I never liked Bingo...

Here we are again,
I'm starting to get tired of this advent of code, I'm solving them, and 42 is not failing under me, but I'm not that motivated to write nice 42ish code.
Here the difficulty was that more then one can win at the same round, it was not very clear from the text. This also makes the order of the bingos as provided in the file very relevant...
The code below is interesting for someone learning 42 since it uses matrixes and lists of mutable elements.
Note the funky `\#add(right=_)`

``````Numbers = { class method mut I.List(S that)={
for s in that.split(S.nl()) (
return \()(for si in s.split(S",") \add(I(string=si)))
)
error X"unreachable: input has at least one nl"
}}
Boards = {
class method mut Board.List(S that) = \()(
for i in Range.endless(), b in that.split(S.nl()++S.nl()) (
//two new lines between each board
)
)
class method mut Board(S board) = (
s = board.replace(S.nl() with=S" ").replace(S"  " with=S" ")
Board(\()(for si in s.split(S" ") \add(I(string=si))))
//the board matrix factory takes an I.List
)
}
Bingo = Data:{
mut I.List ns
mut Board.List bs
mut method Void round()=(
n = \ns.left()
this.#ns().removeLeft()
for mut b in this.#bs() This.round(b=b, n=n)
)
class method Void round(mut Board b, I n)=(
for var ni in b.#vals() if ni==n ni:=I"-1"
)
for i in Range(this.bs().size()), read bi in \bs (
if This.win(b=bi) return i
)
return I"-1"
}
class method Bool win(read Board b) = {
for i in Range(5I) (
allRow = Match.All()(for j in Range(5I) \add(b.val(row=i,col=j)==I"-1"))
if allRow return \.true()
)
for j in Range(5I) (
allCol = Match.All()(for i in Range(5I) \add(b.val(row=i,col=j)==I"-1"))
if allCol return \.true()
)
return \.false()
}
class method I points(read Board b) = (
var res = 0I
for ni in b if ni!=I"-1" ( res+=ni )
res
)
}
MainPart1 = (
fs = Fs.Real.#\$of()
bingo = Bingo(ns=Numbers(input), bs=Boards(input))
while Bool.true() (
current = bingo.ns().left()
bingo.round()
res = bingo.winner()
if res!=I"-1" (
Debug(points*current)
Break()
)
)
)
MainPart2 = (
fs = Fs.Real.#\$of()
bingo = Bingo(ns=Numbers(input), bs=Boards(input))
while Bool.true() (
current = bingo.ns().left()
bingo.round()
while Bool.true() (//more then one can win in a single round
res = bingo.winner()
if res==I"-1" ( Break() )