Day 10, a day late

This commit is contained in:
2019-12-12 01:04:34 +01:00
parent e6a0b2e1bd
commit fd474aa6fb
7 changed files with 162 additions and 19 deletions

View File

@@ -7,10 +7,10 @@ import java.util.stream.Stream
fun lines(resourceFile: String): Stream<String> {
val uri = Paths.get(Utils::class.java.getResource(resourceFile).toURI())
val env = mapOf(Pair("create", "true"))
FileSystems.newFileSystem(uri, env)
return Files.lines(uri)
val uri = Utils::class.java.getResource(resourceFile).toURI()
// val env = mapOf(Pair("create", "true"))
// FileSystems.newFileSystem(uri, env)
return Files.lines(Paths.get(uri))
}
fun line(resourceFile: String): String {

View File

@@ -1,33 +1,121 @@
const val DAY10_INPUT_PATH = "/day/10/input.txt"
package com.basdado.adventofcode.day10
import com.basdado.adventofcode.lines;
import java.util.stream.Collectors;
import com.basdado.adventofcode.lines
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() {
// 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.puzzle2()
Day10.puzzle2()
}
object Day10 {
fun puzzle1() {
println("Hello world!")
val rawData = lines(DAY10_INPUT_PATH).collect(Collectors.toList())
val asteroids =
(0..rawData.size).forEach { y ->
(0..rawData[y].length).forEach { x ->
if (rawData[y][x] == '#') {
}
}
}
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())
return (0 until rawData.size).flatMap { y ->
(rawData[y].indices)
.filter { x -> rawData[y][x] == '#' }
.map { x -> Vector2i(x, y) }
}
}
data class Vector2i(val x: Int, val y: Int) {
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
}
}

View File

@@ -0,0 +1,5 @@
.#....#####...#..
##...##.#####..##
##...#...#.#####.
..#.....X...###..
..#.#.....#....##

View File

@@ -0,0 +1,10 @@
......#.#.
#..#.#....
..#######.
.#.#.###..
.#..#.....
..#....#.#
#..#....#.
.##.#..###
##...#..#.
.#....####

View File

@@ -0,0 +1,10 @@
#.#...#.#.
.###....#.
.#....#...
##.#.#.#.#
....#.#.#.
.##..###.#
..#...##..
..##....##
......#...
.####.###.

View File

@@ -0,0 +1,10 @@
.#..#..###
####.###.#
....###.#.
..###.##.#
##.##.#.#.
....###..#
..#.#..#.#
#..#.#.###
.##...##.#
.....#.#..

View File

@@ -0,0 +1,20 @@
.#..##.###...#######
##.############..##.
.#.######.########.#
.###.#######.####.#.
#####.##.#.##.###.##
..#####..#.#########
####################
#.####....###.#.#.##
##.#################
#####.##.###..####..
..######..##.#######
####.##.####...##..#
.#####..#.######.###
##...#.##########...
#.##########.#######
.####.#.###.###.#.##
....##.##.###..#####
.#.#.###########.###
#.#.#.#####.####.###
###.##.####.##.#..##