Day 10, a day late
This commit is contained in:
@@ -7,10 +7,10 @@ import java.util.stream.Stream
|
|||||||
|
|
||||||
fun lines(resourceFile: String): Stream<String> {
|
fun lines(resourceFile: String): Stream<String> {
|
||||||
|
|
||||||
val uri = Paths.get(Utils::class.java.getResource(resourceFile).toURI())
|
val uri = Utils::class.java.getResource(resourceFile).toURI()
|
||||||
val env = mapOf(Pair("create", "true"))
|
// val env = mapOf(Pair("create", "true"))
|
||||||
FileSystems.newFileSystem(uri, env)
|
// FileSystems.newFileSystem(uri, env)
|
||||||
return Files.lines(uri)
|
return Files.lines(Paths.get(uri))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun line(resourceFile: String): String {
|
fun line(resourceFile: String): String {
|
||||||
|
|||||||
@@ -1,33 +1,121 @@
|
|||||||
const val DAY10_INPUT_PATH = "/day/10/input.txt"
|
package com.basdado.adventofcode.day10
|
||||||
|
|
||||||
import com.basdado.adventofcode.lines;
|
import com.basdado.adventofcode.lines
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors
|
||||||
|
import kotlin.math.PI
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.atan2
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
const val DAY10_INPUT_PATH = "/day/10/input.txt"
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
|
||||||
|
// val circle = listOf(
|
||||||
|
// Day10.Vector2i(0, 1),
|
||||||
|
// Day10.Vector2i(1, 1),
|
||||||
|
// Day10.Vector2i(1, 0),
|
||||||
|
// Day10.Vector2i(0, -1),
|
||||||
|
// Day10.Vector2i(-1, -1),
|
||||||
|
// Day10.Vector2i(-1, 0),
|
||||||
|
// Day10.Vector2i(-1, 1)
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// circle.map {
|
||||||
|
// - (it.angle() + 0.5 * PI)
|
||||||
|
// }.map { if (it < 0) it + 2 * PI else it }.forEach(::println)
|
||||||
|
|
||||||
|
// println(Day10.Vector2i(5, 2).angle())
|
||||||
|
|
||||||
Day10.puzzle1()
|
Day10.puzzle1()
|
||||||
// Day10.puzzle2()
|
Day10.puzzle2()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Day10 {
|
object Day10 {
|
||||||
|
|
||||||
fun puzzle1() {
|
fun puzzle1() {
|
||||||
println("Hello world!")
|
val asteroids = loadAsteroids()
|
||||||
|
println(optimalAsteroidsPerDirection(asteroids).second.size)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun puzzle2() {
|
||||||
|
val asteroids = loadAsteroids()
|
||||||
|
val optimalAsteroid = optimalAsteroidsPerDirection(asteroids)
|
||||||
|
// val optimalAsteroid = Pair(Vector2i(8, 3), asteroidsPerDirection(Vector2i(8, 3), asteroids))
|
||||||
|
// println(optimalAsteroid.first)
|
||||||
|
// optimalAsteroid.second.keys.forEach {
|
||||||
|
// var angle = (it.angle() + 0.5 * PI);
|
||||||
|
// angle = if (angle < 0) 2*PI + angle else angle
|
||||||
|
// println("(${it.x}, ${it.y}) = $angle")
|
||||||
|
// }
|
||||||
|
val sortedAsteroidLists = optimalAsteroid.second
|
||||||
|
.entries
|
||||||
|
.sortedBy { val angle = (it.key.angle() + 0.5 * PI); if (angle < 0) 2*PI + angle else angle }
|
||||||
|
.map { it.value.sortedBy( Vector2i::manhattan ) }
|
||||||
|
// And now we're gonna keep taking one of each list until we reach number 200
|
||||||
|
var listIndex = 0
|
||||||
|
var itemIndexPerList = IntArray(sortedAsteroidLists.size)
|
||||||
|
var i = 0
|
||||||
|
var curItem: Vector2i? = null
|
||||||
|
while (i < 200) {
|
||||||
|
val list = sortedAsteroidLists[listIndex]
|
||||||
|
if (itemIndexPerList[listIndex] < list.size) {
|
||||||
|
curItem = list[itemIndexPerList[listIndex]]
|
||||||
|
// println(optimalAsteroid.first + curItem)
|
||||||
|
itemIndexPerList[listIndex]++
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
listIndex++
|
||||||
|
}
|
||||||
|
val asteroid200 = optimalAsteroid.first + curItem!!
|
||||||
|
println(asteroid200.x * 100 + asteroid200.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun optimalAsteroidsPerDirection(asteroids: List<Vector2i>): Pair<Vector2i, Map<Vector2i, List<Vector2i>>> {
|
||||||
|
return asteroids.map { Pair(it, asteroidsPerDirection(it, asteroids)) }.maxBy { it.second.size }!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun asteroidsPerDirection(asteroid: Vector2i, asteroids: List<Vector2i>): Map<Vector2i, List<Vector2i>> {
|
||||||
|
return asteroids
|
||||||
|
.filter { it != asteroid }
|
||||||
|
.map { it - asteroid }
|
||||||
|
.groupBy { it.normalize() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadAsteroids(): List<Vector2i> {
|
||||||
val rawData = lines(DAY10_INPUT_PATH).collect(Collectors.toList())
|
val rawData = lines(DAY10_INPUT_PATH).collect(Collectors.toList())
|
||||||
val asteroids =
|
return (0 until rawData.size).flatMap { y ->
|
||||||
(0..rawData.size).forEach { y ->
|
(rawData[y].indices)
|
||||||
(0..rawData[y].length).forEach { x ->
|
.filter { x -> rawData[y][x] == '#' }
|
||||||
if (rawData[y][x] == '#') {
|
.map { x -> Vector2i(x, y) }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Vector2i(val x: Int, val y: Int) {
|
data class Vector2i(val x: Int, val y: Int) {
|
||||||
fun normalize(): Vector2i {
|
|
||||||
|
|
||||||
|
fun normalize(): Vector2i {
|
||||||
|
return this / gcd(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun angle() = atan2(y.toDouble(), x.toDouble())
|
||||||
|
fun manhattan() = abs(x) + abs(y)
|
||||||
|
|
||||||
|
operator fun div(d: Int) = Vector2i(x / d, y / d)
|
||||||
|
operator fun minus(n: Int) = Vector2i(x - n, y - n)
|
||||||
|
operator fun minus(v: Vector2i) = Vector2i(x - v.x, y - v.y)
|
||||||
|
operator fun plus(n: Int) = Vector2i(x + n, y + n)
|
||||||
|
operator fun plus(v: Vector2i) = Vector2i(x + v.x, y + v.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
val ORIGIN = Vector2i(0, 0)
|
||||||
|
|
||||||
|
fun gcd(n1: Int, n2: Int) = when {
|
||||||
|
n1 == 0 && n2 == 0 -> 1 // Actually undefined/any number, but whatever
|
||||||
|
n1 == 0 -> abs(n2)
|
||||||
|
n2 == 0 -> abs(n1)
|
||||||
|
else -> (1..(min(abs(n1), abs(n2))))
|
||||||
|
.filter { n1 % it == 0 && n2 % it == 0 }
|
||||||
|
.max() ?: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
5
src/main/resources/day/10/ex0.txt
Normal file
5
src/main/resources/day/10/ex0.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.#....#####...#..
|
||||||
|
##...##.#####..##
|
||||||
|
##...#...#.#####.
|
||||||
|
..#.....X...###..
|
||||||
|
..#.#.....#....##
|
||||||
10
src/main/resources/day/10/ex1.txt
Normal file
10
src/main/resources/day/10/ex1.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
......#.#.
|
||||||
|
#..#.#....
|
||||||
|
..#######.
|
||||||
|
.#.#.###..
|
||||||
|
.#..#.....
|
||||||
|
..#....#.#
|
||||||
|
#..#....#.
|
||||||
|
.##.#..###
|
||||||
|
##...#..#.
|
||||||
|
.#....####
|
||||||
10
src/main/resources/day/10/ex2.txt
Normal file
10
src/main/resources/day/10/ex2.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#.#...#.#.
|
||||||
|
.###....#.
|
||||||
|
.#....#...
|
||||||
|
##.#.#.#.#
|
||||||
|
....#.#.#.
|
||||||
|
.##..###.#
|
||||||
|
..#...##..
|
||||||
|
..##....##
|
||||||
|
......#...
|
||||||
|
.####.###.
|
||||||
10
src/main/resources/day/10/ex3.txt
Normal file
10
src/main/resources/day/10/ex3.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.#..#..###
|
||||||
|
####.###.#
|
||||||
|
....###.#.
|
||||||
|
..###.##.#
|
||||||
|
##.##.#.#.
|
||||||
|
....###..#
|
||||||
|
..#.#..#.#
|
||||||
|
#..#.#.###
|
||||||
|
.##...##.#
|
||||||
|
.....#.#..
|
||||||
20
src/main/resources/day/10/ex4.txt
Normal file
20
src/main/resources/day/10/ex4.txt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
.#..##.###...#######
|
||||||
|
##.############..##.
|
||||||
|
.#.######.########.#
|
||||||
|
.###.#######.####.#.
|
||||||
|
#####.##.#.##.###.##
|
||||||
|
..#####..#.#########
|
||||||
|
####################
|
||||||
|
#.####....###.#.#.##
|
||||||
|
##.#################
|
||||||
|
#####.##.###..####..
|
||||||
|
..######..##.#######
|
||||||
|
####.##.####...##..#
|
||||||
|
.#####..#.######.###
|
||||||
|
##...#.##########...
|
||||||
|
#.##########.#######
|
||||||
|
.####.#.###.###.#.##
|
||||||
|
....##.##.###..#####
|
||||||
|
.#.#.###########.###
|
||||||
|
#.#.#.#####.####.###
|
||||||
|
###.##.####.##.#..##
|
||||||
Reference in New Issue
Block a user