faecher:informatik:oberstufe:java:aoc:aco2023:day20:start

Tag 20 - Pulse Propagation

  • Die Pulse können mit einer eigenen Klasse dargestellt werden. Jeder Puls hat einen Vorgänger, einen Nachfolger und einen Zustand (z. B. 1/0 für high/low).

Lösungsvorschlag Pulse

  • Da verschiedene Pulse-Module vorkommen (insbesondere Flip-Flops und Conjunctions), die intern unterschiedlich funktionieren aber auf gleiche Weise genutzt werden, bietet sich eine OOP-Lösung inklusive Vererbung an. Speichere jede Zeile als in PulseModule und speichere alle PulseModules in einer HashMap.
  • Die Oberklasse PulseModule ist abstrakt. Jede Unterklasse muss ihren eigenen Namen kennen und die Namen aller Nachfolger-Module. Außerdem muss jede Unterklasse die Methode pulse() besitzen. Diese berechnet, welche Ausgabepulse bei einem gegebenen Eingabepuls entstehen.

Lösungsvorschlag PulseModule

  • Die erste Unterklasse FlipFlop muss den aktuellen Zustand speichern können und ansonsten nur die pulse()-Methode implementieren.

Lösungsvorschlag FlipFlop

  • Die zweite Unterklasse Conjunction muss als Besonderheit zu jedem der Vorgänger/Eingänge den letzten Zustand speichern (z. B. in einer HashMap). Die pulse()-Methode muss natürlich anders implementiert werden

Lösungsvorschlag Conjunction

  • Der letzte Modul-Typ "Broadcaster" ist relativ langweilig, da er keine besondere Funktion hat.

Lösungsvorschlag Broadcaster

  • Erstelle aus jeder Eingabezeile die nötigen Puls-Module, die alle auch vom Typ der Oberklasse PulseModule sind. Daher kannst du alle in einer HashMap<String,PulseModule> speichern. Mit dieser HashMap kannst du für jeden Modulnamen (key) sofort das dazugehörige Modul bekommen, egal, ob es ein FlipFlop oder eine Conjunction ist.
  • Du musst nach dem Erstellen der Module noch ein zweites Mal über jedes erstellte Modul iterieren, um die Vorgänger in die Conjunctions eintragen zu können (damit jede Conjunction Buch führen kann, ob ihre Vorgänger jeweils high oder low waren).
  • Um einen einzelnen Durchlauf (Knopfdruck bis Ende) zu erreichen, und die Pulse in der richtigen Reihenfolge abzuarbeiten, musst du eine Queue nutzen. Stecke zu Beginn die Broadcast-Pulse in die Queue. Dann iteriere in einer while-Schleife solange die Schleife nicht leer ist:
    • nimm dir den nächsten Pulse aus der Queue
    • zähle, ob der Pulse high oder low ist
    • hole dir mithilfe des Ziels des Pulses das nächste Module aus der HashMap
    • rufe auf dem Module die pulse()-Methode auf und lass dir alle nachfolgenden Pulse zurückgeben
    • speichere jeden Nachfolge-Pulse in der Queue
  • Tue diese letzten Schritt Knopfdruck-Durchlauf wiederum 1000 Mal

Lösungsvorschlag Teil 1

  • Für Teil 2 ist es wichtig, den folgenden Kniff zu sehen: Der Output ist low, wenn alle Eingänge der letzten Conjunction high sind. Dies passiert aber erst nach vielen Billionen (!) Iterationen. Daher muss man noch einen Schritt weiter denken: Schaue dir jeden Vorgänger der letzten Conjunction an und speichere dir, wann diese Module jeweils einzeln einen high-Pulse an die letzte Conjunction aussenden! Multipliziere am Ende alle diese minimalen Iterationen für die jeweiligen high-Pulses.

Lösungsvorschlag Teil 2

  • faecher/informatik/oberstufe/java/aoc/aco2023/day20/start.txt
  • Zuletzt geändert: 24.12.2023 22:57
  • von Marco Kuemmel