Zatímco 4. den byl docela masakr, kde mě totálně vypekla knihovna JodaTime – z nějakého důvodu převedla javovský Date špatně, 5. už byl o něco lepší, nicméně výkonnostně nic moc 🙂 (chtělo by to optimalizovat na úkor čitelnosti).
Den 4., AB:
import com.svetylkovo.rojo.Rojo
import com.svetylkovo.rojo.annotations.Group
import com.svetylkovo.rojo.annotations.Regex
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import java.io.File
@Regex("\\[(.+)\\] (.+)")
class Record {
@Group(1)
var dateString = ""
@Group(2)
var content = ""
}
class Guard(val id: Int) {
val sleepMinutes = mutableListOf<Int>()
fun maxTimeSpentOnSameMinute() = sleepMinutes.groupBy { it }
.mapValues { it.value.count() }
.maxBy { it.value }
?.value ?: 0
fun mostFrequentMinute(): Int = sleepMinutes.groupBy { it }
.mapValues { it.value.count() }
.maxBy { it.value }
?.key ?: 0
}
fun parseDate(input: String) = DateTime.parse(input, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"))
fun main() {
val idMatcher = Rojo.matcher("#(\\d+)")
val guardsMap = mutableMapOf<Int, Guard>()
val input = File("input4.txt").readText()
val records = Rojo.of(Record::class.java)
.matchList(input)
.sortedBy { it.dateString }
var guard: Guard? = null
var sleepTime: DateTime? = null
var wakeTime: DateTime? = null
for (record in records) {
val content = record.content
when {
"sleep" in content -> sleepTime = parseDate(record.dateString)
"wake" in content -> wakeTime = parseDate(record.dateString)
else -> idMatcher.firstGroup(content)
.findFirst()
.ifPresent {
val id = it.toInt()
guard = guardsMap.computeIfAbsent(id) { Guard(id) }
}
}
val safeSleepTime = sleepTime
val safeWakeTime = wakeTime
guard?.let {
if (safeSleepTime != null && safeWakeTime != null) {
it.sleepMinutes += (safeSleepTime to safeWakeTime).getSleepMinutes()
sleepTime = null
wakeTime = null
}
}
}
val allGuards = guardsMap.values
val mostSleepingGuard = allGuards.maxBy { it.sleepMinutes.size }
mostSleepingGuard?.let {
val mostFrequentMinute = it.mostFrequentMinute()
println(it.id * mostFrequentMinute)
val mostSleepingAtMinute = allGuards.maxBy { it.maxTimeSpentOnSameMinute() }
mostSleepingAtMinute?.let {
println(it.id * it.mostFrequentMinute())
}
}
}
private fun Pair<DateTime, DateTime>.getSleepMinutes(): List<Int> {
var sleepTime = first
return sequence {
while (sleepTime.isBefore(second)) {
yield(sleepTime.minuteOfHour)
sleepTime = sleepTime.plusMinutes(1)
}
}.toList()
}
Den 5., AB:
import java.io.File
fun main() {
val polymer = File("input5.txt").readText().trim()
//part A
val reducedPolymer = getReducedPolymer(polymer)
println(reducedPolymer.length)
//part B
val shortestLength = ('a'..'z').map {
val shorterPolymer = polymer.replace(Regex("[$it${it.toUpperCase()}]"),"")
getReducedPolymer(shorterPolymer).length
}.min()
println(shortestLength)
}
tailrec fun getReducedPolymer(polymer: String): String {
val pairToRemove = polymer.windowed(2, 1) {
it.toString()
}.firstOrNull { it.doesReact() }
if (pairToRemove != null) {
val reducedPolymer = polymer.replaceFirst(pairToRemove, "")
return getReducedPolymer(reducedPolymer)
}
return polymer
}
private fun String.doesReact(): Boolean {
val upper = toUpperCase()
return this[0] != this[1] && upper[0] == upper[1]
}