Skip to content

Commit db07188

Browse files
committed
Solution 2018-02 (Inventory Management System)
1 parent 0126f8b commit db07188

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package de.ronny_h.aoc.year2018.day02
2+
3+
import de.ronny_h.aoc.AdventOfCode
4+
import de.ronny_h.aoc.extensions.combinations
5+
import kotlin.math.min
6+
7+
fun main() = InventoryManagementSystem().run("5434", "agimdjvlhedpsyoqfzuknpjwt")
8+
9+
class InventoryManagementSystem : AdventOfCode<String>(2018, 2) {
10+
override fun part1(input: List<String>): String {
11+
var twoLetterCount = 0
12+
var threeLetterCount = 0
13+
input.forEach { id ->
14+
val groups = id.groupBy { it }
15+
twoLetterCount += if (groups.any { it.value.size == 2 }) 1 else 0
16+
threeLetterCount += if (groups.any { it.value.size == 3 }) 1 else 0
17+
}
18+
return "${twoLetterCount * threeLetterCount}"
19+
}
20+
21+
override fun part2(input: List<String>): String {
22+
val minPair = input
23+
.combinations()
24+
.minBy { lev(it.first, it.second) }
25+
26+
return minPair.first.filterIndexed { i, char ->
27+
minPair.second[i] == char
28+
}
29+
}
30+
}
31+
32+
private val levCache = mutableMapOf<Pair<String, String>, Int>()
33+
34+
/**
35+
* The Levenshtein distance (an edit distance).
36+
*/
37+
fun lev(a: String, b: String): Int {
38+
levCache[a to b]?.let { return it }
39+
40+
if (b.isEmpty()) return a.length
41+
if (a.isEmpty()) return b.length
42+
43+
val aTail = a.substring(1)
44+
val bTail = b.substring(1)
45+
46+
val tailResult = lev(aTail, bTail)
47+
levCache[aTail to bTail] = tailResult
48+
49+
if (a.first() == b.first()) {
50+
return tailResult
51+
}
52+
53+
val aTailResult = lev(aTail, b)
54+
val bTailResult = lev(a, bTail)
55+
levCache[aTail to b] = aTailResult
56+
levCache[a to bTail] = bTailResult
57+
58+
return 1 + min(min(aTailResult, bTailResult), tailResult)
59+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package de.ronny_h.aoc.year2018.day02
2+
3+
import de.ronny_h.aoc.extensions.asList
4+
import io.kotest.core.spec.style.StringSpec
5+
import io.kotest.data.forAll
6+
import io.kotest.data.row
7+
import io.kotest.matchers.shouldBe
8+
9+
class InventoryManagementSystemTest : StringSpec({
10+
11+
"part 1: the checksum (product of number of letters appearing twice and 3 times exactly)" {
12+
val input = """
13+
abcdef
14+
bababc
15+
abbcde
16+
abcccd
17+
aabcdd
18+
abcdee
19+
ababab
20+
""".asList()
21+
22+
InventoryManagementSystem().part1(input) shouldBe "12"
23+
}
24+
25+
"part 2: the common letters between the two correct box IDs" {
26+
val input = """
27+
abcde
28+
fghij
29+
klmno
30+
pqrst
31+
fguij
32+
axcye
33+
wvxyz
34+
""".asList()
35+
InventoryManagementSystem().part2(input) shouldBe "fgij"
36+
}
37+
38+
"The Levenshtein distance" {
39+
forAll(
40+
row("", "", 0),
41+
row("", "a", 1),
42+
row("a", "", 1),
43+
row("abc", "abc", 0),
44+
row("abc", "a_c", 1),
45+
row("abc", "xyz", 3),
46+
row("abc", "abcxyz", 3),
47+
) { a, b, distance ->
48+
lev(a, b) shouldBe distance
49+
}
50+
}
51+
})

0 commit comments

Comments
 (0)