package aoc package day08 import scala.annotation.tailrec val dayNumber = "08" @main def part1: Unit = println(part1(loadInput(dayNumber))) @main def part2: Unit = println(part2(loadInput(dayNumber))) def findPathLength( nodeMap: Map[String, (String, String)], instructions: String, startNode: String, endNode: String => Boolean ): Long = LazyList .continually(instructions) .flatMap(_.toSeq) .scanLeft(startNode) { case (node, 'L') => nodeMap(node)._1 case (node, 'R') => nodeMap(node)._2 } .takeWhile(!endNode(_)) .length def part1(input: String) = val Array(instructions, nodesStr) = input.split("\n\n") val nodeMap = nodesStr .split('\n') .map { case s"$name = ($left, $right)" => (name, (left, right)) } .toMap findPathLength(nodeMap, instructions, "AAA", _ == "ZZZ").toString def part2(input: String) = val Array(instructions, nodesStr) = input.split("\n\n") val nodeMap = nodesStr .split('\n') .map { case s"$name = ($left, $right)" => (name, (left, right)) } .toMap @tailrec def gcd(a: Long, b: Long): Long = if (b == 0) a.abs else gcd(b, a % b) def lcm(a: Long, b: Long) = (a * b).abs / gcd(a, b) nodeMap.keySet .filter(_.endsWith("A")) .map(node => findPathLength(nodeMap, instructions, node, _.endsWith("Z"))) .reduce(lcm) .toString