Skip to content

Commit

Permalink
day 17 working, and day 18 not working
Browse files Browse the repository at this point in the history
  • Loading branch information
norganos committed Dec 19, 2023
1 parent 603fbb2 commit 0b7bbe1
Show file tree
Hide file tree
Showing 6 changed files with 346 additions and 0 deletions.
143 changes: 143 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day17.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import de.linkel.aoc.utils.grid.Grid
import de.linkel.aoc.utils.grid.Point
import de.linkel.aoc.utils.grid.Vector
import jakarta.inject.Singleton
import java.util.PriorityQueue

@Singleton
class Day17: AbstractLinesAdventDay<Int>() {
override val day = 17

override fun process(part: QuizPart, lines: Sequence<String>): Int {
val grid = Grid.parse(lines) { pos, char ->
char.digitToInt()
}
val dest = Point(grid.width - 1, grid.height - 1)
val start = State(Point(0, 0), Direction.EAST, 0)
return if (part == QuizPart.A) {
dijkstra(
start,
{ state -> state.pos == dest },
{ state -> state.possibleNextStates(1, 3).filter { it.pos in grid } },
{ _, to -> grid[to.pos]!! }
)!!.first
} else {
dijkstra(
start,
{ state -> state.pos == dest && state.straight >= 4 },
{ state -> state.possibleNextStates(4, 10).filter { it.pos in grid } },
{ _, to -> grid[to.pos]!! }
)!!.first
}
}

fun print(grid: Grid<Int>, path: Collection<Point>) {
val points = path.toSet()
println(
buildString {
(0 until grid.height).forEach { y ->
(0 until grid.width).forEach { x ->
val p = Point(x, y)
if (p in points) {
append('#')
} else {
append('.')
}
}
append('\n')
}
}
)
}
}

enum class Direction(
val vector: Vector
) {
NORTH(Vector(0, -1)) {
override val left get() = WEST
override val right get() = EAST
override val opposite get() = SOUTH
},
EAST(Vector(1, 0)) {
override val left get() = NORTH
override val right get() = SOUTH
override val opposite get() = WEST
},
SOUTH(Vector(0, 1)) {
override val left get() = EAST
override val right get() = WEST
override val opposite get() = NORTH
},
WEST(Vector(-1, 0)) {
override val left get() = SOUTH
override val right get() = NORTH
override val opposite get() = EAST
};

abstract val left: Direction
abstract val right: Direction
abstract val opposite: Direction
}

operator fun Point.plus(direction: Direction): Point = this + direction.vector

data class State(
val pos: Point,
val direction: Direction,
val straight: Int
) {
fun possibleNextStates(minStraight: Int = 1, maxStraight: Int = 100): List<State> {
return buildList {
if (straight < maxStraight) {
add(State(pos + direction, direction, straight + 1))
}
if (straight >= minStraight) {
add(State(pos + direction.right, direction.right, 1))
add(State(pos + direction.left, direction.left, 1))
}
}
}
}

fun <S> dijkstra(
start: S,
endLambda: (S) -> Boolean,
nextLamba: (S) -> Iterable<S>,
costLambda: (S, S) -> Int
): Pair<Int, List<S>>? {
data class Evaluated(val distance: Int, val prev: S?)

data class Planned(val state: S, val distance: Int) : Comparable<Planned> {
override fun compareTo(other: Planned): Int = distance.compareTo(other.distance)
}

val queue = PriorityQueue(listOf(Planned(start, 0)))
val evaluated = mutableMapOf(start to Evaluated(0, null))

while (queue.isNotEmpty()) {
val current = queue.remove()
if (endLambda(current.state)) {
val winningPath = mutableListOf<S>()
var s: S? = current.state
while (s != null) {
winningPath.add(0, s)
s = evaluated[s]!!.prev
}
return current.distance to winningPath
}

nextLamba(current.state)
.filter { it !in evaluated }
.forEach { state ->
val distance = current.distance + costLambda(current.state, state)
queue.add(Planned(state, distance))
evaluated[state] = Evaluated(distance, current.state)
}
}
return null
}
123 changes: 123 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day18.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import de.linkel.aoc.utils.grid.Grid
import de.linkel.aoc.utils.grid.Point
import jakarta.inject.Singleton
import kotlin.math.max
import kotlin.math.min

@Singleton
class Day18: AbstractLinesAdventDay<Long>() {
override val day = 18

data class Cube(
val dirIn: Char,
val dirOut: Char
)
data class Point(
val x: Long,
val y: Long
)
interface Vector {
val deltaX: Long
val deltaY: Long
}
enum class Direction(
override val deltaX: Long,
override val deltaY: Long
): Vector {
R(1, 0),
D(0, 1),
L(-1, 0),
U(0, -1)
}
data class GenericVector(
override val deltaX: Long,
override val deltaY: Long
): Vector
operator fun Point.plus(vector: Vector): Point = Point(this.x + vector.deltaX, this.y + vector.deltaY)
operator fun Vector.times(factor: Long): Vector = GenericVector(this.deltaX * factor, this.deltaY * factor)

override fun process(part: QuizPart, lines: Sequence<String>): Long {
val origin = Point(0L,0L)
val map = mutableMapOf<Point, Cube>()
var minX = 0L
var minY = 0L
var maxX = 0L
var maxY = 0L
// val map = Grid<Cube>(origin, Dimension(1,1))
map[origin] = Cube('0','?')
lines.fold(origin) { pos, line ->
val (dir, len) = if (part == QuizPart.A) {
val token = line.split(' ')
val dir = Direction.valueOf(token[0])
val len = token[1].toLong()
dir to len
} else {
val hex = line.substringAfter('#').substringBefore(')')
val len = hex.substring(0, 5).toLong(16)
val dir = Direction.entries[hex[5].digitToInt()]
dir to len
}
val dest = pos + dir * len
// map.stretchTo(dest)
(1L..len).forEach {
map[pos + dir * it] = Cube(line[0], line[0])
}
minX = min(minX, dest.x)
minY = min(minY, dest.y)
maxX = max(maxX, dest.x)
maxY = max(maxY, dest.y)
map[pos] = map[pos]!!.copy(dirOut = line[0])
dest
}

var insides = 0L
(minY..maxY)
.forEach { y ->
// var upIn = false
// var downOut = false
var inside = false
(minX..maxX)
.forEach { x ->
val p = Point(x, y)
if (map[p] != null) {
// if (map[p]!!.dirIn == 'D' || map[p]!!.dirOut == 'U')
if (map[p]!!.dirIn == 'U' || map[p]!!.dirOut == 'D')
inside = !inside
// if (map[p]!!.dirIn == 'U')
// upIn = !upIn
// if (map[p]!!.dirOut == 'D')
// downOut = !downOut
} else if (inside) {
// } else if (upIn != downOut) {
insides++
// map[p] = Cube('#', '#')
}
}
}

return insides + map.size
}
fun printMap(grid: Grid<Cube>) {
println(
buildString {
(grid.area.y until (grid.area.y + grid.area.height))
.forEach { y ->
(grid.area.x until (grid.area.x + grid.area.width))
.forEach { x ->
val p = Point(x, y)
if (grid[p] != null) {
append(grid[p]!!.dirIn)
} else {
append('.')
}
}
append('\n')
}
}
)
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day19.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import jakarta.inject.Singleton

@Singleton
class Day19: AbstractLinesAdventDay<Int>() {
override val day = 19

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
}
}
26 changes: 26 additions & 0 deletions src/test/kotlin/de/linkel/aoc/Day17Test.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package de.linkel.aoc

class Day17Test: AbstractDayTest<Int>() {
override val exampleA = """
2413432311323
3215453535623
3255245654254
3446585845452
4546657867536
1438598798454
4457876987766
3637877979653
4654967986887
4564679986453
1224686865563
2546548887735
4322674655533
""".trimIndent()
override val exampleSolutionA = 102
override val solutionA = 956

override val exampleSolutionB = 94
override val solutionB = 1106

override val implementation = Day17()
}
27 changes: 27 additions & 0 deletions src/test/kotlin/de/linkel/aoc/Day18Test.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package de.linkel.aoc

class Day18Test: AbstractDayTest<Long>() {
override val exampleA = """
R 6 (#70c710)
D 5 (#0dc571)
L 2 (#5713f0)
D 2 (#d2c081)
R 2 (#59c680)
D 2 (#411b91)
L 5 (#8ceee2)
U 2 (#caa173)
L 1 (#1b58a2)
U 2 (#caa171)
R 2 (#7807d2)
U 3 (#a77fa3)
L 2 (#015232)
U 2 (#7a21e3)
""".trimIndent()
override val exampleSolutionA = 62L
override val solutionA = 35991L

override val exampleSolutionB = 952408144115L
override val solutionB = 0L

override val implementation = Day18()
}
13 changes: 13 additions & 0 deletions src/test/kotlin/de/linkel/aoc/Day19Test.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package de.linkel.aoc

class Day19Test: AbstractDayTest<Int>() {
override val exampleA = """
""".trimIndent()
override val exampleSolutionA = 0
override val solutionA = 0

override val exampleSolutionB = 0
override val solutionB = 0

override val implementation = Day19()
}

0 comments on commit 0b7bbe1

Please sign in to comment.