From 0f2098634bf395f3c3631813fb476161d7fd3043 Mon Sep 17 00:00:00 2001 From: Hubert Van De Walle Date: Fri, 18 Dec 2020 13:55:19 +0100 Subject: [PATCH] Parallelize solutions + benchmarks --- days/build.gradle.kts | 3 ++ days/src/main/kotlin/Day18.kt | 42 +++++++++++++++--------- days/src/test/kotlin/Day18Benchmark.kt | 44 ++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 days/src/test/kotlin/Day18Benchmark.kt diff --git a/days/build.gradle.kts b/days/build.gradle.kts index 6eb33d2..9ed4323 100644 --- a/days/build.gradle.kts +++ b/days/build.gradle.kts @@ -11,6 +11,9 @@ dependencies { implementation(Libs.Micronaut.kotlin) kapt(Libs.Micronaut.processor) + implementation(Libs.Slf4J.api) + runtimeOnly(Libs.Slf4J.simple) + implementation(Libs.eclipseCollections) { because("Primitive collections mostly") } diff --git a/days/src/main/kotlin/Day18.kt b/days/src/main/kotlin/Day18.kt index 6befef1..db10b0b 100644 --- a/days/src/main/kotlin/Day18.kt +++ b/days/src/main/kotlin/Day18.kt @@ -5,6 +5,8 @@ import be.vandewalleh.aoc.utils.input.Input import be.vandewalleh.aoc.utils.input.Lines import be.vandewalleh.aoc.utils.input.createDay import java.util.* +import org.slf4j.Logger +import org.slf4j.LoggerFactory enum class Operator { Add, Multiply } @@ -13,10 +15,15 @@ operator fun Operator.invoke(a: Long, b: Long) = when (this) { Operator.Multiply -> a * b } +private inline fun Logger.debug(msg: () -> Any) { + if (isDebugEnabled) debug(msg().toString()) +} + @Day(18) class Day18(@Lines val input: Input>) { - 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> { var depth = 0 @@ -37,16 +44,15 @@ class Day18(@Lines val input: Input>) { } } - check(openingPars.isEmpty()) - return groups.also { println(it) } + return groups.also { logger.debug { it } } } private fun solveGroup(group: String, precedence: Boolean) = solveGroup(parseGroup(group), precedence) private fun solveGroup(group: Pair, LinkedList>, precedence: Boolean): Long { val (operands, operators) = group - println(operands) - println(operators) + logger.debug { operands } + logger.debug { operators } if (!precedence) { for (i in operators.indices) { @@ -64,19 +70,18 @@ class Day18(@Lines val input: Input>) { var i = 0 while (operators.any { it == Operator.Add }) { - val a = operands[i] - val b = operands[i + 1] val operator = operators[i] if (operator == Operator.Add) { + val a = operands[i] + val b = operands[i + 1] val res = operator(a, b) operands.removeAt(i) operands[i] = res operators.removeAt(i) - i-- + } else { + i++ } - - i++ } return operands.reduce { a, b -> Operator.Multiply(a, b) } @@ -105,8 +110,6 @@ class Day18(@Lines val input: Input>) { operands.add(operand.toString().toLong()) - check(operands.size == operators.size + 1) - check(operators.isNotEmpty()) return Pair(operands, operators) } @@ -117,7 +120,7 @@ class Day18(@Lines val input: Input>) { val groups = parseGroups(l) if (groups.isEmpty()) break - val highestDepth = groups.keys.sorted().maxOrNull()!! + val highestDepth = groups.keys.maxOrNull()!! val solvableRanges = groups[highestDepth]!! val solved = ArrayDeque>() @@ -155,8 +158,17 @@ class Day18(@Lines val input: Input>) { return solveGroup(l, precedence) } - fun part1() = lines.sumOf { solveLine(it) } - fun part2() = lines.sumOf { solveLine(it, precedence = true) } + fun part1() = lines + .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()) { diff --git a/days/src/test/kotlin/Day18Benchmark.kt b/days/src/test/kotlin/Day18Benchmark.kt new file mode 100644 index 0000000..8e75528 --- /dev/null +++ b/days/src/test/kotlin/Day18Benchmark.kt @@ -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() + + @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() +}