generated from kotlin-hands-on/advent-of-code-kotlin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay15.kt
151 lines (128 loc) · 3.76 KB
/
Day15.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package year2023.`15`
import readInput
import utils.printlnDebug
private const val CURRENT_DAY = "15"
data class Label(
val data: String,
val operation: String,
val number: Int?,
) {
override fun toString(): String = "[$data $number]"
}
private fun parseLineInto(
line: String
): List<String> = line.split(",").filter { it.isNotBlank() }
// HASH Algorithm:
// Determine the ASCII code for the current character of the string.
// Increase the current value by the ASCII code you just determined.
// Set the current value to itself multiplied by 17.
// Set the current value to the remainder of dividing itself by 256.
private fun findHash(line: String): Int {
var hash = 0
line.forEach {
hash += it.code
hash *= 17
hash %= 256
}
return hash
}
private fun parseLineIntoLabels(
line: String
): List<Label> {
return line.split(",")
.filter { it.isNotBlank() }
.map {
if (it.contains("=")) {
val list = it.split("=")
Label(
data = list.first(),
operation = "=",
number = list[1].toInt(),
)
} else if (it.contains("-")) {
val list = it.split("-")
Label(
data = list.first(),
operation = "-",
number = null,
)
} else error("Illegal Line $it")
}
}
class MyHashMap {
private val hashMap = List(256) { mutableListOf<Label>() }
fun add(label: Label) {
val hash = findHash(label.data)
hashMap[hash].replaceAll { currentLabel ->
label.takeIf { it.data == currentLabel.data } ?: currentLabel
}
if (hashMap[hash].none { it.data == label.data }) {
hashMap[hash].add(label)
}
}
fun remove(label: Label) {
val hash = findHash(label.data)
hashMap[hash].removeAll { it.data == label.data }
}
override fun toString(): String {
var boxIndex = 0
val string = hashMap.joinToString("") {
boxIndex++
if (it.isNotEmpty()) {
"Box $boxIndex :$it\n"
} else {
""
}
}
return string
}
fun focusPower(): Int {
var sum = 0
hashMap.forEachIndexed { index, labels ->
var partialSum = 0
labels.forEachIndexed { indexInLine, label ->
val resSum = label.number!! * (index + 1) * (indexInLine + 1)
partialSum += resSum
}
sum += partialSum
}
return sum
}
}
fun main() {
fun part1(input: List<String>): Int {
val hashes = parseLineInto(input.first())
.map { findHash(it) }
printlnDebug { hashes }
return hashes.sum()
}
fun part2(input: List<String>): Int {
val mineHashMap = MyHashMap()
parseLineIntoLabels(input.first())
.forEach {
when (it.operation) {
"=" -> mineHashMap.add(it)
"-" -> mineHashMap.remove(it)
}
}
printlnDebug { mineHashMap }
return mineHashMap.focusPower()
}
// test if implementation meets criteria from the description, like:
val testInput = readInput("Day${CURRENT_DAY}_test")
val part1Test = part1(testInput)
println(part1Test)
check(part1Test == 1320)
val part2Test = part2(testInput)
println(part2Test)
check(part2Test == 145)
val input = readInput("Day$CURRENT_DAY")
// Part 1
val part1 = part1(input)
println(part1)
check(part1 == 507769)
// Part 2
val part2 = part2(input)
println(part2)
check(part2 == 269747)
}