Skip to content

Commit

Permalink
Extract LongCoord to separate file and add missing functions
Browse files Browse the repository at this point in the history
  • Loading branch information
pkoziol committed Dec 11, 2023
1 parent 89675bb commit a04a93e
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 23 deletions.
23 changes: 0 additions & 23 deletions src/main/kotlin/biz/koziolek/adventofcode/coords2d.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,6 @@ data class Coord(val x: Int, val y: Int) {
}
}

data class LongCoord(val x: Long, val y: Long) {
constructor(x: Int, y: Int) : this(x.toLong(), y.toLong())
operator fun plus(other: LongCoord) = LongCoord(x + other.x, y + other.y)
operator fun minus(other: LongCoord) = LongCoord(x - other.x, y - other.y)
operator fun unaryMinus() = LongCoord(-x, -y)
override fun toString() = "$x,$y"

fun distanceTo(other: LongCoord) = sqrt(
(x - other.x).toDouble().pow(2)
+ (y - other.y).toDouble().pow(2)
)

infix fun manhattanDistanceTo(other: LongCoord): Long =
abs(x - other.x) + abs(y - other.y)

companion object {
fun fromString(str: String): LongCoord =
str.split(',')
.map { it.toLong() }
.let { LongCoord(x = it[0], y = it[1]) }
}
}

fun IntProgression.zipAsCoord(ys: IntProgression) = zip(ys) { x, y -> Coord(x, y) }

fun <T> Map<Coord, T>.getWidth() = keys.maxOfOrNull { it.x }?.plus(1) ?: 0
Expand Down
81 changes: 81 additions & 0 deletions src/main/kotlin/biz/koziolek/adventofcode/coords2dLong.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package biz.koziolek.adventofcode

import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.sqrt

data class LongCoord(val x: Long, val y: Long) {
constructor(x: Int, y: Int) : this(x.toLong(), y.toLong())
operator fun plus(other: LongCoord) = LongCoord(x + other.x, y + other.y)
operator fun minus(other: LongCoord) = LongCoord(x - other.x, y - other.y)
operator fun unaryMinus() = LongCoord(-x, -y)
override fun toString() = "$x,$y"

fun distanceTo(other: LongCoord) = sqrt(
(x - other.x).toDouble().pow(2)
+ (y - other.y).toDouble().pow(2)
)

infix fun manhattanDistanceTo(other: LongCoord): Long =
abs(x - other.x) + abs(y - other.y)

companion object {
fun fromString(str: String): LongCoord =
str.split(',')
.map { it.toInt() }
.let { LongCoord(x = it[0], y = it[1]) }
}
}

fun LongProgression.zipAsCoord(ys: LongProgression) = zip(ys) { x, y -> LongCoord(x, y) }

fun <T> Map<LongCoord, T>.getWidth() = keys.maxOfOrNull { it.x }?.plus(1) ?: 0

fun <T> Map<LongCoord, T>.getHeight() = keys.maxOfOrNull { it.y }?.plus(1) ?: 0

fun <T> Map<LongCoord, T>.getAdjacentCoords(coord: LongCoord, includeDiagonal: Boolean): Set<LongCoord> =
keys.getAdjacentCoords(coord, includeDiagonal)

fun Iterable<LongCoord>.getAdjacentCoords(coord: LongCoord, includeDiagonal: Boolean): Set<LongCoord> {
return sequence {
yield(LongCoord(-1, 0))
yield(LongCoord(0, -1))
yield(LongCoord(1, 0))
yield(LongCoord(0, 1))

if (includeDiagonal) {
yield(LongCoord(-1, -1))
yield(LongCoord(1, -1))
yield(LongCoord(-1, 1))
yield(LongCoord(1, 1))
}
}
.map { coord + it }
.filter { contains(it) }
.toSet()
}

fun Map<LongCoord, Int>.toGraph(includeDiagonal: Boolean): Graph<LongCoordNode, UniDirectionalGraphEdge<LongCoordNode>> =
buildGraph {
this@toGraph.forEach { (coord, value) ->
val node2 = coord.toGraphNode()

getAdjacentCoords(coord, includeDiagonal)
.forEach { adjCoord ->
add(UniDirectionalGraphEdge(
node1 = adjCoord.toGraphNode(),
node2 = node2,
weight = value,
))
}
}
}

fun LongCoord.toGraphNode() = LongCoordNode(this)

data class LongCoordNode(val coord: LongCoord) : GraphNode {

override val id = "x${coord.x}_y${coord.y}"

override fun toGraphvizString() = id
}
86 changes: 86 additions & 0 deletions src/test/kotlin/biz/koziolek/adventofcode/Coords2dLongTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package biz.koziolek.adventofcode

import org.junit.jupiter.api.Test

import org.junit.jupiter.api.Assertions.*

internal class Coords2dLongTest {

private val map = mapOf(
LongCoord(0, 0) to 1,
LongCoord(1, 0) to 2,
LongCoord(2, 0) to 3,
LongCoord(0, 1) to 4,
LongCoord(1, 1) to 5,
LongCoord(2, 1) to 6,
LongCoord(0, 2) to 7,
LongCoord(1, 2) to 8,
LongCoord(2, 2) to 9,
LongCoord(0, 3) to 10,
LongCoord(1, 3) to 11,
LongCoord(2, 3) to 12,
)

@Test
fun testCoordPlus() {
assertEquals(LongCoord(10, 20), LongCoord(3, 11) + LongCoord(7, 9))
}

@Test
fun testCoordMinus() {
assertEquals(LongCoord(-4, 2), LongCoord(3, 11) - LongCoord(7, 9))
}

@Test
fun testCoordUnaryMinus() {
assertEquals(LongCoord(5, -6), -LongCoord(-5, 6))
}

@Test
fun testZipAsCoord() {
val coords = (1L..4L).zipAsCoord(7L downTo 4L)

assertEquals(4, coords.size)
assertEquals(LongCoord(1, 7), coords[0])
assertEquals(LongCoord(2, 6), coords[1])
assertEquals(LongCoord(3, 5), coords[2])
assertEquals(LongCoord(4, 4), coords[3])
}

@Test
fun testMapGetWidth() {
assertEquals(3, map.getWidth())
}

@Test
fun testMapGetHeight() {
assertEquals(4, map.getHeight())
}

@Test
fun testMapGetAdjacentCoords() {
val corner = LongCoord(0, 0)

val expectedAdjacentCorner = setOf(LongCoord(1, 0), LongCoord(0, 1))
assertEquals(expectedAdjacentCorner, map.getAdjacentCoords(corner, includeDiagonal = false))

val expectedAdjacentCornerDiagonal = expectedAdjacentCorner + setOf(LongCoord(1, 1))
assertEquals(expectedAdjacentCornerDiagonal, map.getAdjacentCoords(corner, includeDiagonal = true))

val edge = LongCoord(2, 2)

val expectedAdjacentEdge = setOf(LongCoord(2, 1), LongCoord(1, 2), LongCoord(2, 3))
assertEquals(expectedAdjacentEdge, map.getAdjacentCoords(edge, includeDiagonal = false))

val expectedAdjacentEdgeDiagonal = expectedAdjacentEdge + setOf(LongCoord(1, 1), LongCoord(1, 3))
assertEquals(expectedAdjacentEdgeDiagonal, map.getAdjacentCoords(edge, includeDiagonal = true))

val middle = LongCoord(1, 1)

val expectedAdjacentMiddle = setOf(LongCoord(1, 0), LongCoord(2, 1), LongCoord(1, 2), LongCoord(0, 1))
assertEquals(expectedAdjacentMiddle, map.getAdjacentCoords(middle, includeDiagonal = false))

val expectedAdjacentMiddleDiagonal = expectedAdjacentMiddle + setOf(LongCoord(0, 0), LongCoord(2, 0), LongCoord(2, 2), LongCoord(0, 2))
assertEquals(expectedAdjacentMiddleDiagonal, map.getAdjacentCoords(middle, includeDiagonal = true))
}
}

0 comments on commit a04a93e

Please sign in to comment.