generated from kotlin-hands-on/advent-of-code-kotlin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay14.kt
97 lines (70 loc) · 2.78 KB
/
Day14.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package year2021.`14`
import readInput
// region Parsing
private fun parseInput(input: List<String>): String = input.first()
private fun parseMapper(input: List<String>): Transformations {
val transformations = input.drop(2)
return transformations.associate { transformationString ->
val (left, right) = transformationString.split("->")
.map { it.trim() }
left to right
}
}
// endregion
typealias MapPairCount = MutableMap<String, Long>
typealias MapCharCount = Map<Char, Long>
typealias Transformations = Map<String, String>
private fun cycle(input: MapPairCount, transformations: Transformations): MapPairCount {
val resultMap: MapPairCount = mutableMapOf()
input.keys
.forEach { initialPair ->
if (initialPair.length != 2) error("Illegal pair : $initialPair")
val chatToSet = transformations[initialPair]
val left = initialPair.first()
val right = initialPair.last()
val leftPair = "$left$chatToSet"
val rightPair = "$chatToSet$right"
resultMap[leftPair] = resultMap.getOrDefault(leftPair, 0) + input[initialPair]!!
resultMap[rightPair] = resultMap.getOrDefault(rightPair, 0) + input[initialPair]!!
}
return resultMap
}
private fun MapPairCount.countCharCount(firstChar: Char, lastChar: Char): MapCharCount {
val map = mutableMapOf<Char, Long>()
forEach { (key, value) ->
val left = key.first()
val right = key.last()
map[left] = map.getOrDefault(left, 0) + value
map[right] = map.getOrDefault(right, 0) + value
}
map[firstChar] = map[firstChar]!! + 1
map[lastChar] = map[lastChar]!! + 1
return map
}
private fun stringToMapCount(string: String): MapPairCount {
return string.windowed(2)
.groupBy { it }
.mapValues { it.value.size.toLong() } as MapPairCount
}
private fun fastAnswer(input: List<String>, n: Int): Long {
val initLine = parseInput(input)
val transformations = parseMapper(input)
var bufRes = stringToMapCount(initLine)
repeat(n) {
bufRes = cycle(bufRes, transformations)
}
val res = bufRes.countCharCount(initLine.first(), initLine.last())
val answer = res.values.max() - res.values.min()
return answer / 2
}
fun main() {
// test if implementation meets criteria from the description, like:
val testInput = readInput("Day14_test")
val part1Test = fastAnswer(testInput, 10)
val part2Test = fastAnswer(testInput, 40)
println(part1Test.also { check(it == 1588L) })
println(part2Test.also { assert(it == 2188189693529) })
val input = readInput("Day14")
println(fastAnswer(input, 10).also { assert(it == 2188189693529) })
println(fastAnswer(input, 40).also { assert(it == 4110568157153) })
}