-
Notifications
You must be signed in to change notification settings - Fork 0
/
App.kt
106 lines (84 loc) · 3.46 KB
/
App.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
package day05.solution1
// Original solution used to solve the AoC day 5 puzzle. Warts and all.
import common.Solution
data class MoveAction(val numCrates: Int, val from: Int, val to: Int);
typealias CrateStack = List<Char>
typealias CrateStacks = List<CrateStack>
typealias MoveActions = List<MoveAction>
abstract class CrateStackOperator {
fun apply(crateStacks: CrateStacks, moveAction: MoveAction): CrateStacks {
val fromStack = crateStacks[moveAction.from]
val toStack = crateStacks[moveAction.to]
val crates = this.pickCratesFromStack(fromStack, moveAction.numCrates)
return crateStacks.mapIndexed { idx, stack ->
when (idx) {
moveAction.to -> toStack + crates
moveAction.from -> fromStack.dropLast(moveAction.numCrates)
else -> stack
}
}
}
protected abstract fun pickCratesFromStack(stack: List<Char>, numCrates: Int): List<Char>;
}
object CrateStackOperator9000: CrateStackOperator() {
override fun pickCratesFromStack(stack: List<Char>, numCrates: Int): List<Char> {
return stack.takeLast(numCrates).reversed()
}
}
object CrateStackOperator9001: CrateStackOperator() {
override fun pickCratesFromStack(stack: List<Char>, numCrates: Int): List<Char> {
return stack.takeLast(numCrates)
}
}
fun CrateStacks.print(): Unit {
this.forEachIndexed { idx, stack ->
println("Stack ${idx + 1}: $stack")
}
}
typealias ParsedInput = Pair<CrateStacks, MoveActions>
object Day05 : Solution.GroupedLinedInput<ParsedInput>(day = 5) {
private fun parseCrateInputSegment(input: List<String>): CrateStacks {
val chunkedLines = input.map { line ->
line.chunked(4).map { it.trim() }
}
val crateStacks = (1..chunkedLines.last().last().toInt()).map { mutableListOf<Char>() }
chunkedLines.dropLast(1).reversed().forEach { crates ->
crates.forEachIndexed { idx, crate ->
if (crate.isNotEmpty()) {
crateStacks[idx].add(crate[1])
}
}
}
return crateStacks
}
private fun parseMoveActionsInputSegment(input: List<String>): MoveActions {
return input.map { line ->
line.split(" ").let { tokens ->
val numCrates = tokens[1]!!.toInt()
val fromIdx = tokens[3]!!.toInt() - 1
val toIdx = tokens[5]!!.toInt() - 1
MoveAction(numCrates = numCrates, from = fromIdx, to = toIdx)
}
}
}
override fun parseInput(input: List<List<String>>): ParsedInput {
val crateStacks = this.parseCrateInputSegment(input.first())
val moveActions = this.parseMoveActionsInputSegment(input.last())
return (crateStacks to moveActions);
}
override fun part1(input: ParsedInput): Any {
val (crateStacks, moveActions) = input
return moveActions.fold(crateStacks) { currCrateStacks, action ->
CrateStackOperator9000.apply(currCrateStacks, action)
}.map { it.last() }.joinToString(separator = "") { it.toString() }
}
override fun part2(input: ParsedInput): Any {
val (crateStacks, moveActions) = input
return moveActions.fold(crateStacks) { currCrateStacks, action ->
CrateStackOperator9001.apply(currCrateStacks, action)
}.map { it.last() }.joinToString(separator = "") { it.toString() }
}
}
fun main() {
Day05.solve(test = false)
}