Skip to content

Commit

Permalink
2023 - Day08 - refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
fmmr committed Dec 8, 2023
1 parent b80248b commit e1df26e
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 40 deletions.
48 changes: 14 additions & 34 deletions src/main/kotlin/no/rodland/advent_2023/Day08.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@ package no.rodland.advent_2023
import no.rodland.advent.Day
import no.rodland.advent.cycle
import java.math.BigInteger
import java.util.*

// template generated: 08/12/2023
// Fredrik Rødland 2023

class Day08(val input: List<String>) : Day<Long, Long, Pair<Day08.Instructions, Map<String, Day08.Place>>> {
class Day08(val input: List<String>) : Day<BigInteger, BigInteger, Pair<Day08.Instructions, Map<String, Day08.Place>>> {

private val parsed = input.parse()
override fun partOne(): Long {
override fun partOne(): BigInteger {
val (instructions, places) = parsed
return find(listOf("AAA"), places, instructions)
}

override fun partTwo(): Long {
override fun partTwo(): BigInteger {
val (instructions, places) = parsed
val start = places.filterKeys { it.endsWith("A") }.keys.toList()
return find(start, places, instructions)
Expand All @@ -26,52 +25,33 @@ class Day08(val input: List<String>) : Day<Long, Long, Pair<Day08.Instructions,
start: List<String>,
places: Map<String, Place>,
instructions: Instructions
): Long {
): BigInteger {
val periods = start
.map {
dfs(it, places = places, instructions = instructions)
}
.map { traverse(it, places = places, instructions = instructions) }
.map { BigInteger.valueOf(it) }
return periods.reduce { acc, i ->
lcm(acc, i)
}.toLong()
return periods.reduce { acc, i -> lcm(acc, i) }
}

private fun lcm(n1: BigInteger, n2: BigInteger): BigInteger {
// https://no.wikipedia.org/wiki/Minste_felles_multiplum
// lcm = (n1 * n2) / gcd
val gcd = n1.gcd(n2)
return ((n1 * n2) / gcd)
return (n1 * n2) / n1.gcd(n2)
}

data class State(val id: String, val pos: Int)

private fun dfs(
startId: String,
places: Map<String, Place>,
instructions: Instructions
): Long {
private fun traverse(startId: String, places: Map<String, Place>, instructions: Instructions): Long {
var seenCount = 0L
val stack = Stack<State>()
val pos = instructions.pos()
stack.push(State(startId, pos))
while (stack.isNotEmpty()) {
val (id, _) = stack.pop()
var id = startId
for (dir in instructions) {
seenCount++
val nextPlaces = places[id]!!
id = if (dir == Dir.L) nextPlaces.left else nextPlaces.right
if (id.endsWith("Z")) {
return seenCount
}
val nextPlaces = places[id] ?: error("hm - why don't we have place $id")
// If this state has been visited before, skip
// if (!visited.add(State(id, instructions.pos()))) { println("SEEN"); continue }
// println("A PLACE: $nextPlaces $ids")

val nextDir = instructions.next()
val nextIds = if (nextDir == Dir.L) nextPlaces.left else nextPlaces.right
val nextPos = instructions.pos()
stack.push(State(nextIds, nextPos))
seenCount++
}
return seenCount
error("Endstate not found")
}

enum class Dir { L, R }
Expand Down
13 changes: 7 additions & 6 deletions src/test/kotlin/no/rodland/advent_2023/Day08Test.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import no.rodland.advent.*
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import readFile
import java.math.BigInteger

@Suppress("ClassName", "PrivatePropertyName")
@DisableSlow
Expand Down Expand Up @@ -40,10 +41,10 @@ internal class Day08Test {
"ZZZ = (ZZZ, ZZZ)",
)

private val resultTestOne = 2L
private val resultTestTwo = 2L
private val resultOne = 18827L
private val resultTwo = 20220305520997L
private val resultTestOne = BigInteger.valueOf(2L)
private val resultTestTwo = BigInteger.valueOf(2L)
private val resultOne = BigInteger.valueOf(18827)
private val resultTwo = BigInteger.valueOf(20220305520997L)

val test = defaultTestSuiteParseOnInit(
Day08(data08),
Expand Down Expand Up @@ -81,7 +82,7 @@ internal class Day08Test {
@Test
fun `08,1,test,2`() {
val day = Day08(test08_2)
report(test.testPart1.copy(function = { day.partOne() }, expected = 6L))
report(test.testPart1.copy(function = { day.partOne() }, expected = BigInteger.valueOf(6L)))
}

@Test
Expand All @@ -95,7 +96,7 @@ internal class Day08Test {
@Test
fun `08,2,test`() {
val day08 = Day08(test08_3)
report(AOCTest({ day08.partTwo() }, Unit, 6L, 1, day08.day, Part.TWO, false))
report(AOCTest({ day08.partTwo() }, Unit, BigInteger.valueOf(6), 1, day08.day, Part.TWO, false))
}

@Test
Expand Down

0 comments on commit e1df26e

Please sign in to comment.