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

Tag 14 - Parabolic Reflector Dish

Der heutige Tag war wieder verhältnismäßig einfach, wenn man im Hinterkopf hat, wie man bereits Tag 12 lösen konnte.
  • Speichere die Eingabe als zweidimensionales Character-Array.
  • Rufe dann eine Methode auf, die dafür sorgt, dass jedes O soweit nach oben wie möglich bewegt wird:
    • Erzeuge ein neues, gleich großes char-Array, in welches du die aktualisierten Werte einträgst.
    • Gehe spaltenweise über das ursprüngliche Array, fange mit der linken Spalte an. Du gehst von oben nach unten über jede Zelle.
      • Wenn an der Position (x,y) # oder . gespeichert ist, dann wird dies genau so ins neue Array über- bzw. eingetragen.
      • Wenn an der Position (x,y) O gespeichert ist, dann musst du für alle darüberliegenden Werte im neuen Array prüfen, ob O auch dort gespeichert werden könnte. Lege dir dafür ein dx an, welches bei x beginnt und so lange reduziert wird (nach oben geht) wie dort ein . gespeichert ist. Speichere dann bei (dx,y) das O und stelle sicher, dass bei (x,y) ein . gespeichert ist. Dann geht es wieder regulär beim nächsten x weiter.
  • Am Ende iterierst du wieder über alle Zellen. Wenn die Zelle O enthält, dann addierst du den Zeilenwert zur Summe.

Lösungsvorschlag

  • Lege noch zwei weitere Methoden für die Richtungen links, unten und rechts an! Du kannst bei der bisherigen Methode copy-pasten, musst nur beim Anpassen der x-/y-Werte bzw. der dx-/dy-Werte aufpassen.
  • Würdest du alle 1 Milliarde Rotationen ausrechnen, dann würde es Ewigkeiten dauern! Die Wahrscheinlichkeit ist ja aber sehr groß, dass sich nach ein paar Rotationen schließlich eine Situation eingefunden hat, die nach ein paar weiteren Rotationen exakt wieder so vorkommt (und so ist es auch!). Du landest also schließlich in einer Art Schleife, sodass immer wieder nach x-Rotationen die gleiche Ausgangslage gefunden ist. Das machen wir uns zunutze und speichern uns nach jeder Rotation den exakten Zustand und die Zahl des Durchlaufs / der Rotation. Nach jeder Rotation prüfen wir also, ob wir diesen Array-Zustand schon einmal hatten oder nehmen ihn neu in unsere Sammlung auf. Sobald es einen Treffer (= eine Wiederholung) gibt, können wir uns die Differenz diff vom ersten Vorkommnis und dem jetzigen Durchlauf ausrechnen. Es ist klar, dass nun immer nach diff Rotationen wieder derselbe Zustand vorgefunden werden würde. Wir können nun also direkt so häufig diff auf den aktuellen Durchlauf drauf addieren, solange der Wiederholungs-Counter kleiner 1 Milliarde ist. Nur die letzten paar Rotationen müssen nochmals explizit durchgeführt werden.
  • Zum Speichern dieser Array-Zustände und der Zahl der Rotation nutzen wir eine HashMap. Diese muss pro Eintrag immer aus zwei Werten bestehen: einem Key und einem Value. Der Key beschreibt den eindeutigen Array-Zustand und der Value ist die Zahl der Rotation. Um den Array-Zustand eindeutig zu beschreiben bietet es sich z. B. an, einen String zu erstellen der aus den zeilenweise gelesenen Abständen aller O's zueinander besteht. Eine Zeile mit OO..O.##O würde Z. B. zu 0023 werden.

Lösungsvorschlag

  • faecher/informatik/oberstufe/java/aoc/aco2023/day14/start.txt
  • Zuletzt geändert: 14.12.2023 15:57
  • von Marco Kuemmel