Move scala codebase in a directory on its own

This commit is contained in:
Xavier Morel
2020-12-03 10:23:51 +01:00
parent a04451f2f7
commit 7dc5d839af
36 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
import scala.io.StdIn.readLine
def readInput: Option[(Int, Int, Int)] = "(\\d+) players; last marble is worth (\\d+) points".r.findFirstMatchIn(readLine).map(m => (m.group(1).toInt, m.group(2).toInt, 0))
val (players, lastMarble, expected) = readInput.get
// val (players, lastMarble, expected) = (9, 25, 32)
// val (players, lastMarble, expected) = (10, 1618, 8317)
case class Turn(currentPlayer: Int, currentMarble: Int, marbles: List[Int], scores: List[Int]) {
override def toString: String = s"[$currentPlayer] " + marbles.zipWithIndex.map { case (m, i) => if (i == currentMarble) { s"($m)" } else { s" $m " } }.mkString(" ")
def nextPlayer: Int = (currentPlayer % scores.length) + 1
}
def playGame(turn: Turn, marbleValue: Int): Turn =
marbleValue match {
case m if m % 23 == 0 =>
val removedMarbleIndex = (turn.currentMarble - 7 + turn.marbles.length) % turn.marbles.length
val removedMarbleScore = turn.marbles(removedMarbleIndex)
val newScore = List(m + removedMarbleScore + turn.scores(turn.currentPlayer - 1))
val newMarbles = turn.marbles.zipWithIndex.filterNot { case (v, k) => k == removedMarbleIndex } .map(_._1)
Turn(turn.nextPlayer, (removedMarbleIndex % turn.marbles.length), newMarbles, turn.scores.patch(turn.currentPlayer -1, newScore, 1))
case 1 => Turn(turn.nextPlayer, 1, List(0, 1), turn.scores)
case m =>
val insertIndex = {
(turn.currentMarble + 2) % turn.marbles.length match {
case c if c == 0 && turn.marbles.length % 2 == 1 => turn.marbles.length
case c => c
}
}
val marbles = turn.marbles.patch(insertIndex, List(m), 0)
Turn(turn.nextPlayer, insertIndex, marbles, turn.scores)
}
val turn0 = Turn(0, 0, List(0), List.fill(players)(0))
// Print board on each turn :
// (1 to lastMarble).scanLeft(turn0)(playGame).foreach(println)
val lastTurn = (1 to lastMarble).foldLeft(turn0)(playGame)
// Players scores :
// lastTurn.scores.zipWithIndex.foreach { case (v, k) => println(s"Player ${k + 1}: $v") }
println("Computed best score: " + lastTurn.scores.max)
if (expected > 0) {
println(s"Expected: $expected")
}

View File

@@ -0,0 +1,60 @@
import java.time.LocalTime
import scala.io.StdIn.readLine
import scala.collection.mutable.ArrayBuffer
def readInput: Option[(Int, Int, Int)] = "(\\d+) players; last marble is worth (\\d+) points".r.findFirstMatchIn(readLine).map(m => (m.group(1).toInt, m.group(2).toInt, 0))
val (players, lastMarbleOriginal, expected) = readInput.get
// val (players, lastMarbleOriginal, expected) = (9, 25, 32)
// val (players, lastMarbleOriginal, expected) = (10, 1618, 8317)
val lastMarble = lastMarbleOriginal * 100
case class Turn(currentPlayer: Int, marbles: Vector[Int], scores: Array[Long]) {
override def toString: String = s"[${currentPlayer + 1}] " + marbles.mkString(" ")
lazy val nextPlayer: Int = (currentPlayer + 1) % scores.length
def winTurn(marble: Int): Turn = {
val t: Vector[Int] = marbles.take(8)
val newMarbles: Vector[Int] = t.slice(6,7) ++ marbles.drop(8) ++ t.take(6)
val addScore: Long = marble + t.last
Turn(nextPlayer, newMarbles, updateScore(addScore))
}
def classicTurn(marble: Int): Turn =
Turn(nextPlayer, addMarble(marble), scores)
def updateScore(newScore: Long): Array[Long] = {
val newScores: ArrayBuffer[Long] = ArrayBuffer.concat(scores)
newScores(nextPlayer) += newScore
newScores.toArray
}
def addMarble(m: Int): Vector[Int] = {
val h = marbles.last
Vector(m, h) ++ marbles.dropRight(1)
}
}
def playGame(turn: Turn, marbleValue: Int): Turn = {
// Add a bit of visilibity...
marbleValue match {
case m if m % 23 == 0 => turn.winTurn(m)
case m => turn.classicTurn(m)
}
}
val turn0 = Turn(-1, Vector(0), Array.fill(players)(0))
// Print board on each turn :
// (1 to lastMarble).scanLeft(turn0)(playGame).foreach(println)
val last = (1 to lastMarble).foldLeft((0L, turn0)) {
case ((max, t), m) =>
val newT = playGame(t, m)
val maxScore = newT.scores.max
(maxScore, newT)
}
println(s"Expected: ${expected}")
println(s"Result: ${last._1}")