Tag 6 ist eine klassische Aufgabe, die man gut in einem zweidimensionalen Array lösen kann. Besonders Teil 1 ließe sich theoretisch auch ohne einem Array lösen, indem man nur die Koordinaten der Hindernisse miteinander vergleicht/verrechnet und sich so von Hindernis zu Hindernis hangelt. Mit dem Array geht es aber intuitiver.
Teil 2 macht manches insofern etwas schwerer, als dass man sich nun zum Einen merken muss, an welcher Stelle man bereits in welcher Richtung entlang gelaufen ist um Loops zu erkennen. Zum Anderen muss man in einer weiteren Schleife das Hindernis jedes Mal an eine neue Stelle setzen und gleichzeitig die vorherigen Markierungen löschen bzw. eine Startvorlage der Karte kopieren.
Lösungsvorschlag
public void partTwo() {
int width = inputLines.get(0).length();
int height = inputLines.size();
int startX = 0;
int startY = 0;
// Kopiere den Input in ein zweidimensionales Array
char[][] originalMap = new char[width][height];
for (int y = 0; y < height; y++) {
String line = inputLines.get(y);
for (int x = 0; x < width; x++) {
char c = line.charAt(x);
if (c == '^') {
// Speichere die Richtung, in die sich der Guard zu Beginn bewegt.
originalMap[x][y] = (char)(0+'0'); // Die Schreibweise sorgt dafür, dass die Zahl 0 als lesbarer char 0 abgespeichert wird.
startX = x;
startY = y;
}
else {
originalMap[x][y] = c;
}
}
}
int direction = 0;
int obstructions = 0; // zähle die möglichen neuen Hindernis-Koordinaten
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
char[][] map = new char[width][height];
for (int mx = 0; mx < width; mx++) {
for (int my = 0; my < height; my++) {
map[mx][my] = originalMap[mx][my];
}
}
// Setze die Richtung des Guards zu Beginn auf 0
direction = 0;
// Das Hindernis darf weder auf ein anderes Hindernis noch auf die Startposition gesetzt werden.
if (map[x][y] == '#' || (startX == x && startY == y)) {
continue;
}
// Platziere das Hindernis
map[x][y] = '#';
// Platziere den "imaginären" Guard auf die Startposition
int guardX = startX;
int guardY = startY;
while(true) {
int nextX, nextY;
if (direction == 0) { // up
nextX = guardX;
nextY = guardY-1;
} else if (direction == 1) { // right
nextX = guardX+1;
nextY = guardY;
} else if (direction == 2) {// down
nextX = guardX;
nextY = guardY+1;
} else { //left
nextX = guardX-1;
nextY = guardY;
}
// wenn ich in ein Hindernis reinlaufe, dann abbiegen
if (map[nextX][nextY] == '#') {
direction = (direction + 1) % 4;
// Wenn ich in eine Koordinate laufe, an deren Stelle ich schon einmal in dieselbe Richtung gelaufen bin...
} else if (map[nextX][nextY] == (char)(direction+'0')) {
obstructions++;
break; // ... dann kann ich die Endlosschleife abbrechen
} else {
guardX = nextX;
guardY = nextY;
// Markiere in der Map, dass ich hier bereits in die aktuelle Richtung gelaufen bin
map[guardX][guardY] = (char)(direction+'0');
}
// Wenn ich die Spielfläche gleich verlasse, dann kann ich abbrechen
if (guardX == 0 || guardX == width - 1 || guardY == 0 || guardY == height - 1) {
break;
}
}
map[x][y] = '.';
}
}
System.out.println(obstructions);
}