@@ -6,33 +6,43 @@ data class Token(val char: Char, val pos: Int)
6
6
7
7
sealed class EvaluationResult {
8
8
data class Valid (val _blank : Boolean = true ): EvaluationResult()
9
- data class Corrupt (val token : Token ): EvaluationResult()
10
- data class Incomplete (val token : Token ): EvaluationResult()
9
+ data class Corrupt (val token : Token , val stack : List < Token > ): EvaluationResult()
10
+ data class Incomplete (val token : Token , val stack : List < Token > ): EvaluationResult()
11
11
data class Invalid (val token : Token ): EvaluationResult()
12
12
}
13
13
14
+ data class RepairResult (val completion : String )
15
+
14
16
val LEFT_BRACKET_SET = " ([<{" .toSet()
15
17
val RIGHT_BRACKET_SET = " )]>}" .toSet()
16
- val RIGHT_BRACKET_PAIRING = mapOf (
17
- ' ) ' to ' ( ' ,
18
- ' ] ' to ' [ ' ,
19
- ' } ' to ' { ' ,
20
- ' > ' to ' < ' ,
18
+ val BRACKET_PAIRINGS = listOf (
19
+ ' ( ' to ' ) ' ,
20
+ ' [ ' to ' ] ' ,
21
+ ' { ' to ' } ' ,
22
+ ' < ' to ' > ' ,
21
23
)
22
- val BRACKET_POINTS = mapOf (
24
+ val LEFT_TO_RIGHT_BRACKET_MAP = BRACKET_PAIRINGS .toMap()
25
+ val RIGHT_TO_LEFT_BRACKET_MAP = BRACKET_PAIRINGS .associate { it.second to it.first }
26
+ val EVAL_BRACKET_POINTS = mapOf (
23
27
' )' to 3 ,
24
28
' ]' to 57 ,
25
29
' }' to 1197 ,
26
30
' >' to 25137 ,
27
31
)
32
+ val REPAIR_BRACKET_POINTS = mapOf (
33
+ ' )' to 1 ,
34
+ ' ]' to 2 ,
35
+ ' }' to 3 ,
36
+ ' >' to 4 ,
37
+ )
28
38
29
39
object ExpressionEvaluator {
30
40
fun evaluateNextToken (pos : Int , tokens : List <Token >, stack : List <Token >): EvaluationResult {
31
41
if (pos == tokens.size) {
32
42
val token = stack.last()
33
43
return when (token.char) {
34
- in LEFT_BRACKET_SET -> EvaluationResult .Incomplete (token)
35
- in RIGHT_BRACKET_SET -> EvaluationResult .Corrupt (tokens[pos - 1 ])
44
+ in LEFT_BRACKET_SET -> EvaluationResult .Incomplete (token, stack )
45
+ in RIGHT_BRACKET_SET -> EvaluationResult .Corrupt (tokens[pos - 1 ], stack )
36
46
else -> EvaluationResult .Valid ()
37
47
}
38
48
}
@@ -44,8 +54,8 @@ object ExpressionEvaluator {
44
54
}
45
55
in RIGHT_BRACKET_SET -> {
46
56
val peek = stack.lastOrNull()
47
- if (peek?.char != RIGHT_BRACKET_PAIRING [token.char]) {
48
- EvaluationResult .Corrupt (token)
57
+ if (peek?.char != RIGHT_TO_LEFT_BRACKET_MAP [token.char]) {
58
+ EvaluationResult .Corrupt (token, stack )
49
59
} else {
50
60
evaluateNextToken(pos + 1 , tokens, stack.dropLast(1 ))
51
61
}
@@ -62,6 +72,18 @@ object ExpressionEvaluator {
62
72
}
63
73
}
64
74
75
+ object IncompleteExpressionRepairer {
76
+ fun buildCompletionString (stack : List <Token >, expr : String = ""): String {
77
+ if (stack.isEmpty()) {
78
+ return expr;
79
+ }
80
+
81
+ val token = stack.last()
82
+ val currentExpr = expr + LEFT_TO_RIGHT_BRACKET_MAP [token.char]
83
+ return buildCompletionString(stack.dropLast(1 ), currentExpr)
84
+ }
85
+ }
86
+
65
87
fun runSolutionPart1 (expressions : List <String >) {
66
88
val evaluations = expressions.map { it to ExpressionEvaluator .evaluate(it) }
67
89
@@ -75,12 +97,44 @@ fun runSolutionPart1(expressions: List<String>) {
75
97
.groupingBy { it.token.char }
76
98
.eachCount()
77
99
.toList()
78
- .sumOf { (char, count) -> count * BRACKET_POINTS [char]!! }
100
+ .sumOf { (char, count) -> count * EVAL_BRACKET_POINTS [char]!! }
79
101
80
102
println (" \n Points = $points " )
81
103
}
82
104
105
+ fun runSolutionPart2 (expressions : List <String >) {
106
+ val evaluations = expressions.map { it to ExpressionEvaluator .evaluate(it) }
107
+
108
+ val repairs = evaluations
109
+ .filter { (_, result) -> result is EvaluationResult .Incomplete }
110
+ .map { (expr, result) ->
111
+ val stack = (result as EvaluationResult .Incomplete ).stack
112
+ expr to IncompleteExpressionRepairer .buildCompletionString(stack)
113
+ }
114
+
115
+ val sumPointsForRepair: (String ) -> Long = { repair: String ->
116
+ repair.toList().fold(0L ) { points, bracket ->
117
+ (points * 5 ) + REPAIR_BRACKET_POINTS [bracket]!!
118
+ }
119
+ }
120
+
121
+ println ()
122
+
123
+ val scoredRepairs = repairs
124
+ .map { (expr, repair) -> repair to sumPointsForRepair(repair) }
125
+ .sortedBy { (_, points) -> points }
126
+
127
+ scoredRepairs.forEach { (repair, points) ->
128
+ println (" repair $repair : points = $points " )
129
+ }
130
+
131
+ val middleScoredReport = scoredRepairs[scoredRepairs.size / 2 ]
132
+
133
+ println (" \n Middle: $middleScoredReport " )
134
+ }
135
+
83
136
fun main () {
84
137
val expressions = File (" day10/src/main/resources/puzzleInput.txt" ).readLines()
85
- runSolutionPart1(expressions)
138
+ // runSolutionPart1(expressions)
139
+ runSolutionPart2(expressions)
86
140
}
0 commit comments