Skip to content

Instantly share code, notes, and snippets.

@lry127
Last active September 13, 2024 11:44
Show Gist options
  • Save lry127/ad8335216d4737bff3056b6a1cef95e8 to your computer and use it in GitHub Desktop.
Save lry127/ad8335216d4737bff3056b6a1cef95e8 to your computer and use it in GitHub Desktop.
Advent of code Day 3 solution in Java
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);
}
}
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