|
| 1 | +package AdventOfCode2015 |
| 2 | + |
| 3 | +object Day23: |
| 4 | + sealed trait State |
| 5 | + case object Running extends State |
| 6 | + case object Halted extends State |
| 7 | + |
| 8 | + case class Cpu(instructions: Seq[String], registers: Map[String, Int] = Map(), ip: Int = 0, state: State = Running): |
| 9 | + def next: Cpu = copy(ip = ip + 1) |
| 10 | + def read(key: String): Int = key.toIntOption.getOrElse(registers.getOrElse(key, 0)) |
| 11 | + def write(key: String, value: Int): Cpu = next.copy(registers = registers.updated(key, value)) |
| 12 | + def step: Cpu = |
| 13 | + if !instructions.indices.contains(ip) then return copy(state = Halted) |
| 14 | + val (op, src, dest) = instructions(ip).split("[, ]+") match |
| 15 | + case Array(op, src, dest) => (op, src, dest) |
| 16 | + case Array(op, dest) => (op, "", dest) |
| 17 | + op match |
| 18 | + case "hlf" => write(dest, read(dest) / 2) |
| 19 | + case "tpl" => write(dest, read(dest) * 3) |
| 20 | + case "inc" => write(dest, read(dest) + 1) |
| 21 | + case "jmp" => copy(ip = ip + read(dest)) |
| 22 | + case "jie" => if read(src) % 2 == 0 then copy(ip = ip + read(dest)) else next |
| 23 | + case "jio" => if read(src) == 1 then copy(ip = ip + read(dest)) else next |
| 24 | + end Cpu |
| 25 | + |
| 26 | + // Reverse engineering the code shows that it calculates the length of the |
| 27 | + // 3n + 1 sequence (https://en.wikipedia.org/wiki/Collatz_conjecture) |
| 28 | + // for one of two different numbers chosen depending on whether a is 0 or 1. |
| 29 | + def run(input: Seq[String], a: Int): Int = |
| 30 | + Iterator.iterate(Cpu(input, Map("a" -> a)))(_.step).dropWhile(_.state == Running).next().registers("b") |
| 31 | + |
| 32 | + def part1(input: Seq[String]): Int = run(input, 0) |
| 33 | + |
| 34 | + def part2(input: Seq[String]): Int = run(input, 1) |
| 35 | + |
| 36 | + def main(args: Array[String]): Unit = |
| 37 | + val data = io.Source.fromResource("AdventOfCode2015/Day23.txt").getLines().toSeq |
| 38 | + println(part1(data)) |
| 39 | + println(part2(data)) |
0 commit comments