Grundidee: Wir verfahren ganz ähnlich wie in Teil 1, markieren aber im rekursiven Aufruf alle Felder einer Region als "gerade markiert" ('2'). Direkt nach der Rekursion gehen wir über das gesamte Feld und suchen an den Spalten und Zeilen die Grenzübergänge von den "gerade markierten" Feldern zu den Nachbarfeldern. (Eine ziemlich "unschöne", aber funktionale Lösung.)
public void partTwo() {
width = inputLines.get(0).length();
height = inputLines.size();
farm = new char[width][height][2];
// 2. Char in dritter Dimension:
// 0: bereits besucht/bearbeitet
// 1: neu
// 2: gerade markiert
for (int y = 0; y < height; y++) {
String line = inputLines.get(y);
for (int x = 0; x < width; x++) {
farm[x][y][0] = line.charAt(x);
farm[x][y][1] = '1';
}
}
int price = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (farm[x][y][1] == '1') {
area = 0;
perimeter = 0;
//findRegion2() funktioniert fast gleich wie zuvor: bloß der perimeter-Teil ist hier nicht mehr nötig
findRegion2(farm[x][y][0], x, y);
// NEU: zähle nun alle durchgehenden Kanten an denjenigen Feldern,
// die innerhalb von findRegion2() als '2' ("gerade markiert") gekennzeichnet wurden
perimeter = countFences();
price += area*perimeter;
}
}
}
System.out.println(price);
}
// "Hardcoding": läuft alle horizontalen und vertikalen Kanten zwischen den Spalten/Zeilen
// UND am Rand entlang, um zusammenhängende Grenzen zu erfassen.
private int countFences() {
int counter = 0;
// oberer Rand
boolean counting = false;
for (int x = 0; x < width; x++) {
if (farm[x][0][1] == '2') {
counting = true;
} else if (counting) {
counter++;
counting = false;
}
}
if (counting) {
counter++;
}
//mittlere Zeilen, jeweils zu den oberen nachbarn
for (int y = 1; y < height; y++) {
// zähle Grenzen nach OBEN
counting = false;
for (int x = 0; x < width; x++) {
if (farm[x][y][1] == '2' && farm[x][y][0] != farm[x][y-1][0]) {
counting = true;
} else if (counting) {
counter++;
counting = false;
}
}
if (counting) {
counter++;
}
}
//mittlere Zeilen, jeweils zu den unteren nachbarn
for (int y = 0; y < height-1; y++) {
// zähle Grenzen nach UNTEN
counting = false;
for (int x = 0; x < width; x++) {
if (farm[x][y][1] == '2' && farm[x][y][0] != farm[x][y+1][0]) {
counting = true;
} else if (counting) {
counter++;
counting = false;
}
}
if (counting) {
counter++;
}
}
// unterer Rand
counting = false;
for (int x = 0; x < width; x++) {
if (farm[x][height-1][1] == '2') {
counting = true;
} else if (counting) {
counter++;
counting = false;
}
}
if (counting) {
counter++;
}
// linker Rand
counting = false;
for (int y = 0; y < height; y++) {
if (farm[0][y][1] == '2') {
counting = true;
} else if (counting) {
counter++;
counting = false;
}
}
if (counting) {
counter++;
}
//mittlere spalten, jeweils zu den linken nachbarn
for (int x = 1; x < width; x++) {
// zähle Grenzen nach LINKS
counting = false;
for (int y = 0; y < height; y++) {
if (farm[x][y][1] == '2' && farm[x][y][0] != farm[x-1][y][0]) {
counting = true;
} else if (counting) {
counter++;
counting = false;
}
}
if (counting) {
counter++;
}
}
//mittlere spalten, jeweils zu den rechten nachbarn
for (int x = 0; x < width-1; x++) {
// zähle Grenzen nach RECHTS
counting = false;
for (int y = 0; y < height; y++) {
if (farm[x][y][1] == '2' && farm[x][y][0] != farm[x+1][y][0]) {
counting = true;
} else if (counting) {
counter++;
counting = false;
}
}
if (counting) {
counter++;
}
}
// rechter Rand
counting = false;
for (int y = 0; y < height; y++) {
if (farm[width-1][y][1] == '2') {
counting = true;
} else if (counting) {
counter++;
counting = false;
}
}
if (counting) {
counter++;
}
// setze '2' auf '0'
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (farm[x][y][1] == '2') {
farm[x][y][1] = '0';
}
}
}
return counter;
}
private void findRegion2(char c, int x, int y) {
if (x < 0 || x >= width || y < 0 || y >= height) {
return;
}
if (farm[x][y][1] != '1' || farm[x][y][0] != c) {
return;
}
area++;
farm[x][y][1] = '2';
findRegion2(c, x-1, y);
findRegion2(c, x+1, y);
findRegion2(c, x, y-1);
findRegion2(c, x, y+1);
}