Day 8: Resonant Collinearity
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
You are viewing a single thread.
View all comments 1 point
Kotlin
A bit late to the party, but here’s my solution. I don’t know, if you even need to search for the smallest integer vector in the same direction in part 2, but I did it anyway.
Code:
import kotlin.math.abs
import kotlin.math.pow
fun main() {
fun part1(input: List<String>): Int {
val inputMap = Day08Map(input)
return inputMap.isoFrequencyNodeVectorsByLocations
.flatMap { (location, vectors) ->
vectors.map { (2.0 scaleVec it) + location }
}
.toSet()
.count { inputMap.isInGrid(it) }
}
fun part2(input: List<String>): Int {
val inputMap = Day08Map(input)
return buildSet {
inputMap.isoFrequencyNodeVectorsByLocations.forEach { (location, vectors) ->
vectors.forEach { vector ->
var i = 0.0
val scaledDownVector = smallestIntegerVectorInSameDirection2D(vector)
while (inputMap.isInGrid(location + (i scaleVec scaledDownVector))) {
add(location + (i scaleVec scaledDownVector))
i++
}
}
}
}.count()
}
val testInput = readInput("Day08_test")
check(part1(testInput) == 14)
check(part2(testInput) == 34)
val input = readInput("Day08")
part1(input).println()
part2(input).println()
}
tailrec fun gcdEuclid(a: Int, b: Int): Int =
if (b == 0) a
else if (a == 0) b
else if (a > b) gcdEuclid(a - b, b)
else gcdEuclid(a, b - a)
fun smallestIntegerVectorInSameDirection2D(vec: VecNReal): VecNReal {
assert(vec.dimension == 2) // Only works in two dimensions.
assert(vec == vec.roundComponents()) // Only works on integer vectors.
return (gcdEuclid(abs(vec[0].toInt()), abs(vec[1].toInt())).toDouble().pow(-1) scaleVec vec).roundComponents()
}
class Day08Map(input: List<String>): Grid2D<Char>(input.reversed().map { it.toList() }) {
init {
transpose()
}
val isoFrequencyNodesLocations = asIterable().toSet().filter { it != '.' }.map { frequency -> asIterable().indicesWhere { frequency == it } }
val isoFrequencyNodeVectorsByLocations = buildMap {
isoFrequencyNodesLocations.forEach { isoFrequencyLocationList ->
isoFrequencyLocationList.mapIndexed { index, nodeLocation ->
this[VecNReal(nodeLocation)] = isoFrequencyLocationList
.slice((0 until index) + ((index + 1)..isoFrequencyLocationList.lastIndex))
.map { VecNReal(it) - VecNReal(nodeLocation) }
}
}
}
}