Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
Beide Seiten, vorherige Überarbeitung Vorherige Überarbeitung Nächste Überarbeitung | Vorherige Überarbeitung | ||
faecher:informatik:oberstufe:java:aoc:aco2023:day12:start [15.12.2023 17:49] – Marco Kuemmel | faecher:informatik:oberstufe:java:aoc:aco2023:day12:start [15.12.2023 18:42] (aktuell) – Marco Kuemmel | ||
---|---|---|---|
Zeile 59: | Zeile 59: | ||
===== Teil 2 ===== | ===== Teil 2 ===== | ||
- | //Mit 3 Tagen Verspätung nun auch endlich eine ausformulierte Lösung für Teil 2...//\\ | + | //Mit 3 Tagen Verspätung nun auch endlich eine ausformulierte Lösung für Teil 2... (danke an Frank Schiebel für den Impuls 😊)//\\ |
Teil 2 ist definitiv nicht trivial. Beide einfachen Ansätze aus Teil 1 genügen hier nicht mehr, da (je nach Eingabedatei) etwa 1,6 Billionen (!) Kombinationen durchprobiert werden müssten! Man muss sich daher dringend die " | Teil 2 ist definitiv nicht trivial. Beide einfachen Ansätze aus Teil 1 genügen hier nicht mehr, da (je nach Eingabedatei) etwa 1,6 Billionen (!) Kombinationen durchprobiert werden müssten! Man muss sich daher dringend die " | ||
* Rufe pro Eingabezeile eine rekursive Methode '' | * Rufe pro Eingabezeile eine rekursive Methode '' | ||
+ | * Die Methode '' | ||
+ | * Der ganz entscheidende Punkt ist es, direkt zu Beginn innerhalb der Methode zu prüfen, ob die rekursive Methode bereits mit denselben Parametern aufgerufen wurde. Man speichert sich für jeden Parameter unmittelbar vor dem '' | ||
+ | * Eine gute Datenstruktur dazu ist die '' | ||
+ | * Wurde der Key bisher noch __nicht__ in die HashMap eingetragen, | ||
+ | * Genügt die Anzahl an String-Buchstaben um alle Zahlen-Vorkommnisse im besten Falle unterzubringen? | ||
+ | * Ist der String empty? | ||
+ | * Gibt es keine Zahlen mehr, sodass keine " | ||
+ | * Anschließend muss in Abhängigkeit des __ersten__ Characters vom String vielfach unterschieden werden. Je nachdem, ob der erste Buchstabe ein '' | ||
+ | * Bei einem '' | ||
+ | * Bei einem ''#'' | ||
+ | * Bei einem ''?'' | ||
+ | * Immer bei einer Abbruchbedingung gibt es entweder den Fall, dass dies zu einem oder zu keinem Match führt. In der Summe führt das insgesamt zu Billionen (!) Fällen, die dank der dynamischen Programmierung in einigen Millisekunden (!) berechnet werden können. | ||
+ | ++++ Lösungsvorschlag Teil 2 | | ||
+ | <code java> | ||
+ | public long partTwo() { | ||
+ | long summe = 0; | ||
+ | | ||
+ | int zeile = 0; | ||
+ | for (String line: inputLines) { | ||
+ | String s = line.split(" | ||
+ | int[] numbers = strToIntArray(s + "," | ||
+ | | ||
+ | cache = new HashMap< | ||
+ | long arrangements = 0; | ||
+ | String input = line.split(" | ||
+ | arrangements = getMatches(input + "?" | ||
+ | summe += arrangements; | ||
+ | } | ||
+ | | ||
+ | return summe; | ||
+ | } | ||
+ | |||
+ | private long getMatches(String input, int[] numbers) { | ||
+ | // berechne key: | ||
+ | String key = input; | ||
+ | for (int n: numbers) { | ||
+ | key += n + " | ||
+ | } | ||
+ | | ||
+ | // prüfe, ob key bereits vorhanden... | ||
+ | if (cache.containsKey(key)) { | ||
+ | return cache.get(key); | ||
+ | } | ||
+ | | ||
+ | // wenn input nicht mehr ausreicht für noch zu treffende matches | ||
+ | int summeZahlen = 0; | ||
+ | for (int n: numbers) { | ||
+ | summeZahlen += n; | ||
+ | } | ||
+ | if (input.length() < summeZahlen + numbers.length - 1) { | ||
+ | cache.put(key, | ||
+ | return 0; | ||
+ | } | ||
+ | | ||
+ | // leerer input | ||
+ | if (input.length() == 0) { | ||
+ | if (numbers.length > 0) { | ||
+ | cache.put(key, | ||
+ | return 0; | ||
+ | } else { | ||
+ | cache.put(key, | ||
+ | return 1; | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | // keine zahlen mehr | ||
+ | if (numbers.length == 0) { | ||
+ | if (input.contains("#" | ||
+ | cache.put(key, | ||
+ | return 0; | ||
+ | } else { | ||
+ | cache.put(key, | ||
+ | return 1; | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | // wenn input mit . beginnt | ||
+ | if (input.charAt(0) == ' | ||
+ | long res = getMatches(input.substring(1), | ||
+ | cache.put(key, | ||
+ | return res; | ||
+ | } | ||
+ | // wenn input mit # beginnt | ||
+ | else if (input.charAt(0) == '#' | ||
+ | // prüfe, dass anzahl an vorderen # für erste Zahl ausreicht. | ||
+ | | ||
+ | for (int i = 0; i < numbers[0]; i++) { | ||
+ | // -> reicht nicht | ||
+ | if (input.charAt(i) == ' | ||
+ | cache.put(key, | ||
+ | return 0; | ||
+ | } | ||
+ | } | ||
+ | // -> reicht | ||
+ | | ||
+ | String next = input.substring(1); | ||
+ | int[] nextNumbers; | ||
+ | // wenn erste Zahl nur noch 1 ist | ||
+ | if (numbers[0] == 1 && next.length() > 0) { | ||
+ | if (next.charAt(0) == '#' | ||
+ | cache.put(key, | ||
+ | return 0; | ||
+ | } else if (next.charAt(0) == '?' | ||
+ | next = ' | ||
+ | } | ||
+ | | ||
+ | // entferne die vorderste Zahl | ||
+ | nextNumbers = new int[numbers.length - 1]; | ||
+ | for (int i = 0; i < numbers.length - 1; i++) { | ||
+ | nextNumbers[i] = numbers[i+1]; | ||
+ | } | ||
+ | long res = getMatches(next, | ||
+ | cache.put(key, | ||
+ | return res; | ||
+ | } else if (numbers[0] == 1 && next.length() == 0) { | ||
+ | cache.put(key, | ||
+ | return 1; | ||
+ | } | ||
+ | | ||
+ | // wenn nächstes Zeichen ? ist, muss es # werden | ||
+ | if (next.charAt(0) == '?' | ||
+ | next = '#' | ||
+ | } | ||
+ | | ||
+ | numbers[0] = numbers[0] - 1; | ||
+ | long res = getMatches(next, | ||
+ | cache.put(key, | ||
+ | return res; | ||
+ | } | ||
+ | // wenn input mit '?' | ||
+ | else if (input.charAt(0) == '?' | ||
+ | long res = getMatches(' | ||
+ | + getMatches('#' | ||
+ | cache.put(key, | ||
+ | return res; | ||
+ | } | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | ++++ | ||
</ | </ | ||
</ | </ |