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] }