-
Notifications
You must be signed in to change notification settings - Fork 3
/
Day09.scala
58 lines (45 loc) · 3.03 KB
/
Day09.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
package AdventOfCode2019
object Day09:
object IntCode:
val powers = Map(1 -> 100, 2 -> 1000, 3 -> 10000)
sealed trait State
case object Initial extends State
case object Running extends State
case object Halted extends State
case class Output(value: Long) extends State
def apply(input: Seq[Long]): IntCode =
val memory = input.zipWithIndex.map((value, index) => index.toLong -> value)
IntCode(0, 0, memory.toMap.withDefaultValue(0), Seq(), Initial)
end IntCode
case class IntCode(ip: Long, relativeBase: Long, memory: Map[Long, Long], input: Seq[Long], result: IntCode.State):
import IntCode._
private def read(offset: Int): Long = (memory(ip) / powers(offset)) % 10 match
case 0 => memory(memory(ip + offset))
case 1 => memory(ip + offset)
case 2 => memory(relativeBase + memory(ip + offset))
private def write(offset: Int, value: Long): Map[Long, Long] = (memory(ip) / powers(offset)) % 10 match
case 0 => memory.updated(memory(ip + offset), value)
case 2 => memory.updated(relativeBase + memory(ip + offset), value)
def next: IntCode = memory(ip) % 100 match
case 1 => copy(ip = ip + 4, memory = write(3, read(1) + read(2)), result = Running) // Add
case 2 => copy(ip = ip + 4, memory = write(3, read(1) * read(2)), result = Running) // Multiply
case 3 => copy(ip = ip + 2, memory = write(1, input.head), input = input.tail, result = Running) // Read
case 4 => copy(ip = ip + 2, result = Output(read(1))) // Write
case 5 => copy(ip = if read(1) != 0 then read(2) else ip + 3, result = Running) // Jump if true
case 6 => copy(ip = if read(1) == 0 then read(2) else ip + 3, result = Running) // Jump if false
case 7 => copy(ip = ip + 4, memory = write(3, if read(1) < read(2) then 1 else 0), result = Running) // Less than
case 8 => copy(ip = ip + 4, memory = write(3, if read(1) == read(2) then 1 else 0), result = Running) // Equals
case 9 => copy(ip = ip + 2, relativeBase = relativeBase + read(1), result = Running) // Relative base
case 99 => copy(result = Halted) // Halt
def withInput(next: Long*): IntCode = copy(input = next)
def nextOutput: IntCode = Iterator.iterate(next)(_.next).dropWhile(_.result == Running).next()
def allOutput: Seq[Long] =
val output = Iterator.iterate(this)(_.nextOutput).takeWhile(_.result != Halted)
output.toSeq.map(_.result).collect { case Output(value) => value }
end IntCode
def part1(memory: Seq[Long]): Long = IntCode(memory).withInput(1).allOutput.last
def part2(memory: Seq[Long]): Long = IntCode(memory).withInput(2).allOutput.last
def main(args: Array[String]): Unit =
val data = io.Source.fromResource("AdventOfCode2019/Day09.txt").mkString.trim.split(",").map(_.toLong).toSeq
println(part1(data))
println(part2(data))