generated from kotlin-hands-on/advent-of-code-kotlin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay08.kt
108 lines (91 loc) · 3.27 KB
/
Day08.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
package year2022.`08`
import readInput
import transpose
fun main() {
fun createGrid(input: List<String>): List<List<Int>> {
return input.map {
it.split("")
.drop(1)
.dropLast(1)
.map { item -> item.toInt() }
}
}
fun <T> genericCombine(
first: List<List<T>>,
second: List<List<T>>,
block: (left: T, right: T) -> T
): List<List<T>> {
return first.mapIndexed { i, line ->
List(line.size) { j -> block(first[i][j], second[i][j]) }
}
}
fun <T> Iterable<T>.takeUntil(predicate: (T) -> Boolean): List<T> {
val list = ArrayList<T>()
for (item in this) {
if (!predicate(item)) {
list.add(item)
return list
}
list.add(item)
}
return list
}
fun calculateHorizontalVisibilityGrid(
grid: List<List<Int>>,
): List<List<Boolean>> {
return grid.mapIndexed { i, line ->
List(line.size) { j ->
val currentTreeSize = grid[i][j]
val leftSide = grid[i].take(j)
val rightSide = grid[i].drop(j + 1)
val isVisibleFromLeft = leftSide.all { it < currentTreeSize }
val isVisibleFromRight = rightSide.all { it < currentTreeSize }
isVisibleFromLeft || isVisibleFromRight
}
}
}
fun calculateHorizontalScoreGrid(
grid: List<List<Int>>,
): List<List<Int>> {
return grid.mapIndexed { i, line ->
List(line.size) { j ->
val currentTreeSize = grid[i][j]
val fromLeft = grid[i].take(j).reversed()
val fromLeftTaken = fromLeft.takeUntil { it < currentTreeSize }
val fromRight = grid[i].drop(j + 1)
val fromRightTaken = fromRight.takeUntil { it < currentTreeSize }
val leftCount = fromLeftTaken.count().takeIf { it != 0 } ?: 1
val rightCount = fromRightTaken.count().takeIf { it != 0 } ?: 1
if (fromLeft.isEmpty() || fromRight.isEmpty()) {
0
} else {
leftCount * rightCount
}
}
}
}
fun part1(input: List<String>): Int {
val grid = createGrid(input)
val vertical = transpose(calculateHorizontalVisibilityGrid(transpose(grid)))
val horizontal = calculateHorizontalVisibilityGrid(grid)
return genericCombine(vertical, horizontal) { left, right -> left || right }
.flatten()
.count { it }
}
fun part2(input: List<String>): Int {
val grid = createGrid(input)
val horizontal = calculateHorizontalScoreGrid(grid)
val vertical = transpose(calculateHorizontalScoreGrid(transpose(grid)))
return genericCombine(vertical, horizontal) { left, right -> left * right }
.flatten()
.max()
}
// test if implementation meets criteria from the description, like:
val testInput = readInput("Day08_test")
val part1Test = part2(testInput)
println(part1Test)
check(part1Test == 8)
val input = readInput("Day08")
println(part1(input))
println(part2(input))
}