Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| lehrkraefte:blc:informatik:ffprg2-2023:aufgabe3 [2023/11/14 07:10] – [Wortbaum] Ivo Blöchliger | lehrkraefte:blc:informatik:ffprg2-2023:aufgabe3 [2023/11/14 07:24] (current) – [Aufgabe 3] Ivo Blöchliger | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Aufgabe 3 ====== | ||
| + | Gegeben ist eine Aufteilung in Regionen und die Wörter in den Regionen. | ||
| + | Es soll jetzt überprüft werden, ob das Puzzle eine eindeutige Lösung hat. | ||
| + | |||
| + | Dazu wird ein Algorithmus gesucht, der systematisch das Puzzle versucht zu lösen, indem dieser sämtliche Möglichkeiten durchprobiert. Sobald eine zweite Lösung gefunden wurde, kann der Algorithmus abgebrochen werden. Ansonsten muss er fertig laufen. | ||
| + | |||
| + | «Alles durchprobieren» ist je nach Definition von «alles» praktisch schlicht unmöglich. Die Idee ist, möglichst früh sagen zu können, dass mit der bereits getroffenen Wahl keine Lösung möglich ist. | ||
| + | |||
| + | Dazu verwenden wir folgende zwei Eigenschaften: | ||
| + | * Nur Wörter aus der Wortliste sind zugelassen. | ||
| + | * Die Region, die von einem Wort belegt wird, muss zusammenhängend und zwischen 4 und 8 Felder umfassen. | ||
| + | |||
| + | |||
| + | <WRAP todo> | ||
| + | Navigieren Sie in das Verzeichnis funkmast und «checken» Sie den «tag» a3 aus: | ||
| + | |||
| + | <code bash> | ||
| + | git fetch --all --tags | ||
| + | git checkout tags/a3 | ||
| + | git switch -c dev | ||
| + | </ | ||
| + | </ | ||
| + | ===== Vorschlag zur Implementation ===== | ||
| + | Folgende Feststellung ist zentral für den Algorithmus: | ||
| + | * Das Feld am meisten link in der obersten Zeile, die noch freie Zellen hat, ist zwingend ein Wortanfang (vorausgesetzt, | ||
| + | |||
| + | ==== Wortbaum ==== | ||
| + | Die Idee ist, alle Wörter der Wortliste möglichst schnell und effizient durchprobieren zu können. Da jeweils der, bzw. die ersten Buchstaben gegeben sind, brauchen wir schnellen Zugriff auf alle Wörter die mit gegebenen Buchstaben beginnent. Dazu wird die Liste in einem Baum gespeichert, | ||
| + | |||
| + | Jeder Knoten hat maximal 27 Einträge, ' | ||
| + | |||
| + | Die Liste [" | ||
| + | <code javascript> | ||
| + | {' | ||
| + | </ | ||
| + | Der Clue ist, dass einfach bei dem Unterbaum weitergearbeitet werden kann, der durch die bereits gegebenen Buchstaben erreicht werden kann. Dazu reicht es, die Referenz auf den Unterbaum zu haben, es brauchen keine weiteren Daten kopiert oder gespeichert zu werden. | ||
| + | |||
| + | Dieser Baum muss nur einmal aus der Wortliste erstellt werden. | ||
| + | |||
| + | ==== tryNextLetter(used, | ||
| + | |||
| + | Diese Funktion liefert ein Array von möglichen Wörtern, die bei der obersten, am meisten links liegenden freien Zellen starten. Ein Wort ist wie die Variable '' | ||
| + | Ist das Array leer, heisst das, dass die vorhergehende Platzierung nicht möglich ist und diese schrittweise rückgängig gemacht werden muss. | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | Beim ersten Aufruf wird die Funktion mit '' | ||
| + | |||
| + | |||
| + | Die Funktion initialisiert das Array '' | ||
| + | * Ist '' | ||
| + | * Bei einem normalen Buchstaben '' | ||
| + | * Position zu '' | ||
| + | * '' | ||
| + | * Position wieder aus '' | ||
| + | |||
| + | |||
| + | ==== connected(coords) ==== | ||
| + | Diese Funktion überprüft, | ||
| + | |||
| + | Dabei wird wie folgt vorgegangen: | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * Solange '' | ||
| + | * Sei '' | ||
| + | * Für jeden Index '' | ||
| + | * Wenn '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | ==== placeNextWord(used, | ||
| + | Diese Funktion ermittelt die aktuelle Startposition für das nächste mögliche Wort und platziert alle möglichen Wörter und ruft sich dabei wieder auf. Als Resultat liefert die Funktion die Anzahl Lösungen (0,1 oder 2, mehr werden nicht gesucht). | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | Zuerst wird die Startzelle gesucht. Gibt es keine solche, ist das Puzzle voll und die Funktion gibt als Resultat 1 Lösung zurück. | ||
| + | |||
| + | Ab der Startzelle wird für alle möglichen Wörter gesucht und in '' | ||
| + | |||
| + | Ist '' | ||
| + | |||
| + | '' | ||
| + | |||
| + | Sonst wird für jedes '' | ||
| + | * Das Wort '' | ||
| + | * Es wird '' | ||
| + | * Ist '' | ||
| + | * Die dem '' | ||
| + | |||
| + | ==== solve() ==== | ||
| + | Die Funktion erstellt den Wortbaum '' | ||
| + | Das Puzzle hat einen eindeutige Lösung wenn 1 gemolden wird. (0 ist nicht möglich, weil das Puzzle ja mit einer Lösung generiert wurde). | ||
| + | |||
| + | |||
| + | ===== Weitere Betrachtungen ===== | ||
| + | Es gibt erstaunlich wenige Wörter, die jeweils überhaupt platziert werden können (durchschnittlich unter zwei, wenn man alle Fälle weglässt, wo kein Wort platziert werden kann). Der Algorithmus funktioniert auch noch einigermassen gut bei 4x so grossen Feldern (14x24) mit einer Wortliste von 23k Wörtern. | ||
| + | |||
| + | Darum funktioniert der hier vorgestellte Algorithmus auch. Es ist nicht klar, ob sich eine frühe Feststellung von nicht-zusammenhängenden Regionen überhaupt lohnen würde. | ||
| + | |||
| + | Wenn es mehrere Lösungen gibt, sind es fast immer Fälle der folgenden Art: | ||
| + | <code txt> | ||
| + | +---+---+ | ||
| + | | A B | | ||
| + | + | ||
| + | | E R | | ||
| + | +---+---+ | ||
| + | | R A | | ||
| + | + | ||
| + | | B E | | ||
| + | +---+---+ | ||
| + | |||
| + | oder | ||
| + | |||
| + | +---+---+ | ||
| + | | A B | | ||
| + | + +---+ | ||
| + | | E | R | | ||
| + | + | ||
| + | | R | A | | ||
| + | +---+ + | ||
| + | | B E | | ||
| + | +---+---+ | ||
| + | |||
| + | </ | ||
| + | |||
| + | Vor allem bei grösseren Felder würde es sich wohl lohnen, solche Fälle zum vornherein zu finden und neue Wörter zu wählen. | ||