day16
This commit is contained in:
parent
68938c4eed
commit
705e05fbab
|
|
@ -0,0 +1,109 @@
|
|||
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)
|
||||
}
|
||||
Loading…
Reference in New Issue