Last active
January 30, 2024 11:41
-
-
Save segomin/5b24e7ffb470bc9f83ccd439845bd0a3 to your computer and use it in GitHub Desktop.
aoc2023_day08.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import inputs.Input.loadFileSync | |
import locations.Directory.currentDir | |
import scala.annotation.tailrec | |
def loadInput(filename: String) = loadFileSync(s"$currentDir/input/$filename") | |
@main def main: Unit = | |
val testInput = """RL | |
| | |
|AAA = (BBB, CCC) | |
|BBB = (DDD, EEE) | |
|CCC = (ZZZ, GGG) | |
|DDD = (DDD, DDD) | |
|EEE = (EEE, EEE) | |
|GGG = (GGG, GGG) | |
|ZZZ = (ZZZ, ZZZ)""".stripMargin | |
val testInput2 = """LLR | |
| | |
|AAA = (BBB, BBB) | |
|BBB = (AAA, ZZZ) | |
|ZZZ = (ZZZ, ZZZ)""".stripMargin | |
val input = loadInput("day08.txt") | |
assert(part1(testInput) == 2) | |
assert(part1(input) == 19241) | |
val testInput3 ="""LR | |
| | |
|11A = (11B, XXX) | |
|11B = (XXX, 11Z) | |
|11Z = (11B, XXX) | |
|22A = (22B, XXX) | |
|22B = (22C, 22C) | |
|22C = (22Z, 22Z) | |
|22Z = (22B, 22B) | |
|XXX = (XXX, XXX)""".stripMargin | |
assert(part2(testInput3) == 6) | |
assert(part2(input) == BigInt(9606140307013L)) | |
@tailrec | |
def nextStep(step: Long, key: String, instructor: Instructor, pathMap: Map[String, (String, String)]): Long = { | |
if (key == "ZZZ") return step | |
instructor.getNext() match { | |
case 'L' => nextStep(step + 1, pathMap(key)._1, instructor, pathMap) | |
case 'R' => nextStep(step + 1, pathMap(key)._2, instructor, pathMap) | |
} | |
} | |
case class Instruction(key: String, direction: Char) | |
@tailrec | |
def allIntercepts(step: Long, key: String, instructor: Instructor, pathMap: Map[String, (String, String)], intercepts: Map[Instruction, Long]): Map[Instruction, Long] = { | |
val instruction = Instruction(key, instructor.getNext()) | |
if (intercepts.contains(instruction)) return intercepts | |
val accIntercepts = key.last match { | |
case 'Z' => intercepts + (instruction -> step) | |
case _ => intercepts | |
} | |
instruction.direction match { | |
case 'L' => allIntercepts(step + 1, pathMap(key)._1, instructor, pathMap, accIntercepts) | |
case 'R' => allIntercepts(step + 1, pathMap(key)._2, instructor, pathMap, accIntercepts) | |
} | |
} | |
class Instructor(instructions: String) { | |
private var currentIndex = 0 | |
val length = instructions.length | |
def getNext(): Char = { | |
val char = instructions.charAt(currentIndex) | |
currentIndex = (currentIndex + 1) % instructions.length | |
char | |
} | |
} | |
def part1(input: String) = { | |
val (instructions: String, pathMap: Map[String, (String, String)]) = parseInput(input) | |
nextStep(0, "AAA", Instructor(instructions), pathMap) | |
} | |
def part2(input: String): BigInt = { | |
val (instructions: String, pathMap: Map[String, (String, String)]) = parseInput(input) | |
val starts = pathMap.keys.filter(key => key.last == 'A').toList | |
val leastCommonMultiple = starts.flatMap(start => { | |
allIntercepts(0, start, Instructor(instructions), pathMap, Map.empty).map { | |
case (instruction, step) => BigInt(step) | |
} | |
}).reduce((a, b) => a * b / a.gcd(b)) | |
leastCommonMultiple | |
} | |
def parseInput(testInput: String): (String, Map[String, (String, String)]) = { | |
val inputs = testInput.split("\n").toList.splitAt(2) | |
val instructions = inputs._1.head | |
val pattern = """\s*(\w+)\s*=\s*\((\w+),\s*(\w+)\)\s*""".r | |
val pathMap: Map[String, (String, String)] = inputs._2.map { | |
case pattern(key, left, right) => key -> (left, right) | |
}.toMap | |
(instructions, pathMap) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment