Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Created January 8, 2022 05:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sungkmi/c532b0725b1a47677364a285527c7b47 to your computer and use it in GitHub Desktop.
Save sungkmi/c532b0725b1a47677364a285527c7b47 to your computer and use it in GitHub Desktop.
package lascala.aoc2021.day1_10.day4
case class Bingo(
board: BingoBoard,
marked: Marked,
)
extension (b: Bingo)
def checkBingo(n: Int): Option[Bingo] = b.board.indexOf(n) match
case None => Some(b)
case Some((r, c)) =>
def checkRow: Boolean = (0 until 5).forall { i =>
i == c || b.marked.isSet(r, i)
}
def checkColumn: Boolean = (0 until 5).forall { i =>
i == r || b.marked.isSet(i, c)
}
if checkRow || checkColumn then None
else Some(b.copy(marked = b.marked.set(r, c)))
end checkBingo
def sum: Int =
val unmarked = for
(number, (r, c)) <- b.board.toMap
if !b.marked.isSet(r, c)
yield number
unmarked.sum
end sum
opaque type BingoBoard = Map[Int, (Int, Int)]
extension (bb: BingoBoard)
def toMap: Map[Int, (Int, Int)] = bb
def indexOf(n: Int): Option[(Int, Int)] = bb.get(n)
end extension
object BingoBoard:
def parse(s: String): BingoBoard =
def parseLine(line: String): Seq[Int] =
line.sliding(3, 3).map(_.trim.toInt).toSeq
val rc = for
(line, rowIndex) <- s.split("\n").zipWithIndex
(digit, colIndex) <- parseLine(line).zipWithIndex
yield (digit, (rowIndex, colIndex))
rc.toMap
end parse
end BingoBoard
opaque type Row = BigInt
extension (r: Row)
def isSet(n: Int): Boolean = r.testBit(n)
def set(n: Int): Row = r.setBit(n)
object Row:
def empty: Row = BigInt(0)
opaque type Marked = IndexedSeq[Row]
extension (m: Marked)
def isSet(r: Int, c: Int): Boolean = m(r).isSet(c)
def set(r: Int, c: Int): Marked = m.updated(r, m(r).set(c))
object Marked:
def empty: Marked = IndexedSeq.fill(5)(Row.empty)
def parse(s: String): (Seq[Int], Seq[Bingo]) =
val inputs = s.split("\n\n")
val numbers = inputs.head.split(",").map(_.toInt)
val bingos = inputs.tail.map(BingoBoard.parse).map(Bingo(_, Marked.empty))
(numbers, bingos)
def solve1(s: String): BigInt =
val (numbers, bingos) = parse(s)
@annotation.tailrec
def loop(numbers: Seq[Int], bingos: Seq[Bingo], acc: Int): BigInt =
val number = numbers.head
val nextBingos = bingos.map(_.checkBingo(number))
if nextBingos.forall(_.nonEmpty) then
loop(numbers.tail, nextBingos.flatten, acc + number)
else
val Some(i) = nextBingos.zipWithIndex.find(_._1.isEmpty).map(_._2)
(bingos(i).sum - number) * number
end loop
loop(numbers, bingos, 0)
end solve1
def solve2(s: String): BigInt =
val (numbers, bingos) = parse(s)
@annotation.tailrec
def loop(numbers: Seq[Int], bingos: Seq[Bingo], acc: Int): BigInt =
val number = numbers.head
val nextBingos = bingos.map(_.checkBingo(number))
if nextBingos.forall(_.isEmpty) then (bingos.head.sum - number) * number
else loop(numbers.tail, nextBingos.flatten, acc + number)
end loop
loop(numbers, bingos, 0)
end solve2
@main def part1: Unit =
val ans = solve1(input)
println(ans)
@main def part2: Unit =
val ans = solve2(input)
println(ans)
//val input =
package lascala.aoc2021.day1_10.day4
import minitest.SimpleTestSuite
import hedgehog.minitest.HedgehogSupport
import hedgehog.*
object Day4Test extends SimpleTestSuite with HedgehogSupport:
val testInput = """7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7"""
example("day4 - bingo board") {
val boardString = """22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19"""
val board = BingoBoard.parse(boardString)
Result.all(
List(
board.indexOf(0) ==== Some((0, 4)),
board.indexOf(1) ==== Some((4, 0)),
board.indexOf(2) ==== Some((1, 1)),
),
)
}
example("day4 - solve1") {
solve1(testInput) ==== 4512
}
example("day4 - solve2") {
solve2(testInput) ==== 1924
}
end Day4Test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment