1
0

Parallelize solutions + benchmarks

This commit is contained in:
Hubert Van De Walle 2020-12-18 13:55:19 +01:00
parent 83b5a09e73
commit 0f2098634b
3 changed files with 74 additions and 15 deletions

View File

@ -11,6 +11,9 @@ dependencies {
implementation(Libs.Micronaut.kotlin) implementation(Libs.Micronaut.kotlin)
kapt(Libs.Micronaut.processor) kapt(Libs.Micronaut.processor)
implementation(Libs.Slf4J.api)
runtimeOnly(Libs.Slf4J.simple)
implementation(Libs.eclipseCollections) { implementation(Libs.eclipseCollections) {
because("Primitive collections mostly") because("Primitive collections mostly")
} }

View File

@ -5,6 +5,8 @@ import be.vandewalleh.aoc.utils.input.Input
import be.vandewalleh.aoc.utils.input.Lines import be.vandewalleh.aoc.utils.input.Lines
import be.vandewalleh.aoc.utils.input.createDay import be.vandewalleh.aoc.utils.input.createDay
import java.util.* import java.util.*
import org.slf4j.Logger
import org.slf4j.LoggerFactory
enum class Operator { Add, Multiply } enum class Operator { Add, Multiply }
@ -13,10 +15,15 @@ operator fun Operator.invoke(a: Long, b: Long) = when (this) {
Operator.Multiply -> a * b Operator.Multiply -> a * b
} }
private inline fun Logger.debug(msg: () -> Any) {
if (isDebugEnabled) debug(msg().toString())
}
@Day(18) @Day(18)
class Day18(@Lines val input: Input<List<String>>) { class Day18(@Lines val input: Input<List<String>>) {
val lines = input.value.map { it.replace(" ", "") } private val logger = LoggerFactory.getLogger("Day18")
private val lines = input.value.map { it.replace(" ", "") }
private fun parseGroups(line: String): Map<Int, List<IntRange>> { private fun parseGroups(line: String): Map<Int, List<IntRange>> {
var depth = 0 var depth = 0
@ -37,16 +44,15 @@ class Day18(@Lines val input: Input<List<String>>) {
} }
} }
check(openingPars.isEmpty()) return groups.also { logger.debug { it } }
return groups.also { println(it) }
} }
private fun solveGroup(group: String, precedence: Boolean) = solveGroup(parseGroup(group), precedence) private fun solveGroup(group: String, precedence: Boolean) = solveGroup(parseGroup(group), precedence)
private fun solveGroup(group: Pair<LinkedList<Long>, LinkedList<Operator>>, precedence: Boolean): Long { private fun solveGroup(group: Pair<LinkedList<Long>, LinkedList<Operator>>, precedence: Boolean): Long {
val (operands, operators) = group val (operands, operators) = group
println(operands) logger.debug { operands }
println(operators) logger.debug { operators }
if (!precedence) { if (!precedence) {
for (i in operators.indices) { for (i in operators.indices) {
@ -64,20 +70,19 @@ class Day18(@Lines val input: Input<List<String>>) {
var i = 0 var i = 0
while (operators.any { it == Operator.Add }) { while (operators.any { it == Operator.Add }) {
val a = operands[i]
val b = operands[i + 1]
val operator = operators[i] val operator = operators[i]
if (operator == Operator.Add) { if (operator == Operator.Add) {
val a = operands[i]
val b = operands[i + 1]
val res = operator(a, b) val res = operator(a, b)
operands.removeAt(i) operands.removeAt(i)
operands[i] = res operands[i] = res
operators.removeAt(i) operators.removeAt(i)
i-- } else {
}
i++ i++
} }
}
return operands.reduce { a, b -> Operator.Multiply(a, b) } return operands.reduce { a, b -> Operator.Multiply(a, b) }
} }
@ -105,8 +110,6 @@ class Day18(@Lines val input: Input<List<String>>) {
operands.add(operand.toString().toLong()) operands.add(operand.toString().toLong())
check(operands.size == operators.size + 1)
check(operators.isNotEmpty())
return Pair(operands, operators) return Pair(operands, operators)
} }
@ -117,7 +120,7 @@ class Day18(@Lines val input: Input<List<String>>) {
val groups = parseGroups(l) val groups = parseGroups(l)
if (groups.isEmpty()) break if (groups.isEmpty()) break
val highestDepth = groups.keys.sorted().maxOrNull()!! val highestDepth = groups.keys.maxOrNull()!!
val solvableRanges = groups[highestDepth]!! val solvableRanges = groups[highestDepth]!!
val solved = ArrayDeque<Pair<IntRange, Long>>() val solved = ArrayDeque<Pair<IntRange, Long>>()
@ -155,8 +158,17 @@ class Day18(@Lines val input: Input<List<String>>) {
return solveGroup(l, precedence) return solveGroup(l, precedence)
} }
fun part1() = lines.sumOf { solveLine(it) } fun part1() = lines
fun part2() = lines.sumOf { solveLine(it, precedence = true) } .parallelStream()
.map { solveLine(it) }
.reduce { t, u -> t + u }
.get()
fun part2() = lines
.parallelStream()
.map { solveLine(it, precedence = true) }
.reduce { t, u -> t + u }
.get()
} }
fun main() = with(createDay<Day18>()) { fun main() = with(createDay<Day18>()) {

View File

@ -0,0 +1,44 @@
package be.vandewalleh.aoc.days
import be.vandewalleh.aoc.utils.input.createDay
import java.util.concurrent.TimeUnit
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import org.openjdk.jmh.runner.Runner
import org.openjdk.jmh.runner.options.OptionsBuilder
/*
Benchmark Mode Cnt Score Error Units
Day18Benchmark.part1 avgt 3 0.253 ± 0.098 ms/op
Day18Benchmark.part2 avgt 3 0.283 ± 0.027 ms/op
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Warmup(iterations = 1)
@Measurement(iterations = 3)
open class Day18Benchmark {
private val day18 = createDay<Day18>()
@Benchmark
fun part1(blackhole: Blackhole) {
blackhole.consume(day18.part1())
}
@Benchmark
fun part2(blackhole: Blackhole) {
blackhole.consume(day18.part2())
}
}
fun main() {
val opt = OptionsBuilder()
.include(Day18Benchmark::class.simpleName)
.forks(1)
.build()
Runner(opt).run()
}