Last active
September 13, 2024 11:44
-
-
Save lry127/ad8335216d4737bff3056b6a1cef95e8 to your computer and use it in GitHub Desktop.
Advent of code Day 3 solution in Java
This file contains hidden or 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
import java.util.*; | |
public class D3 { | |
record Point(int row, int col) {} | |
static class NumberRecord { | |
ArrayList<Point> span = new ArrayList<>(); | |
ArrayList<Integer> values = new ArrayList<>(); | |
void takePoint(Point pt, int value) { | |
span.add(pt); | |
values.add(value); | |
} | |
int getQuestion1Value(SymbolRecord symbols) { | |
int repValue = combineDigitsToNumericValue(); | |
boolean satisfied = isQuestion1CriteriaSatisfied(symbols); | |
return satisfied ? repValue : 0; | |
} | |
int getQuestion2Value(int[][] calTable, SymbolRecord symbolTable) { | |
Set<Point> allSurroundingPts = getAllPossibleSymbolSlots(); | |
for (Point pt : allSurroundingPts) { | |
if (!symbolTable.isGear(pt)) { | |
continue; | |
} | |
int[] thisRow = calTable[pt.row]; | |
int value = combineDigitsToNumericValue(); | |
if (thisRow[pt.col] == 0) { | |
thisRow[pt.col] = value; | |
return 0; | |
} else { | |
int res = thisRow[pt.col] * value; | |
thisRow[pt.col] = 0; | |
return res; | |
} | |
} | |
return 0; | |
} | |
private int combineDigitsToNumericValue() { | |
int result = 0; | |
int len = values.size(); | |
for (int i = 0; i < len; ++i) { | |
int digit = values.get(i); | |
int exp = len - i - 1; | |
result += (int) (digit * Math.pow(10, exp)); | |
} | |
return result; | |
} | |
private boolean isQuestion1CriteriaSatisfied(SymbolRecord symbolTable) { | |
Set<Point> allPossiblePos = getAllPossibleSymbolSlots(); | |
for (Point pt : allPossiblePos) { | |
if (symbolTable.isSymbol(pt)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
private Set<Point> getAllPossibleSymbolSlots() { | |
Set<Point> points = new HashSet<>(); | |
for (Point pt : span) { | |
points.addAll(getSurroundingSlots(pt)); | |
} | |
return points; | |
} | |
private Set<Point> getSurroundingSlots(Point pt) { | |
Set<Point> points = new HashSet<>(); | |
for (int rowDiff = -1; rowDiff < 2; ++rowDiff) { | |
for (int colDiff = -1; colDiff < 2; ++colDiff) { | |
int surroundingRowNo = pt.row + rowDiff; | |
int surroundingColNo = pt.col + colDiff; | |
if (surroundingRowNo < 0 || surroundingColNo < 0) { | |
continue; | |
} | |
Point surrounding = new Point(pt.row + rowDiff, pt.col + colDiff); | |
points.add(surrounding); | |
} | |
} | |
points.remove(pt); | |
return points; | |
} | |
static List<NumberRecord> parseLine(String data, int rowNo) { | |
char[] charArray = data.toCharArray(); | |
ArrayList<NumberRecord> numbersInLine = new ArrayList<>(); | |
NumberRecord number = null; | |
for (int colNo = 0; colNo < charArray.length; ++colNo) { | |
char currChar = charArray[colNo]; | |
boolean isDigit = Character.isDigit(currChar); | |
if (isDigit) { | |
Point currPt = new Point(rowNo, colNo); | |
int value = Character.getNumericValue(currChar); | |
if (number == null) { | |
number = new NumberRecord(); | |
} | |
number.takePoint(currPt, value); | |
} else { | |
if (number != null) { | |
numbersInLine.add(number); | |
number = null; | |
} | |
} | |
} | |
if (number != null) { | |
numbersInLine.add(number); | |
} | |
return numbersInLine; | |
} | |
} | |
static class SymbolRecord { | |
enum SymbolType { | |
NON_SYMBOL('.'), | |
REGULAR_SYMBOL('S'), | |
NUMBER('0'), | |
GEAR('*'); | |
final char rep; | |
SymbolType(char rep) { | |
this.rep = rep; | |
} | |
} | |
ArrayList<ArrayList<SymbolType>> rows = new ArrayList<>(); | |
void parseLine(String data) { | |
ArrayList<SymbolType> row = new ArrayList<>(data.length()); | |
char[] charArray = data.toCharArray(); | |
for (int i = 0; i < charArray.length; ++i) { | |
char thisChar = charArray[i]; | |
boolean isPeriod = thisChar == '.'; | |
boolean isGear = thisChar == '*'; | |
SymbolType type; | |
if (isPeriod) { | |
type = SymbolType.NON_SYMBOL; | |
} else if (isGear) { | |
type = SymbolType.GEAR; | |
} else if (Character.isDigit(thisChar)) { | |
type = SymbolType.NUMBER; | |
} else { | |
type = SymbolType.REGULAR_SYMBOL; | |
} | |
row.add(i, type); | |
} | |
rows.add(row); | |
} | |
// debug | |
void printTable() { | |
for (int rowNo = 0; rowNo < rows.size(); ++rowNo) { | |
ArrayList<SymbolType> symbolRow = rows.get(rowNo); | |
System.err.print("row " + rowNo + " \t"); | |
StringBuilder sb = new StringBuilder(); | |
for (SymbolType type : symbolRow) { | |
sb.append(type.rep).append(' '); | |
} | |
System.err.println(sb); | |
} | |
} | |
private boolean isGivenType(Point pt, SymbolType expectedType) { | |
if (pt.row >= rows.size()) { | |
return false; | |
} | |
ArrayList<SymbolType> thisRow = rows.get(pt.row); | |
if (pt.col >= thisRow.size()) { | |
return false; | |
} | |
return thisRow.get(pt.col) == expectedType; | |
} | |
boolean isSymbol(Point pt) { | |
boolean isRegularSymbol = isGivenType(pt, SymbolType.REGULAR_SYMBOL); | |
return isRegularSymbol | isGivenType(pt, SymbolType.GEAR); | |
} | |
boolean isGear(Point pt) { | |
return isGivenType(pt, SymbolType.GEAR); | |
} | |
} | |
public static void main(String[] args) { | |
SymbolRecord symbols = new SymbolRecord(); | |
ArrayList<NumberRecord> numbers = new ArrayList<>(); | |
Scanner input = ProblemInputReader.getResScanner("/d3/input.txt"); | |
int rowNo = 0; | |
while (input.hasNextLine()) { | |
String line = input.nextLine(); | |
symbols.parseLine(line); | |
List<NumberRecord> numbersInLine = NumberRecord.parseLine(line, rowNo); | |
numbers.addAll(numbersInLine); | |
++rowNo; | |
} | |
int colLen = symbols.rows.getFirst().size(); | |
int[][] table = new int[symbols.rows.size()][]; | |
for (int i = 0; i < table.length; ++i) { | |
table[i] = new int[colLen]; | |
} | |
int question1Sum = numbers.stream().mapToInt((it) -> it.getQuestion1Value(symbols)).sum(); | |
int question2Sum = | |
numbers.stream().mapToInt((it) -> it.getQuestion2Value(table, symbols)).sum(); | |
symbols.printTable(); | |
System.err.format("Q1: %d, Q2: %d\n", question1Sum, question2Sum); | |
} | |
} |
This file contains hidden or 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
import java.io.InputStream; | |
import java.util.Scanner; | |
public class ProblemInputReader { | |
public static Scanner getResScanner(String resourcePath) { | |
InputStream is = ProblemInputReader.class.getResourceAsStream(resourcePath); | |
return new Scanner(is); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment