Skip to content

Commit 8993f78

Browse files
committed
Solution 2018-05 (Alchemical Reduction)
1 parent facfb07 commit 8993f78

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package de.ronny_h.aoc.year2018.day05
2+
3+
import de.ronny_h.aoc.AdventOfCode
4+
5+
fun main() = AlchemicalReduction().run(9900, 4992)
6+
7+
class AlchemicalReduction : AdventOfCode<Int>(2018, 5) {
8+
override fun part1(input: List<String>): Int = input.first().react().length
9+
10+
override fun part2(input: List<String>): Int {
11+
val polymer = input.first()
12+
return "abcdefghijklmnopqrstuvwxyz".minOf {
13+
polymer.react(it).length
14+
}
15+
}
16+
}
17+
18+
fun String.react(toRemove: Char = ' '): String {
19+
val toRemoveUpperCase = toRemove.uppercaseChar()
20+
val toSkip = List(length) { i ->
21+
get(i) == toRemove || get(i) == toRemoveUpperCase
22+
}.toMutableList()
23+
var somethingNewIsSkipped: Boolean
24+
25+
do {
26+
somethingNewIsSkipped = false
27+
var index = 0
28+
while (index < lastIndex) {
29+
if (toSkip[index]) {
30+
index++
31+
continue
32+
}
33+
val nextIndex = nextNonSkippedIndex(index, toSkip)
34+
if (nextIndex > lastIndex) {
35+
break
36+
}
37+
if (get(index) == get(nextIndex).oppositeCase()) {
38+
toSkip[index] = true
39+
toSkip[nextIndex] = true
40+
index = nextIndex + 1
41+
somethingNewIsSkipped = true
42+
} else {
43+
index++
44+
}
45+
}
46+
} while (somethingNewIsSkipped)
47+
return filterIndexed { i, _ -> !toSkip[i] }
48+
}
49+
50+
private fun String.nextNonSkippedIndex(index: Int, toSkip: List<Boolean>): Int {
51+
var nextIndex = index + 1
52+
while (nextIndex < length && toSkip[nextIndex]) {
53+
nextIndex++
54+
}
55+
return nextIndex
56+
}
57+
58+
private fun Char.oppositeCase() = if (isLowerCase()) uppercaseChar() else lowercaseChar()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package de.ronny_h.aoc.year2018.day05
2+
3+
import io.kotest.core.spec.style.StringSpec
4+
import io.kotest.data.forAll
5+
import io.kotest.data.row
6+
import io.kotest.matchers.shouldBe
7+
8+
class AlchemicalReductionTest : StringSpec({
9+
10+
"simple reactions" {
11+
forAll(
12+
row("aA", ""),
13+
row("abBA", ""),
14+
row("abBAc", "c"),
15+
row("cabBA", "c"),
16+
row("abAB", "abAB"),
17+
row("aabAAB", "aabAAB"),
18+
row("dabAcCaCBAcCcaDA", "dabCBAcaDA"),
19+
) { chain, result ->
20+
chain.react() shouldBe result
21+
}
22+
}
23+
24+
"part 1: the number of units after all possible reactions" {
25+
val input = listOf("dabAcCaCBAcCcaDA")
26+
AlchemicalReduction().part1(input) shouldBe 10
27+
}
28+
29+
"part 2: the number of units after all possible reactions with the most problem-causing unit removed" {
30+
val input = listOf("dabAcCaCBAcCcaDA")
31+
AlchemicalReduction().part2(input) shouldBe 4
32+
}
33+
})

0 commit comments

Comments
 (0)