Skip to content

Commit

Permalink
day 23... part took me ages to discover the single flaw (visited the …
Browse files Browse the repository at this point in the history
…same junction multiple times taking loops, so the graph search room was way too big and produced too high results)
  • Loading branch information
norganos committed Dec 23, 2023
1 parent ef298ea commit 6f36144
Showing 3 changed files with 192 additions and 5 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ dependencies {
implementation("io.micronaut.serde:micronaut-serde-jackson")
implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0-RC2")
implementation("de.linkel.aoc:aoc-utils:1.0.5")
runtimeOnly("ch.qos.logback:logback-classic")
runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin")
155 changes: 154 additions & 1 deletion src/main/kotlin/de/linkel/aoc/Day23.kt
Original file line number Diff line number Diff line change
@@ -2,13 +2,166 @@ package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import de.linkel.aoc.utils.grid.Area
import de.linkel.aoc.utils.grid.Point
import jakarta.inject.Singleton
import java.util.*
import kotlin.collections.ArrayDeque
import kotlin.collections.List
import kotlin.collections.Set
import kotlin.collections.filter
import kotlin.collections.first
import kotlin.collections.forEach
import kotlin.collections.isNotEmpty
import kotlin.collections.last
import kotlin.collections.lastIndex
import kotlin.collections.listOf
import kotlin.collections.mutableSetOf
import kotlin.collections.plus
import kotlin.collections.setOf
import kotlin.collections.sumOf
import kotlin.math.max

@Singleton
class Day23: AbstractLinesAdventDay<Int>() {
override val day = 23

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
val map = lines.toList()
val start = map.first().indexOf('.') to 0
val end = map.last().indexOf('.') to map.lastIndex

return if (part == QuizPart.A) longestPath(map, start, end)
else {
val area = Area(
x = 0,
y = 0,
width = map.first().length,
height = map.size
)

val startPoint = Point(start.first, start.second)
val endPoint = Point(end.first, end.second)
val segments = extractSegments(area, map, startPoint, endPoint)
longestPath(segments, startPoint to segments.first { it.start == startPoint }, segments.first { it.end == endPoint })
}
}

fun longestPath(map: List<String>, start: Pair<Int, Int>, end: Pair<Int, Int>): Int {
val xRange = 0 until map.first().length
val yRange = 0 until map.size
val queue = Stack<List<Pair<Int,Int>>>()
queue.push(listOf(start))
var max = 0
while (queue.isNotEmpty()) {
val path = queue.pop()
val pos = path.last()
if (pos == end) {
max = max(max, path.size)
} else when (map[pos.second][pos.first]) {
'>' -> listOf((pos.first + 1) to pos.second)
'<' -> listOf((pos.first - 1) to pos.second)
'^' -> listOf(pos.first to (pos.second - 1))
'v' -> listOf(pos.first to (pos.second + 1))
else -> listOf(
(pos.first + 1) to pos.second,
(pos.first - 1) to pos.second,
pos.first to (pos.second + 1),
pos.first to (pos.second - 1),
)
}
.filter { it.first in xRange && it.second in yRange }
.filter { map[it.second][it.first] != '#' }
.filter { it !in path }
.forEach {
queue.push(path + it)
}
}
return max - 1
}

data class Segment(
val start: Point,
val end: Point,
val length: Int
) {
fun other(point: Point) = if (point == start) end else start
}

fun extractSegments(area: Area, map: List<String>, initStart: Point, finalEnd: Point): Set<Segment> {
val queue = ArrayDeque<Pair<Point, Point>>()
queue.add(initStart to initStart)
val visited = mutableSetOf(initStart)
val result = mutableSetOf<Segment>()
while (queue.isNotEmpty()) {
var (start, pos) = queue.removeFirst()
var steps = 0
while (true) {
visited.add(pos)
if (pos != start) {
steps++
}
val rawNeighbors = listOf(
pos + NORTH,
pos + WEST,
pos + EAST,
pos + SOUTH
)
.filter { it in area }
.filter { map[it.y][it.x] != '#' }

if (pos != initStart && rawNeighbors.size == 1) {
if (pos == finalEnd) {
result.add(Segment(start, pos, steps))
}
break
}

val neighbors = rawNeighbors
.filter { it !in visited }

if (neighbors.size == 1) {
pos = neighbors.first()
} else {
result.add(Segment(start, pos, steps))
neighbors
.forEach {
queue.addLast(pos to it)
}
break
}
}
}
return result
}

fun longestPath(graph: Set<Segment>, start: Pair<Point, Segment>, end: Segment): Int {
data class State(val point: Point, val path: List<Segment>, val visited: Set<Point>)

val queue = Stack<State>()
queue.push(State(start.first, listOf(start.second), setOf(start.second.start, start.second.end)))
var max = 0

while (queue.isNotEmpty()) {
val (pos, path, blacklist) = queue.pop()
val segment = path.last()
if (segment == end) {
val len = path.sumOf { it.length }
if (len > max) {
max = len
println("zwischenergebnis $max")
}
} else {
val endPoint = segment.other(pos)
graph
.filter { it.start == endPoint || it.end == endPoint }
.filter { it !in path }
.filter { it.other(endPoint) !in blacklist }
.forEach {
queue.push(State(endPoint,path + it, blacklist + it.other(endPoint)))
}
}
}
return max
}
}
41 changes: 37 additions & 4 deletions src/test/kotlin/de/linkel/aoc/Day23Test.kt
Original file line number Diff line number Diff line change
@@ -2,12 +2,45 @@ package de.linkel.aoc

class Day23Test: AbstractDayTest<Int>() {
override val exampleA = """
#.#####################
#.......#########...###
#######.#########.#.###
###.....#.>.>.###.#.###
###v#####.#v#.###.#.###
###.>...#.#.#.....#...#
###v###.#.#.#########.#
###...#.#.#.......#...#
#####.#.#.#######.#.###
#.....#.#.#.......#...#
#.#####.#.#.#########v#
#.#...#...#...###...>.#
#.#.#v#######v###.###v#
#...#.>.#...>.>.#.###.#
#####v#.#.###v#.#.###.#
#.....#...#...#.#.#...#
#.#########.###.#.#.###
#...###...#...#...#.###
###.###.#.###v#####v###
#...#...#.#.>.>.#.>.###
#.###.###.#.###.#.#v###
#.....###...###...#...#
#####################.#
""".trimIndent()
override val exampleSolutionA = 0
override val solutionA = 0
override val exampleSolutionA = 94
override val solutionA = 2050

override val exampleSolutionB = 0
override val solutionB = 0
override val exampleSolutionB = 154
override val solutionB = 6262

override val implementation = Day23()
}
/* wrong results:
5459
5587
5723 5907
7186
7470
7566
7690
*/

0 comments on commit 6f36144

Please sign in to comment.