Day 8.
This commit is contained in:
parent
ba3d677880
commit
9d314599e4
144
src/aoc2023/Day08.kt
Normal file
144
src/aoc2023/Day08.kt
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
package aoc2023
|
||||||
|
|
||||||
|
import println
|
||||||
|
import readInput
|
||||||
|
|
||||||
|
/*
|
||||||
|
--- Day 8: Haunted Wasteland ---
|
||||||
|
You're still riding a camel across Desert Island when you spot a sandstorm quickly approaching. When you turn to warn the Elf, she disappears before your eyes! To be fair, she had just finished warning you about ghosts a few minutes ago.
|
||||||
|
One of the camel's pouches is labeled "maps" - sure enough, it's full of documents (your puzzle input) about how to navigate the desert. At least, you're pretty sure that's what they are; one of the documents contains a list of left/right instructions, and the rest of the documents seem to describe some kind of network of labeled nodes.
|
||||||
|
It seems like you're meant to use the left/right instructions to navigate the network. Perhaps if you have the camel follow the same instructions, you can escape the haunted wasteland!
|
||||||
|
After examining the maps for a bit, two nodes stick out: AAA and ZZZ. You feel like AAA is where you are now, and you have to follow the left/right instructions until you reach ZZZ.
|
||||||
|
This format defines each node of the network individually. For example:
|
||||||
|
RL
|
||||||
|
|
||||||
|
AAA = (BBB, CCC)
|
||||||
|
BBB = (DDD, EEE)
|
||||||
|
CCC = (ZZZ, GGG)
|
||||||
|
DDD = (DDD, DDD)
|
||||||
|
EEE = (EEE, EEE)
|
||||||
|
GGG = (GGG, GGG)
|
||||||
|
ZZZ = (ZZZ, ZZZ)
|
||||||
|
|
||||||
|
Starting with AAA, you need to look up the next element based on the next left/right instruction in your input. In this example, start with AAA and go right (R) by choosing the right element of AAA, CCC. Then, L means to choose the left element of CCC, ZZZ. By following the left/right instructions, you reach ZZZ in 2 steps.
|
||||||
|
Of course, you might not find ZZZ right away. If you run out of left/right instructions, repeat the whole sequence of instructions as necessary: RL really means RLRLRLRLRLRLRLRL... and so on. For example, here is a situation that takes 6 steps to reach ZZZ:
|
||||||
|
LLR
|
||||||
|
|
||||||
|
AAA = (BBB, BBB)
|
||||||
|
BBB = (AAA, ZZZ)
|
||||||
|
ZZZ = (ZZZ, ZZZ)
|
||||||
|
|
||||||
|
Starting at AAA, follow the left/right instructions. How many steps are required to reach ZZZ?
|
||||||
|
|
||||||
|
*/
|
||||||
|
fun main() {
|
||||||
|
|
||||||
|
val inlineTestInput = """
|
||||||
|
RL
|
||||||
|
|
||||||
|
AAA = (BBB, CCC)
|
||||||
|
BBB = (DDD, EEE)
|
||||||
|
CCC = (ZZZ, GGG)
|
||||||
|
DDD = (DDD, DDD)
|
||||||
|
EEE = (EEE, EEE)
|
||||||
|
GGG = (GGG, GGG)
|
||||||
|
ZZZ = (ZZZ, ZZZ)
|
||||||
|
"""
|
||||||
|
val inlineTestInput2 = """
|
||||||
|
LR
|
||||||
|
|
||||||
|
ABA = (ABB, XXX)
|
||||||
|
ABB = (XXX, ABZ)
|
||||||
|
ABZ = (ABB, XXX)
|
||||||
|
BAA = (BAB, XXX)
|
||||||
|
BAB = (BAC, BAC)
|
||||||
|
BAC = (BAZ, BAZ)
|
||||||
|
BAZ = (BAB, BAB)
|
||||||
|
XXX = (XXX, XXX)
|
||||||
|
"""
|
||||||
|
|
||||||
|
fun part1(input: List<String>): Int {
|
||||||
|
val cmd = input[0]
|
||||||
|
val map = HashMap<String, Pair<String, String>>()
|
||||||
|
for (i in input.drop(2)) {
|
||||||
|
"([A-Z][A-Z][A-Z]) = .([A-Z][A-Z][A-Z]), ([A-Z][A-Z][A-Z]).".toRegex().matchEntire(i)!!.destructured
|
||||||
|
.let { (id, left, right) -> map[id] = left to right }
|
||||||
|
}
|
||||||
|
var instPos = 0
|
||||||
|
var steps = 0
|
||||||
|
var loc = "AAA"
|
||||||
|
do {
|
||||||
|
loc = if (cmd[instPos] == 'L') map[loc]!!.first else map[loc]!!.second
|
||||||
|
instPos = (instPos + 1) % cmd.length
|
||||||
|
steps++
|
||||||
|
} while (loc != "ZZZ")
|
||||||
|
return steps
|
||||||
|
}
|
||||||
|
|
||||||
|
fun part2(input: List<String>): Long {
|
||||||
|
val cmd = input[0]
|
||||||
|
val map = HashMap<String, Pair<String, String>>()
|
||||||
|
for (i in input.drop(2)) {
|
||||||
|
"([A-Z][A-Z][A-Z]) = .([A-Z][A-Z][A-Z]), ([A-Z][A-Z][A-Z]).".toRegex().matchEntire(i)!!.destructured
|
||||||
|
.let { (id, left, right) -> map[id] = left to right }
|
||||||
|
}
|
||||||
|
val starts = map.keys.filter { it.endsWith("A") }
|
||||||
|
var ggts = HashSet<Int>()
|
||||||
|
for (start in starts) {
|
||||||
|
var instPos = 0
|
||||||
|
var steps = 0
|
||||||
|
var loc = start
|
||||||
|
do {
|
||||||
|
loc = if (cmd[instPos] == 'L') map[loc]!!.first else map[loc]!!.second
|
||||||
|
instPos = (instPos + 1) % cmd.length
|
||||||
|
steps++
|
||||||
|
} while (!loc.endsWith("Z"))
|
||||||
|
ggts.add(steps)
|
||||||
|
}
|
||||||
|
val primes = ArrayList<Int>()
|
||||||
|
val factors = HashSet<Int>()
|
||||||
|
var prime = 2
|
||||||
|
primes.add(2)
|
||||||
|
do {
|
||||||
|
val newGgts = HashSet<Int>()
|
||||||
|
for (f in ggts) {
|
||||||
|
if (prime * 2 - 1 > f) {
|
||||||
|
factors.add(f)
|
||||||
|
} else {
|
||||||
|
if (f % prime == 0) {
|
||||||
|
newGgts.add(f / prime)
|
||||||
|
factors.add(prime)
|
||||||
|
} else {
|
||||||
|
newGgts.add(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ggts = newGgts
|
||||||
|
if (prime == 2) {
|
||||||
|
prime = 3
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
prime += 2
|
||||||
|
} while (primes.any { (prime % it) == 0 })
|
||||||
|
}
|
||||||
|
primes.add(prime)
|
||||||
|
} while (ggts.isNotEmpty())
|
||||||
|
|
||||||
|
return factors.map { it.toLong() }.reduce(Long::times)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if implementation meets criteria from the description, like:
|
||||||
|
val testInput = inlineTestInput.trim().reader().readLines()
|
||||||
|
val testInput2 = inlineTestInput2.trim().reader().readLines()
|
||||||
|
//val testInput = readInput("aoc2023/Day08_test")
|
||||||
|
val testInputPart1Result = part1(testInput)
|
||||||
|
println("Part 1 Test: $testInputPart1Result")
|
||||||
|
val testInputPart2Result = part2(testInput2)
|
||||||
|
println("Part 2 Test: $testInputPart2Result")
|
||||||
|
check(testInputPart1Result == 2)
|
||||||
|
check(testInputPart2Result == 6L)
|
||||||
|
|
||||||
|
val input = readInput("aoc2023/Day08")
|
||||||
|
part1(input).println()
|
||||||
|
part2(input).println()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user