DEV Community

Discussion on: AoC Day 6: Chronal Coordinates

Collapse
 
jbristow profile image
Jon Bristow • Edited

Kotlin Solution

Part 1

This one wasn't too bad. I had a false start trying to flood-fill with multiple generators, and that got silly really quickly.

Then I realized I could just build a big array, chunk through item by item, remove any symbol on an edge, and then just count the places they reached.

fun String.parsePoint() = this.split(""", """).let { found ->
    Point(found[0].toInt(), found[1].toInt())
}

fun Point.manhattanDistance(b: Point): Int =
    (x - b.x).absoluteValue + (y - b.y).absoluteValue

val alpha = ('a'..'z') + ('A'..'Z')

fun answer1(input: List<Point>): Int? {
    val minX = input.minBy { (x, y) -> x }!!.x
    val minY = input.minBy { (x, y) -> y }!!.y
    val maxX = input.maxBy { (x, y) -> x }!!.x
    val maxY = input.maxBy { (x, y) -> y }!!.y

    val map = input.mapIndexed { i, point ->
        point to alpha[i].toString()
    }.toMap().toMutableMap()

    val output =
        (minY..maxY).map { y ->
            (minX..maxX).map { x ->
                map.toList().groupBy { (k, _) ->
                    (x to y).manhattanDistance(k)
                }.minByKey()!!.value.let { closest ->
                    when {
                        closest.count() > 1 -> "."
                        else -> closest.first().second
                    }
                }
            }
        }

    return map.values.filter { v ->
        v !in output.first()
                && v !in output.map { it.first() }
                && v !in output.last()
                && v !in output.map { it.last() }
    }.map { v ->
        output.flatten().count { it == v }
    }.max()
}

Part 2

This is where I got stuck a bit trying to optimize instead of just letting it finish this code's 30 second cycle.

I'm not happy I couldn't figure out the math, but I'll post some pictures I've generated from my output in penance.

fun answer2(input: List<Point>): Int? {
    val dist = 10000

    val minX = input.minBy { (x, y) -> x }!!.x
    val minY = input.minBy { (x, y) -> y }!!.y
    val maxX = input.maxBy { (x, y) -> x }!!.x
    val maxY = input.maxBy { (x, y) -> y }!!.y

    val ptc =
        (maxX - dist..minX + dist).map { x ->
            println("row $x")
            (maxY - dist..minY + dist).map { y ->
                x to y
            }
                .filter { point -> input.sumBy(point::manhattanDistance) < dist }
        }.fold(emptySet<Point>()) { a, b ->
            a + b
        }

    return ptc.count()
}
Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

You don't have to construct an array; you can just iterate over min(x)..max(x) and min(y)..max(y) and add + to the nearest input point.

Collapse
 
jbristow profile image
Jon Bristow • Edited

The promised images!

Sample Data

Part 1 - Answer
Part 1 - Answer

Part 2 - Answer
Part 2 - Answer

Answers

Part 1 - Answer
Part 1 - Answer

Part 2 - Answer
Part 2 - Answer

Annnnnd, by posting these pictures, I see that the optimization for part 2 is to bound yourself by the points. 10000 is a bit of a red herring.

EDIT: 2018-12-06T11:01:40-08:00
Found some problems with my image processing and fixed them.