Další z ne-úplně lehkých dnů. Nyní již bylo zapotřebí trochy odhadu a víry, že se člověk vydal správnou cestou 🙂 .
import com.svetylkovo.rojo.Rojo
import com.svetylkovo.rojo.annotations.Group
import com.svetylkovo.rojo.annotations.Regex
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.OutputStream
@Regex("(-?\\d+).+?(-?\\d+).+?(-?\\d+).+?(-?\\d+)")
data class Star(
@Group(1)
var x: Long = 0,
@Group(2)
var y: Long = 0,
@Group(3)
var vx: Int = 0,
@Group(4)
var vy: Int = 0
) {
/**
* Direction can be either 1 (forward movement) or -1 (backward movement)
*/
fun move(direction: Int) {
x += vx * direction
y += vy * direction
}
}
class NightSky(val stars: List<Star>) {
var width: Long = 0
var height: Long = 0
val size get() = width * height
private fun transposeStarsToTopLeft() {
val xOffset = stars.asSequence()
.map { it.x }
.min()
?.times(-1) ?: 0
val yOffset = stars.asSequence()
.map { it.y }
.min()
?.times(-1) ?: 0
stars.forEach {
it.x += xOffset
it.y += yOffset
}
width = stars.maxBy { it.x }?.x ?: 1
height = stars.maxBy { it.y }?.y ?: 1
}
fun moveTheStars(direction: Int = 1) {
if (direction == 1) {
transposeStarsToTopLeft()
stars.forEach { it.move(direction) }
} else {
stars.forEach { it.move(direction) }
transposeStarsToTopLeft()
}
}
fun writeSkyState(out: OutputStream) {
val writer = out.writer()
val newline = "\n"
val star = "#"
val emptyness = "."
val starsPosition = stars.asSequence()
.map { it.x to it.y }
.toHashSet()
for (y in 0..height) {
for (x in 0..width) {
if (x to y in starsPosition) writer.write(star)
else writer.write(emptyness)
}
writer.write(newline)
writer.flush()
}
writer.flush()
}
fun getSkyStateAsString(): String {
val out = ByteArrayOutputStream()
writeSkyState(out)
return out.toString()
}
}
fun main() {
val input = File("input10.txt").readText()
val outDir = File("output10").apply { mkdir() }
val stars = Rojo.of(Star::class.java).matchList(input)
val nightSky = NightSky(stars)
var lastSize = Long.MAX_VALUE
//A
println("Searching for minimal step")
var minimalStepNumeber = 0
for (step in 1..20000) {
minimalStepNumeber = step
nightSky.moveTheStars()
if (nightSky.size > lastSize) break
else lastSize = nightSky.size
}
repeat(5) { step ->
println("Generating step $step")
outDir.resolve("Out$step.txt")
.outputStream()
.use { nightSky.writeSkyState(it) }
nightSky.moveTheStars(-1)
}
println("Done, let's investigate the files output!")
//B
println("They would have to wait ${minimalStepNumeber - 2} seconds")
}