faecher:informatik:oberstufe:java:aoc:aoc2024:day03:start

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

faecher:informatik:oberstufe:java:aoc:aoc2024:day03:start [03.12.2024 14:48] – angelegt Marco Kuemmelfaecher:informatik:oberstufe:java:aoc:aoc2024:day03:start [03.12.2024 15:53] (aktuell) Marco Kuemmel
Zeile 45: Zeile 45:
             result +=  num1 * num2;             result +=  num1 * num2;
         }         }
 +    }
 +
 +    System.out.println(result);
 +}
 +</code>
 +++++
 +
 +===== Teil 2 =====
 +Für Teil 2 ist zunächst essenziell, dass man die komplette Datei als **einen zusammenhängenden String** betrachtet - **nicht** Zeile für Zeile!
 +
 +Die Regel mit ''don't()'' und ''do()'' kann man wie folgt angehen. Man kann weiterhin denselben Code wie aus Teil 1 nutzen, allerdings darf man dies eben nicht auf den gesamten Text anwenden, sondern man muss bestimmte Teil im Text entfernen. 
 +++ Was muss entfernt werden? |
 +Entfernt werden muss alles **nach** einem ''don't()'' und bis zum ersten folgenden ''do()''.
 +++
 +
 +Wenn man dies auf einen Eingabe-String ''eingabe'' anwenden will, funktioniert das mit folgendem Befehl: ''eingabe.replaceAll("HIER_STEHT_DIE_REGEX", "")''. Das zweite Argument gibt an, durch was der gefundene String ersetzt werden soll (=Empty String, entpricht also einer Löschung).
 +++ Wie sieht die Regex aus? |
 +''don't\\(\\).*?do\\(\\)''
 +++
 +
 +Hier ist bereits berücksichtigt, dass in Java doppelt escaped wird. Sehr knifflig ist der mittlere Abschnitt ''.*?''. Die ersten zwei Zeichen sind in der Kombination häufig anzutreffen: Zwischen don't() und do() dürfen beliebige Zeichen (''.'') beliebig häufig (''*'') vorkommen. Allerdings möchte man ja nur so wenig löschen, wie es geht. In einem String wie ''don't()aaa_do()bbb_do()'' soll nicht erst beim letzten ''do()'' gestoppt werden, sondern bereits beim ersten. Reguläre Ausdrücke arbeiten aber standardmäßig **greedy** (also gierig) und suchen nach langen Mustern. Um sie **lazy** (faul) zu machen, muss man zusätzlich ein Fragezeichen ''?'' anhängen. Die 3 Zeichen könnte man also lesen als //so viele Zeichen wie **nötig**//.
 +
 +++++ Lösungsvorschlag |
 +<code java>
 +public void partTwo() {
 +    // Speichere, welche Form die mul-Operatoren haben
 +    // Bei Java müssen Sonderzeichen doppelt-escaped werden: \\ 
 +    Pattern pattern = Pattern.compile("mul\\(\\d{1,3},\\d{1,3}\\)");
 +    
 +    long result = 0;
 +
 +    String allLines = "";
 +    for (String line: inputLines) {
 +        allLines += line;
 +    }
 +
 +    allLines = allLines.replaceAll("don't\\(\\).*?do\\(\\)", "");
 +    
 +    /* Eventuell muss man hier noch nachträglich prüfen, ob es zum Ende ein
 +     * don't() OHNE nachfolgendes do() gibt. Dann muss der komplette Rest
 +     * "abgeschnitten" werden. Bei meinem Input war es nicht nötig.
 +     */
 +
 +    Matcher matcher = pattern.matcher(allLines);
 +
 +    while (matcher.find()) {
 +        String mul = matcher.group();
 +        int num1 = Integer.parseInt(mul.split(",")[0].split("\\(")[1]);
 +        int num2 = Integer.parseInt(mul.split(",")[1].split("\\)")[0]);
 +        result +=  num1 * num2;
     }     }
  
  • faecher/informatik/oberstufe/java/aoc/aoc2024/day03/start.1733237330.txt.gz
  • Zuletzt geändert: 03.12.2024 14:48
  • von Marco Kuemmel