Ich habe für Teil 1 und Teil 2 verschiedene Lösungswege genutzt.
Lösungsvorschlag
private int breite;
private int hoehe;
private ArrayList<int[]> trenchList;
Deque<int[]> fillQueue = new ArrayDeque();
private char[][] map;
public int partOne() {
trenchList = new ArrayList();
int offsetX = 0;
int offsetY = 0;
int largestX = 0;
int largestY = 0;
int lastX = 0;
int lastY = 0;
trenchList.add(new int[]{0,0});
// speichere den offset für x und y
for (String line: inputLines) {
char dir = line.split(" ")[0].charAt(0);
int steps = Integer.parseInt(line.split(" ")[1]);
String color = line.split("[(]")[1].split("[)]")[0];
while (steps > 0) {
if (dir == 'R') {
trenchList.add(new int[]{lastX + 1, lastY});
lastX++;
} else if (dir == 'L') {
trenchList.add(new int[]{lastX - 1, lastY});
lastX--;
} else if (dir == 'U') {
trenchList.add(new int[]{lastX, lastY - 1});
lastY--;
} else {
trenchList.add(new int[]{lastX, lastY + 1});
lastY++;
}
steps--;
if (lastX < offsetX) {
offsetX = lastX;
}
if (lastY < offsetY) {
offsetY = lastY;
}
if (lastX > largestX) {
largestX = lastX;
}
if (lastY > largestY) {
largestY = lastY;
}
}
}
breite = largestX - offsetX + 1;
hoehe = largestY - offsetY + 1;
map = new char[breite][hoehe];
// trage für die trench ein 't' in die map ein
for (int[] k: trenchList) {
map[k[0]-offsetX][k[1]-offsetY] = 't';
}
for (int x = 0; x < breite; x++) {
if (map[x][0] == '\u0000') {
fillQueue.push(new int[]{x, 0});
fillOutside();
}
if (map[x][hoehe-1] == '\u0000') {
fillQueue.push(new int[]{x, hoehe-1});
fillOutside();
}
}
for (int y = 0; y < hoehe; y++) {
if (map[0][y] == '\u0000') {
fillQueue.push(new int[]{0, y});
fillOutside();
}
if (map[breite-1][y] == '\u0000') {
fillQueue.push(new int[]{breite-1, y});
fillOutside();
}
}
int insideCounter = 0;
for (int x = 0; x < breite; x++) {
for (int y = 0; y < hoehe; y++) {
if (map[x][y] != 'o') {
insideCounter++;
}
}
}
return insideCounter;
}
private void fillOutside() {
while (!fillQueue.isEmpty()) {
int[] k = fillQueue.pop();
int x = k[0];
int y = k[1];
if (x < 0 || y < 0 || x == breite || y == hoehe || map[x][y] != '\u0000') {
continue;
} else {
map[x][y] = 'o';
fillQueue.push(new int[]{x + 1, y});
fillQueue.push(new int[]{x - 1, y});
fillQueue.push(new int[]{x, y + 1});
fillQueue.push(new int[]{x, y - 1});
}
}
}
0 (wegen "rechts")
0 (wegen oberes Ende von "oben")
1 (wegen "rechts")
1 (wegen unteres Ende von "oben")
3 (wegen "links")
5 (wegen "rechts")
5 (wegen oberes Ende von "unten")
7 (wegen unteres Ende von "unten")
7 (wegen "links")
Nun muss man zusätzlich noch unterscheiden, ob die Eintragung jeweils das obere oder untere Ende vom Pool markiert. Platzsparend kann man dies z. B. tun, indem man die Zahlen als String abspeichert und hinten eine 0 für oberes Ende und 1 für unteres Ende anhängt. Damit steht eigentlich in der Spalte:
00
00
10
11
31
50
50
71
71
Hat man diese Werte, kann man schnell die Differenzen ausrechnen und damit die Fläche über alle Spalten aufsummieren. Wichtig ist nun, die Werte noch zu bereinigen:
y=1 hat die Endung 0 und 1 (kommt doppelt vor). Wir können daher y=1 gänzlich aus der Liste streichen. Ebenso können wir alle anderen Dopplungen streichen und müssen die Einträge sortieren (der Pfad kann "chaotisch" verlaufen und die Werte müssen nicht bereits automatisch aufsteigend sortiert sein. Am Ende bleibt übrig:
00
31
50
71
Die Fläche in der einen Spalte ist also: ( (3-1) + 1) + ( (7-5) + 1)
Lösungsvorschlag Teil 2
private ArrayList<ArrayList<Integer>> spalten;
public long partTwo() {
ArrayList<String> anweisungen = new ArrayList();
spalten = new ArrayList();
int breite = 0;
for (String line: inputLines) {
String hex = line.split("#")[1].split("[)]")[0];
int steps = Integer.parseInt(hex.substring(0, 5), 16);
// zähle alle schritte nach rechts
if (hex.substring(5).equals("0")) {
breite += steps;
}
anweisungen.add(steps + hex.substring(5));
}
ArrayList<ArrayList<String>> spalten = new ArrayList();
for (int i = 0; i < breite; i++) {
spalten.add(new ArrayList<String>());
}
int x = 0;
int y = 0;
for (String anweisung: anweisungen) {
// rechts
if (anweisung.charAt(anweisung.length()-1) == '0') {
// 0 am Ende bedeutet: ein oberes Ende vom Pool innerhalb der Spalte
spalten.get(x).add(y + "" + 0);
int steps = Integer.parseInt(anweisung.substring(0, anweisung.length()-1));
for (int i = 0; i < steps; i++) {
x = (x+1) % breite;
spalten.get(x).add(y + "" + 0);
}
}
// unten
else if (anweisung.charAt(anweisung.length()-1) == '1') {
spalten.get(x).add(y + "" + 0);
int steps = Integer.parseInt(anweisung.substring(0, anweisung.length()-1));
y += steps;
spalten.get(x).add(y + "" + 1);
}
// links
else if (anweisung.charAt(anweisung.length()-1) == '2') {
// 1 am Ende bedeutet: ein unteres Ende vom Pool innerhalb der Spalte
spalten.get(x).add(y + "" + 1);
int steps = Integer.parseInt(anweisung.substring(0, anweisung.length()-1));
for (int i = 0; i < steps; i++) {
x--;
if (x < 0) {
x = breite - 1;
}
spalten.get(x).add(y + "" + 1);
}
}
// oben
else if (anweisung.charAt(anweisung.length()-1) == '3') {
spalten.get(x).add(y + "" + 1);
int steps = Integer.parseInt(anweisung.substring(0, anweisung.length()-1));
y -= steps;
spalten.get(x).add(y + "" + 0);
}
}
long summe = 0;
// Gehe über jede Spalte
for (ArrayList<String> spalte: spalten) {
// entferne alle vollständigen dopplungen (wandelt es in ein "sortiertes" Set um (alles kann dort nur einmalig vorkommen))
Set<String> set = new LinkedHashSet<>(spalte);
spalte.clear();
spalte.addAll(set);
// sortiere
spalte = sortArrayList(spalte);
// prüfe nun, ob direkte Nachfolger in allen Zeichen exklusive dem letzten übereinstimmen -> y-koordinate gleichzeitig oberes und unteres Ende -> kann entfernt werden.
for (int i = 0; i < spalte.size() - 1; i++) {
if (spalte.get(i).substring(0, spalte.get(i).length()-1).equals(spalte.get(i+1).substring(0,spalte.get(i+1).length()-1))) {
spalte.remove(i);
spalte.remove(i); //zweimal i, da durch das erste Löschen die hinteren Elemente 1 nach vorne rücken
i--;
}
}
for (int i = 0; i < spalte.size(); i = i+2) {
summe += Integer.parseInt(spalte.get(i+1).substring(0, spalte.get(i+1).length()-1)) - Integer.parseInt(spalte.get(i).substring(0, spalte.get(i).length()-1)) + 1;
}
}
return summe;
}
/**
* Selection-Sort, um die Werte pro Spalte nach Zahlenwert zu sortieren.
*/
private ArrayList<String> sortArrayList(ArrayList<String> input) {
for (int i = 0; i < input.size(); i++) {
int min = i;
for (int j = i; j < input.size(); j++) {
if (Integer.parseInt(input.get(j).substring(0, input.get(j).length()-1)) < Integer.parseInt(input.get(min).substring(0, input.get(min).length()-1))) {
min = j;
}
}
String temp = input.get(min);
input.set(min, input.get(i));
input.set(i, temp);
}
return input;
}