-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay13.kt
67 lines (57 loc) · 2.15 KB
/
Day13.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
import util.chunkAt
import util.oneBitDiff
import util.parseBinary
object Day13 : Day(13) {
override val expected = DayResult(405, 27742, 400, 32728)
override fun solvePart1(input: Sequence<String>) = sumSymmetries(input, false)
override fun solvePart2(input: Sequence<String>) = sumSymmetries(input, true)
private fun sumSymmetries(input: Sequence<String>, smudge: Boolean) =
input.toList().chunkAt { it.isBlank() }.sumOf { valley ->
val grid = valley.map { it.toList() }.toList()
val lines = grid.map { it.parseBinary('#') }
val lineSym = lines.findSymmetry(smudge)
if (lineSym != null) {
lineSym * 100
} else {
val columns = (0..<grid[0].size).map { i -> grid.map { it[i] }.parseBinary('#') }
val columnSym = columns.findSymmetry(smudge)
columnSym ?: 0
}
}
private fun List<Long>.findSymmetry(smudge: Boolean): Int? {
val leftCandidates = indices.drop(1).filter {
this[it] == first() || (smudge && oneBitDiff(this[it], first()))
}
leftCandidates.firstNotNullOfOrNull { right ->
checkSymmetry(0, right, smudge)
}?.let { return it }
val rightCandidates = indices.toList().dropLast(1).filter {
this[it] == last() || (smudge && oneBitDiff(this[it], last()))
}
rightCandidates.firstNotNullOfOrNull { left ->
checkSymmetry(left, size - 1, smudge)
}?.let { return it }
return null
}
private fun List<Long>.checkSymmetry(left: Int, right: Int, smudge: Boolean): Int? {
var smudgeAvailable = smudge
var l = left
var r = right
while (l < r) {
if (this[l] != this[r]) {
if (!smudgeAvailable) return null
else if (!oneBitDiff(this[l], this[r])) return null
else {
smudgeAvailable = false
}
}
l++
r--
}
return when {
l == r -> null
smudgeAvailable -> null
else -> l
}
}
}