forked from matelaszlo/advent-of-code-scala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay08.scala
74 lines (60 loc) · 2.8 KB
/
Day08.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.lmat.adventofcode.year2017
import com.lmat.adventofcode.SimpleCommonPuzzle
import com.lmat.adventofcode.year2017.Day08Definitions._
import com.lmat.util.Files.readResource
import scala.collection.immutable.Map
object Day08Definitions {
case class Condition(register: String, comparison: String, amount: Int)
case class Instruction(register: String, operation: String, amount: Int, condition: Condition)
}
object Day08 extends SimpleCommonPuzzle[Seq[Instruction], Int, Int] {
override def parse(resource: String): Seq[Instruction] =
readResource(resource).map(parseInstruction)
def parseInstruction(string: String): Instruction = {
val components = string.split("\\s+")
Instruction(
components(0),
components(1),
components(2).toInt,
Condition(
components(4),
components(5),
components(6).toInt
)
)
}
case class RegisterState(state: Map[String, Int]) {
def get(register: String): Int =
state.getOrElse(register, 0)
def inc(register: String, amount:Int) =
RegisterState(state.updated(register, get(register) + amount))
def dec(register: String, amount:Int) =
RegisterState(state.updated(register, get(register) - amount))
def maxValue: Int =
if (state.isEmpty) 0
else state.values.max
}
object RegisterState {
val empty = RegisterState(Map(): Map[String, Int])
}
override def part1(instructions: Seq[Instruction]): Int =
instructions.foldLeft(RegisterState.empty)((state, instruction) => applyInstruction(state, instruction))
.maxValue
override def part2(instructions: Seq[Instruction]): Int =
instructions.scanLeft(RegisterState.empty)((state, instruction) => applyInstruction(state, instruction))
.map(_.maxValue).max
def applyInstruction(registerState: RegisterState, instruction: Instruction): RegisterState = (instruction.operation, evaluateCondition(registerState, instruction.condition)) match {
case (_, false) => registerState
case ("inc", true) => registerState.inc(instruction.register, instruction.amount)
case ("dec", true) => registerState.dec(instruction.register, instruction.amount)
case (_, true) => throw new IllegalArgumentException("Wrong operation")
}
def evaluateCondition(registerState: RegisterState, condition: Condition): Boolean = condition.comparison match {
case "==" => registerState.get(condition.register) == condition.amount
case "!=" => registerState.get(condition.register) != condition.amount
case "<" => registerState.get(condition.register) < condition.amount
case "<=" => registerState.get(condition.register) <= condition.amount
case ">" => registerState.get(condition.register) > condition.amount
case ">=" => registerState.get(condition.register) >= condition.amount
}
}