8000 Day 10 · l0s/advent-of-code-java@785ff7b · GitHub
[go: up one dir, main page]

Skip to content

Commit 785ff7b

Browse files
committed
Day 10
1 parent 84d347b commit 785ff7b

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

src/test/java/com/macasaet/Day10.java

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package com.macasaet;
2+
3+
import java.util.ArrayList;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
import java.util.stream.Stream;
7+
import java.util.stream.StreamSupport;
8+
9+
import org.junit.jupiter.api.Test;
10+
11+
/**
12+
* --- Day 10: Syntax Scoring ---
13+
*/
14+
public class Day10 {
15+
16+
protected Stream<String> getInput() {
17+
return StreamSupport
18+
.stream(new LineSpliterator("day-10.txt"),
19+
false);
20+
}
21+
22+
/**
23+
* The type of open and closing delimiter for a chunk in the navigation subsystem
24+
*/
25+
public enum BracketType {
26+
PARENTHESIS('(', ')', 3, 1),
27+
SQUARE('[', ']', 57, 2),
28+
CURLY('{', '}', 1197, 3),
29+
ANGLED('<', '>', 25137, 4);
30+
31+
private final char open;
32+
private final char close;
33+
private final int corruptionPoints;
34+
private final int autocompletePoints;
35+
36+
BracketType(char open, char close, int corruptionPoints, final int autocompletePoints) {
37+
this.open = open;
38+
this.close = close;
39+
this.corruptionPoints = corruptionPoints;
40+
this.autocompletePoints = autocompletePoints;
41+
}
42+
43+
public static BracketType forOpen(final char c) {
44+
return switch (c) {
45+
case '(' -> PARENTHESIS;
46+
case '[' -> SQUARE;
47+
case '{' -> CURLY;
48+
case '<' -> ANGLED;
49+
default -> throw new IllegalStateException("Unexpected value: " + c);
50+
};
51+
}
52+
53+
public static BracketType forClose(final char c) {
54+
return switch (c) {
55+
case ')' -> PARENTHESIS;
56+
case ']' -> SQUARE;
57+
case '}' -> CURLY;
58+
case '>' -> ANGLED;
59+
default -> throw new IllegalStateException("Unexpected value: " + c);
60+
};
61+
}
62+
}
63+
64+
/**
65+
* @param line a line in the navigation subsystem
66+
* @return a score of how corrupt the line is. A score of zero means it is not corrupt. The higher the value, the
67+
* more corrupt the line is.
68+
*/
69+
public int calculateCorruptionScore(final char[] line) {
70+
final var stack = new LinkedList<BracketType>();
71+
for (int i = 0; i < line.length; i++) {
72+
final var c = line[i];
73+
if (c == '(' || c == '[' || c == '{' || c == '<') {
74+
stack.push(BracketType.forOpen(c));
75+
} else if (c == ')' || c == ']' || c == '}' || c == '>') {
76+
if (stack.peek().close == c) {
77+
stack.pop();
78+
} else {
79+
// corrupt
80+
return BracketType.forClose(c).corruptionPoints;
81+
}
82+
}
83+
}
84+
// if stack is not empty, it's incomplete
85+
return 0;
86+
}
87+
88+
/**
89+
* @param line a non-corrupt line in the navigation subsystem. Behaviour is undefined for corrupt lines.
90+
* @return the score for the suffix required to complete the line
91+
*/
92+
public long calculateCompletionScore(final char[] line) {
93+
final var stack = new LinkedList<BracketType>();
94+
for (int i = 0; i < line.length; i++) {
95+
final var c = line[i];
96+
if (c == '(' || c == '[' || c == '{' || c == '<') {
97+
stack.push(BracketType.forOpen(c));
98+
} else if (c == ')' || c == ']' || c == '}' || c == '>') {
99+
if (stack.peek().close == c) {
100+
stack.pop();
101+
} else {
102+
throw new IllegalArgumentException("Corrupt: " + new String(line));
103+
}
104+
}
105+
}
106+
long result = 0;
107+
while (!stack.isEmpty()) {
108+
final var unclosed = stack.pop();
109+
result = result * 5 + unclosed.autocompletePoints;
110+
}
111+
return result;
112+
}
113+
114+
@Test
115+
public final void part1() {
116+
final var result = getInput()
117+
.map(String::toCharArray)
118+
.filter(line -> line.length > 0)
119+
.mapToInt(this::calculateCorruptionScore)
120+
.sum();
121+
System.out.println("Part 1: " + result);
122+
}
123+
124+
@Test
125+
public final void part2() {
126+
final var list = getInput()
127+
.map(String::toCharArray)
128+
.filter(line -> line.length > 0)
129+
.filter(line -> calculateCorruptionScore(line) <= 0) // discard corrupted lines
130+
.mapToLong(this::calculateCompletionScore)
131+
.sorted()
132+
.collect(ArrayList<Long>::new, List::add, List::addAll);
133+
final var result = list.get(list.size() / 2);
134+
System.out.println("Part 2: " + result);
135+
}
136+
137+
}

src/test/resources/sample/day-10.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[({(<(())[]>[[{[]{<()<>>
2+
[(()[<>])]({[<{<<[]>>(
3+
{([(<{}[<>[]}>{[]{[(<()>
4+
(((({<>}<{<{<>}{[]{[]{}
5+
[[<[([]))<([[{}[[()]]]
6+
[{[{({}]{}}([{[{{{}}([]
7+
{<[[]]>}<{[{[{[]{()[[[]
8+
[<(<(<(<{}))><([]([]()
9+
<{([([[(<>()){}]>(<<{{
10+
<{([{{}}[<[[[<>{}]]]>[]]

0 commit comments

Comments
 (0)
0