Created
December 11, 2021 00:14
-
-
Save SquireOfSoftware/b9fb64867373c9fc6d4f8c4214948750 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package advent_2021.day10; | |
import java.io.File; | |
import java.util.*; | |
public class Day10 { | |
public static void main(String[] args) { | |
File file = new File("day10.csv"); | |
// File file = new File("sample.csv"); | |
// sample part 1: 26397 | |
// sample part 2: 288957 | |
Day10 day10 = new Day10(); | |
try (Scanner myReader = new Scanner(file)) { | |
while (myReader.hasNextLine()) { | |
String data = myReader.nextLine(); | |
day10.addData(Arrays.asList(data.split(""))); | |
} | |
} catch (Exception e) { | |
e.fillInStackTrace(); | |
System.err.println(e); | |
} | |
/* | |
part 1 | |
find corrupt lines, that do not close properly | |
ignore the missing lines for now | |
if any of the lines end with the following | |
): 3 points. | |
]: 57 points. | |
}: 1197 points. | |
>: 25137 points. | |
then that is the error score for that corrupted line | |
find the corrupted line, calculate the error score | |
answer: 390993 | |
*/ | |
System.out.println(day10.getCorruptLinesValue()); | |
/* | |
part 2 | |
throw away the corrupt lines, find the missing lines and complete them | |
for each character that you use to complete it you can assign this value | |
): 1 point. | |
]: 2 points. | |
}: 3 points. | |
>: 4 points. | |
for each new character you can multiply the current total by 5, then add the | |
completion value | |
then sort the results and pick the middle value | |
answer: 2391385187 | |
*/ | |
System.out.println(day10.getMiddleCompletionValue()); | |
} | |
enum Pair { | |
parenthesis("(", ")", 3, 1), | |
square("[", "]", 57, 2), | |
curly("{", "}", 1197, 3), | |
angle("<", ">", 25137, 4); | |
final String start; | |
final String end; | |
final int errorValue; | |
final int completionValue; | |
Pair(String start, String end, int errorValue, int completionValue) { | |
this.start = start; | |
this.end = end; | |
this.errorValue = errorValue; | |
this.completionValue = completionValue; | |
} | |
} | |
// for reference | |
private final List<List<String>> inputs = new ArrayList<>(); | |
private final Map<String, Pair> startPairMap = new HashMap<>(4); | |
private final Map<String, Pair> endPairMap = new HashMap<>(4); | |
private final List<Line> processedLines = new ArrayList<>(); | |
public Day10() { | |
startPairMap.put(Pair.parenthesis.start, Pair.parenthesis); | |
endPairMap.put(Pair.parenthesis.end, Pair.parenthesis); | |
startPairMap.put(Pair.square.start, Pair.square); | |
endPairMap.put(Pair.square.end, Pair.square); | |
startPairMap.put(Pair.curly.start, Pair.curly); | |
endPairMap.put(Pair.curly.end, Pair.curly); | |
startPairMap.put(Pair.angle.start, Pair.angle); | |
endPairMap.put(Pair.angle.end, Pair.angle); | |
} | |
public void addData(List<String> input) { | |
inputs.add(input); | |
Line line = new Line(); | |
Stack<String> bracketStack = new Stack<>(); | |
for (String bracket: input) { | |
if(startPairMap.containsKey(bracket)) { | |
// then we know its a start of something | |
bracketStack.push(bracket); | |
} else if (endPairMap.containsKey(bracket)) { | |
// then we know this is an ending bracket | |
// check for the last bracket and if it does not equal | |
// then it is corrupt | |
Pair type = endPairMap.get(bracket); | |
String currentStackValue = bracketStack.peek(); | |
if (Objects.equals(type.start, currentStackValue)) { | |
// then we know its a legit thing, so let us pop it from the stack | |
bracketStack.pop(); | |
} else { | |
// there is a mismatch and so now we need to mark the line as corrupt | |
// and stop the processing | |
line.setCorrupt(endPairMap.get(bracket)); | |
line.addLeftOverStack(bracketStack); | |
break; | |
} | |
} | |
} | |
if (!bracketStack.isEmpty()) { | |
// we are potentially missing things | |
line.addLeftOverStack(bracketStack); | |
} | |
processedLines.add(line); | |
} | |
public long getCorruptLinesValue() { | |
long sum = 0; | |
for(Line line: processedLines) { | |
if (line.isCorrupt()) { | |
sum += line.getCorruptValue(); | |
} | |
} | |
return sum; | |
} | |
public long getMiddleCompletionValue() { | |
List<Long> completionValues = new ArrayList<>(); | |
for(Line line: processedLines) { | |
if (!line.isCorrupt() && line.isMissing()) { | |
Stack<String> leftOverStack = new Stack<>(); | |
leftOverStack.addAll(line.getLeftOverStack()); | |
long completionValue = 0; | |
while(!leftOverStack.isEmpty()) { | |
String bracket = leftOverStack.pop(); | |
Pair type = startPairMap.get(bracket); | |
completionValue *= 5; // as per spec | |
completionValue += type.completionValue; | |
} | |
completionValues.add(completionValue); | |
} | |
} | |
completionValues.sort(Long::compareTo); | |
int median = completionValues.size() % 2 == 1 ? completionValues.size() / 2 + 1 : completionValues.size(); | |
// the counts are different to positions, so you need to subtract 1 | |
median--; | |
return completionValues.get(median); | |
} | |
private static class Line { | |
private Stack<String> bracketStack = new Stack<>(); | |
private Pair corruptCharacter = null; | |
public void setCorrupt(Pair type) { | |
this.corruptCharacter = type; | |
} | |
public boolean isCorrupt() { | |
return corruptCharacter != null; | |
} | |
public int getCorruptValue() { | |
return corruptCharacter.errorValue; | |
} | |
public void addLeftOverStack(Stack<String> bracketStack) { | |
this.bracketStack = bracketStack; | |
} | |
public boolean isMissing() { | |
return !bracketStack.isEmpty(); | |
} | |
public Stack<String> getLeftOverStack() { | |
return bracketStack; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment