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

Day 4: Ceres Search

Der heutige Tag ist gar nicht mal so schwer, sobald man 1-2 mögliche Kniffe erkannt hat, wie man die Lösung angehen kann.

Klar ist, dass man den Input in einem zweidimensionalen Array speichern muss. Als Datentyp ist char allerdings nicht wirklich geeignet, da wir ja bestimmte Abfolgen in dem Text erkennen müssen. int bietet sich daher viel besser an!

Übertrage also als Erstes den Input in ein zweidimensionales int-Array, wobei X=1, M=2, A=3, S=4 ist.

Anschließend müssen wir nun alle Vorkommnisse der Zahlenfolge 1234 in dem Array finden (auch rückwärts, diagonal, etc). Es wäre absolut ungünstig, für jede der 8 Richtungen, in die man suchen muss, eine eigene Methode/Strategie zu entwickeln. Klar ist also, wir brauchen eine Lösung, die alle 8 Richtungen universell abdecken kann.

Folgende Vorgehensweise bietet sich an: Suche den Startpunkt jeder Folge, also eine 1. Starte von dort ausgehend dann die Suche in alle 8 Richtungen. Diese 8 Richtungen weisen sich dadurch aus, dass man sich pro Schritt sowohl in x- als auch in y-Richtung jeweils -1, 0 oder +1 bewegt. Man kann also vom Startpunkt aus eine verschachtelte Schleife starten, die alle Kombinationen der delta-x und delta-y Schrittweiten abdeckt. Diese verschachtelte Schleife soll uns also z. B. die Schrittkombination (dx=-1, dx=-1) → nach links oben, (dx=0, dy=-1) → nach mittig oben, etc geben.

Innerhalb dieser verschachtelten Schleife bietet sich nun eine rekursive Methode an, die sich jeweils um die dx- und dy-Werte weiterbewegt und dabei jeweils prüft, ob an der nächsten Position der nächsthöhere int-Werte gefunden wird. Schafft diese Methode es, alle Zahlen bis inkl. der 4 zu finden, so kann 1 zurückgegeben werden (ein weiteres XMAS wurde gefunden). Andernfalls wird 0 zurückgegeben. Mit einer 0 abbrechen muss die Methode sowohl, wenn die Arraygrenzen überschritten werden, als auch, wenn die nächstes gefundene Zahl falsch ist.

Lösungsvorschlag

Auch Teil 2 lässt sich tatsächlich besonders einfach lösen, wenn wir zuvor die Buchstaben in die Zahlen 1-4 umwandeln. Die 1 für das X interessiert uns hier gar nicht mehr.

Eine wichtige Erkenntnis ist, dass die Mitte des Kreuzes immer einen Abstand von 1 zu allen Rändern des Arrays haben muss! Wir starten unsere Suche nach allen möglichen Kreuz-Mitten (also nach allen Vorkommnissen von A=3).

Für jede gefundene 3 müssen wir nun prüfen, ob die päärchenweise diagonal gegenüberliegenden Buchstaben ein M und ein S sind. Als Zahlen ausgedrückt sind das die Zahlen 2 und 4. Wir können also prüfen, ob die jeweils diagonal gegenüberliegenden Zahlen in der Summe die Zahl 6 ergeben! Mit diesem Kniff müssen wir nicht extra prüfen, ob z. B. das M nun links oben oder rechts unten war. Wir müssen bloß sicherstellen, dass nicht eine der Zahlen eine 3 war (denn auch 3+3, also diagonal gegenüberliegende A's) ergeben die Zahl 6.

Lösungsvorschlag

  • faecher/informatik/oberstufe/java/aoc/aoc2024/day04/start.txt
  • Zuletzt geändert: 04.12.2024 08:08
  • von Marco Kuemmel