mirror of
https://github.com/chylex/Advent-of-Code.git
synced 2025-05-25 00:34:06 +02:00
Add 2021 - Day 5 - Part 2
This commit is contained in:
parent
5ad19b6979
commit
07287a648d
@ -1,38 +1,62 @@
|
||||
import java.io.File
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
fun main() {
|
||||
val lineRegex = Regex("^(\\d+),(\\d+) -> (\\d+),(\\d+)$")
|
||||
val lines = File("input/1.txt").readLines()
|
||||
.mapNotNull(lineRegex::matchEntire)
|
||||
.map { it.groupValues.takeLast(4).map(String::toInt) }
|
||||
.map { Line.of(it[0], it[1], it[2], it[3]) }
|
||||
.map { Line(it[0], it[1], it[2], it[3]) }
|
||||
|
||||
val straightLines = lines.filter(Line::isStraight)
|
||||
val straightLineFloor = Floor(straightLines)
|
||||
|
||||
println("Points where at least 2 straight lines overlap: ${straightLineFloor.countPointsWithOverlap(2)}")
|
||||
println("(Took ${measureTimeMillis { part1(lines) }} ms)")
|
||||
println("(Took ${measureTimeMillis { part2(lines) }} ms)")
|
||||
}
|
||||
|
||||
@Suppress("ProtectedInFinal")
|
||||
data class Line protected constructor(val x1: Int, val y1: Int, val x2: Int, val y2: Int) {
|
||||
companion object {
|
||||
fun of(x1: Int, y1: Int, x2: Int, y2: Int): Line {
|
||||
return Line(min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2))
|
||||
}
|
||||
@Suppress("ProtectedInFinal", "MemberVisibilityCanBePrivate")
|
||||
data class Line(val x1: Int, val y1: Int, val x2: Int, val y2: Int) {
|
||||
val minX = min(x1, x2)
|
||||
val minY = min(y1, y2)
|
||||
val maxX = max(x1, x2)
|
||||
val maxY = max(y1, y2)
|
||||
|
||||
init {
|
||||
require(isStraight || is45Degrees) { "Line must be straight or have a slope of 45 degrees!" }
|
||||
}
|
||||
|
||||
val isStraight
|
||||
get() = x1 == x2 || y1 == y2
|
||||
|
||||
val is45Degrees
|
||||
get() = abs(x2 - x1) == abs(y2 - y1)
|
||||
|
||||
val length = 1 + max(abs(x2 - x1), abs(y2 - y1))
|
||||
|
||||
private val slopeX = Integer.signum(x2 - x1)
|
||||
private val slopeY = Integer.signum(y2 - y1)
|
||||
|
||||
fun contains(x: Int, y: Int): Boolean {
|
||||
return if (x1 == x2)
|
||||
x == x1 && y in y1..y2
|
||||
else if (y1 == y2)
|
||||
y == y1 && x in x1..x2
|
||||
else
|
||||
throw UnsupportedOperationException()
|
||||
if (x1 == x2) {
|
||||
return x == x1 && y in minY..maxY
|
||||
}
|
||||
|
||||
if (y1 == y2) {
|
||||
return y == y1 && x in minX..maxX
|
||||
}
|
||||
|
||||
if (x !in minX..maxX || y !in minY..maxY) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (i in 0 until length) {
|
||||
if (x == x1 + (slopeX * i) && y == y1 + (slopeY * i)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,13 +67,22 @@ class Floor(private val lines: List<Line>) {
|
||||
private val maxY = lines.maxOf { max(it.y1, it.y2) }
|
||||
|
||||
fun countPointsWithOverlap(minOverlap: Int): Int {
|
||||
val xs = minX..maxX
|
||||
val xs = minX..maxY
|
||||
val ys = minY..maxY
|
||||
return xs.sumOf { x ->
|
||||
ys.count { y ->
|
||||
lines.count { it.contains(x, y) } >= minOverlap
|
||||
val xy = xs.flatMap { x -> ys.map { y -> x to y } }
|
||||
return xy.parallelStream().filter { (x, y) -> hasOverlapOf(x, y, minOverlap) }.count().toInt()
|
||||
}
|
||||
|
||||
private fun hasOverlapOf(x: Int, y: Int, minOverlap: Int): Boolean {
|
||||
var count = 0
|
||||
|
||||
for (line in lines) {
|
||||
if (line.contains(x, y) && ++count >= minOverlap) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@ -69,3 +102,14 @@ class Floor(private val lines: List<Line>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun part1(lines: List<Line>) {
|
||||
val straightLines = lines.filter(Line::isStraight).ifEmpty { return }
|
||||
val straightLineFloor = Floor(straightLines)
|
||||
println("Points where at least 2 straight lines overlap: ${straightLineFloor.countPointsWithOverlap(2)}")
|
||||
}
|
||||
|
||||
fun part2(lines: List<Line>) {
|
||||
val floor = Floor(lines)
|
||||
println("Points where at least 2 lines overlap: ${floor.countPointsWithOverlap(2)}")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user