Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
Nächste Überarbeitung | Vorherige Überarbeitung | ||
faecher:informatik:oberstufe:java:aoc:aco2023:day12:start [12.12.2023 18:45] – angelegt 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 ===== | ||
- | Teil 2 ist definitiv nicht trivial. Beide einfachen Ansätze aus Teil 1 genügen hier nicht mehr, da mehrere Milliarden | + | //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 | ||
+ | * 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, dann muss man sich zuerst um die Abbruchbedingungen kümmern. Davon gibt es mehrere, u. a.: | ||
+ | * 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 | ||
+ | ++++ 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; | ||
+ | } | ||
+ | </ | ||
+ | ++++ | ||
</ | </ | ||
</ | </ |