109 lines
4.0 KiB
Kotlin
109 lines
4.0 KiB
Kotlin
import java.io.File
|
|
|
|
fun main(args: Array<String>) {
|
|
println("Hello day16!")
|
|
solve()
|
|
}
|
|
|
|
data class RuleRange(val min: Int, val max: Int)
|
|
data class Rule(val name: String, val ruleRangeFirst: RuleRange, val ruleRangeSecond: RuleRange)
|
|
|
|
val numbersRegex = Regex("\\d+")
|
|
|
|
fun readRules(ruleAsString: String): Rule {
|
|
val (ruleName, rest) = ruleAsString.split(":")
|
|
val ruleRanges = numbersRegex.findAll(rest)
|
|
.flatMap { match -> match.groupValues.map { it.toInt() } }
|
|
.chunked(2)
|
|
.map { pair -> RuleRange(pair[0], pair[1]) }
|
|
.toList()
|
|
|
|
return Rule(ruleName, ruleRanges[0], ruleRanges[1])
|
|
}
|
|
|
|
fun checkRuleRange(v: Int, ruleRange: RuleRange): Boolean = v >= ruleRange.min && v <= ruleRange.max
|
|
|
|
fun errorRateIfViolated(v: Int, rules: List<Rule>): Long {
|
|
if (rules.any { rule -> checkRuleRange(v, rule.ruleRangeFirst) || checkRuleRange(v, rule.ruleRangeSecond) }) {
|
|
return 0
|
|
}
|
|
return v.toLong()
|
|
}
|
|
|
|
fun sumErrorRateOfViolations(ticket: String, rules: List<Rule>): Long =
|
|
ticket.split(",")
|
|
.map { it.toInt() }
|
|
.map { errorRateIfViolated(it, rules) }
|
|
.sum()
|
|
|
|
fun isValidValue(v: Int, rules: List<Rule>): Boolean =
|
|
rules.any { rule -> checkRuleRange(v, rule.ruleRangeFirst) || checkRuleRange(v, rule.ruleRangeSecond) }
|
|
|
|
fun isValidTicket(ticket: String, rules: List<Rule>): Boolean =
|
|
ticket.split(",")
|
|
.map { it.toInt() }
|
|
.all { isValidValue(it, rules) }
|
|
|
|
fun isRuleValidFor(rule: Rule, values: List<Int>): Boolean = values.all { v -> checkRuleRange(v, rule.ruleRangeFirst) || checkRuleRange(v, rule.ruleRangeSecond) }
|
|
|
|
fun valuesForColumn(ticketValues: List<List<Int>>, col: Int) = ticketValues.map { it[col] }
|
|
|
|
fun rulesPerColumn(ticketValues: List<List<Int>>, rules: List<Rule>): MutableMap<Rule, MutableSet<Int>> {
|
|
val ruleValidForColumn = mutableMapOf<Rule, MutableSet<Int>>()
|
|
for (i in ticketValues[0].indices) {
|
|
val columnValues = valuesForColumn(ticketValues, i)
|
|
for (rule in rules) {
|
|
if (isRuleValidFor(rule, columnValues)) {
|
|
if (!ruleValidForColumn.containsKey(rule)) {
|
|
ruleValidForColumn[rule] = mutableSetOf()
|
|
}
|
|
ruleValidForColumn[rule]?.add(i)
|
|
}
|
|
}
|
|
}
|
|
|
|
return ruleValidForColumn
|
|
}
|
|
|
|
fun ruleToColumnAssignment(validRulesPerColumns: MutableMap<Rule, MutableSet<Int>>): Map<Rule, Int> {
|
|
val rulePerColumnAssignment = mutableMapOf<Rule, Int>()
|
|
while (validRulesPerColumns.isNotEmpty()) {
|
|
val currentAssignment = validRulesPerColumns.asSequence().filter { it.value.size == 1 }.first()
|
|
val column = currentAssignment.value.first()
|
|
rulePerColumnAssignment[currentAssignment.key] = column
|
|
|
|
validRulesPerColumns.remove(currentAssignment.key)
|
|
for (validRulPerColumns in validRulesPerColumns) {
|
|
validRulPerColumns.value.remove(column)
|
|
}
|
|
}
|
|
|
|
return rulePerColumnAssignment
|
|
}
|
|
|
|
fun solve() {
|
|
val readLines = File("day16/input").readText();
|
|
val (ruleText, ticketWithLabel, nearbyWithLabel) = readLines.split("\n\n")
|
|
val ticket = ticketWithLabel.split("\n")[1]
|
|
val nearby = nearbyWithLabel.split("\n").drop(1).filter { it.isNotEmpty() }
|
|
|
|
val rules = ruleText.split("\n").filter { it.isNotEmpty() }.map { readRules(it) }
|
|
|
|
val errorRate = nearby.map { sumErrorRateOfViolations(it, rules) }.sum()
|
|
println(errorRate)
|
|
|
|
// part 2
|
|
val nearbyValidTickets = nearby.filter { isValidTicket(it, rules) }
|
|
|
|
val nearbyTicketValues = nearbyValidTickets.map { t -> t.split(",").map { it.toInt() } }
|
|
|
|
val validRulesPerColumns = rulesPerColumn(nearbyTicketValues, rules)
|
|
|
|
val ruleToColumnAssignment = ruleToColumnAssignment(validRulesPerColumns)
|
|
|
|
val ticketValues = ticket.split(",").map { it.toLong() }
|
|
|
|
val departureProduct = ruleToColumnAssignment.entries.filter { it.key.name.startsWith("departure") }.map { ticketValues[it.value] }.reduce { acc, i -> acc * i }
|
|
|
|
println(departureProduct)
|
|
} |