1
0

Optimize part2 + benchmark

This commit is contained in:
2020-12-16 11:09:55 +01:00
parent edce14cd40
commit 5ffebae101
2 changed files with 104 additions and 40 deletions
+65 -40
View File
@@ -4,8 +4,9 @@ import be.vandewalleh.aoc.utils.input.Day
import be.vandewalleh.aoc.utils.input.Groups
import be.vandewalleh.aoc.utils.input.Input
import be.vandewalleh.aoc.utils.input.createDay
import org.eclipse.collections.api.multimap.list.MutableListMultimap
import org.eclipse.collections.api.multimap.set.MutableSetMultimap
import org.eclipse.collections.impl.factory.Multimaps
import org.eclipse.collections.impl.factory.primitive.IntSets
@Day(16)
class Day16(@Groups val input: Input<List<List<String>>>) {
@@ -42,7 +43,7 @@ class Day16(@Groups val input: Input<List<List<String>>>) {
return invalid.sum()
}
private fun isTicketValid(ticket: List<Int>, ranges: List<IntRange>): Boolean {
private fun isTicketValid(ticket: List<Int>, ranges: Iterable<IntRange>): Boolean {
for (number in ticket) {
if (!ranges.any { number in it }) return false
}
@@ -52,26 +53,59 @@ class Day16(@Groups val input: Input<List<List<String>>>) {
private fun inRanges(value: Int, ranges: List<IntRange>) = ranges.any { value in it }
fun part2(): Long {
val minMax = Multimaps.mutable.list.empty<String, IntRange>()
val rangesByName = namedRanges()
val validTickets = validTickets(rangesByName)
val indexesByCategory = indexesByCategory(rangesByName, validTickets)
for (line in rangesGroup) {
val name = line.substringBefore(":")
extractRanges(line).forEach {
minMax.put(name, it)
removeDuplicates(indexesByCategory)
val myTicketValues = myTicket.split(",").map { it.toInt() }
var mult = 1L
indexesByCategory.forEachKeyValue { category, index ->
if (category.startsWith("departure")) {
mult *= myTicketValues[index]
}
}
val validTickets = mutableListOf<List<Int>>()
for (line in nearbyTicketsGroup) {
val ticket = line.splitToSequence(",").map { it.toInt() }.toList()
if (isTicketValid(ticket, minMax.valuesView().toList())) {
validTickets.add(ticket)
return mult
}
private fun removeDuplicates(indexesByCategory: MutableSetMultimap<String, Int>) {
val toBeRemoved = HashSet<Int>()
val queue = ArrayDeque<Int>()
indexesByCategory.multiValuesView()
.sortedBy { it.size() }
.forEach { it.forEach { if (toBeRemoved.add(it)) queue.add(it) } }
queue.removeLast()
val categoriesToRemove = mutableListOf<String>()
while (queue.isNotEmpty()) {
val duplicate = queue.removeFirst()
categoriesToRemove.clear()
for (entry in indexesByCategory.keyMultiValuePairsView()) {
if (entry.two.size() < 2) continue
categoriesToRemove.add(entry.one)
}
for (category in categoriesToRemove) {
indexesByCategory.remove(category, duplicate)
}
}
}
val indexesByCategory = Multimaps.mutable.list.empty<String, Int>()
private fun indexesByCategory(
rangesByName: MutableListMultimap<String, IntRange>,
validTickets: MutableList<List<Int>>,
): MutableSetMultimap<String, Int> {
val indexesByCategory = Multimaps.mutable.set.empty<String, Int>()
for (entry in minMax.keyMultiValuePairsView()) {
for (entry in rangesByName.keyMultiValuePairsView()) {
val category = entry.one
val ranges = entry.two.toList()
@@ -83,38 +117,29 @@ class Day16(@Groups val input: Input<List<List<String>>>) {
if (allInRange) indexesByCategory.put(category, i)
}
}
return indexesByCategory
}
val removed = IntSets.mutable.empty()
while (!indexesByCategory.multiValuesView().all { it.size() == 1 }) {
val values = indexesByCategory.multiValuesView()
val categoriesToRemove = mutableListOf<String>()
val one = values.filter { it.size() == 1 }
.map { it.first() }
.find { removed.add(it) }
?: error("No values left to remove")
for (entry in indexesByCategory.keyMultiValuePairsView()) {
val values = entry.two
if (values.size() < 2) continue
val category = entry.one
if (values.find { it == one } != null) categoriesToRemove.add(category)
}
for (category in categoriesToRemove) {
indexesByCategory.remove(category, one)
private fun validTickets(rangesByName: MutableListMultimap<String, IntRange>): MutableList<List<Int>> {
val validTickets = mutableListOf<List<Int>>()
for (line in nearbyTicketsGroup) {
val ticket = line.splitToSequence(",").map { it.toInt() }.toList()
if (isTicketValid(ticket, rangesByName.valuesView().toList())) {
validTickets.add(ticket)
}
}
val myTicketValues = myTicket.split(",").map { it.toInt() }
var mult = 1L
return validTickets
}
indexesByCategory.forEachKeyValue { category, index ->
if (category.startsWith("departure")) {
mult *= myTicketValues[index]
private fun namedRanges(): MutableListMultimap<String, IntRange> {
val rangesByName = Multimaps.mutable.list.empty<String, IntRange>()
for (line in rangesGroup) {
val name = line.substringBefore(":")
extractRanges(line).forEach {
rangesByName.put(name, it)
}
}
return mult
return rangesByName
}
}