Day 4
This commit is contained in:
parent
1747cd8c93
commit
0f233d908d
2 changed files with 675 additions and 0 deletions
74
aoc/src/Day4.scala
Normal file
74
aoc/src/Day4.scala
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import scala.io.Source
|
||||
|
||||
object Day4 extends App:
|
||||
|
||||
val input = Source
|
||||
.fromURL(getClass.getResource("day4Input.txt"))
|
||||
.mkString
|
||||
|
||||
final case class Bingo(boards: Array[Board], playedNumbers: Seq[Int]):
|
||||
def playNumber(number: Int) =
|
||||
Bingo(
|
||||
boards.map(board => if (board.isWinner) board else board.mark(number)),
|
||||
playedNumbers.appended(number)
|
||||
)
|
||||
|
||||
def winningBoards: Seq[Board] = boards
|
||||
.filter(_.isWinner)
|
||||
.map(board => (board, board.lastMarked.map(playedNumbers.indexOf(_))))
|
||||
.sortBy(_._2)
|
||||
.map(_._1)
|
||||
|
||||
val gameOver = boards.forall(_.isWinner)
|
||||
|
||||
object Bingo:
|
||||
def parse(input: Array[String]): Bingo =
|
||||
Bingo(input.map(Board.parse), Seq())
|
||||
|
||||
final case class Board(
|
||||
val rows: Array[Array[Cell]],
|
||||
lastMarked: Option[Int] = None
|
||||
):
|
||||
val isWinner: Boolean = rows.exists(_.forall(_.marked)) ||
|
||||
rows.transpose.exists(_.forall(_.marked))
|
||||
|
||||
def mark(number: Int): Board =
|
||||
Board(
|
||||
rows.map(_.map(_.mark(number))),
|
||||
Some(number)
|
||||
)
|
||||
|
||||
def score: Int =
|
||||
rows.flatMap(_.filterNot(_.marked).map(_.value)).sum *
|
||||
lastMarked.getOrElse(0)
|
||||
|
||||
object Board:
|
||||
def parse(input: String) =
|
||||
Board(
|
||||
input
|
||||
.split('\n')
|
||||
.map(
|
||||
_.split(' ')
|
||||
.filter(_.nonEmpty)
|
||||
.map(Cell.parse)
|
||||
)
|
||||
)
|
||||
|
||||
final case class Cell(value: Int, marked: Boolean = false):
|
||||
def mark(number: Int): Cell =
|
||||
if (number == value) Cell(value, true) else this
|
||||
|
||||
object Cell:
|
||||
def parse(input: String) = Cell(input.toInt)
|
||||
|
||||
val numbersAndBoardsInput = input.split("\n\n")
|
||||
val drawnNumbers = numbersAndBoardsInput.head.split(',').map(_.toInt)
|
||||
val initialState = Bingo.parse(numbersAndBoardsInput.tail)
|
||||
|
||||
val finalState = drawnNumbers.foldLeft(initialState)(_.playNumber(_))
|
||||
|
||||
val firstWinningBoard = finalState.winningBoards.head
|
||||
println(s"Part 1: ${firstWinningBoard.score}")
|
||||
|
||||
val lastWinningBoard = finalState.winningBoards.last
|
||||
println(s"Part 2: ${lastWinningBoard.score}")
|
||||
Loading…
Add table
Add a link
Reference in a new issue