Letzte Woche haben wir daran gearbeitet, die kürzeste 1-D-Zeichenfolge unter Verwendung der 10.000 häufigsten Wörter in englischer Sprache zu erstellen . Versuchen wir jetzt die gleiche Herausforderung in 2D!
Was Sie tun müssen, ist, alle obigen Wörter zu nehmen und sie in ein Rechteck so klein wie möglich zu setzen, um Überlappungen zuzulassen. Wenn Ihre Wörter zum Beispiel wären, wäre ["ape","pen","ab","be","pa"]
ein mögliches Rechteck:
.b..
apen
Das obige Rechteck würde eine Punktzahl von 5 ergeben.
Regeln:
- Das Überlappen mehrerer Buchstaben in einem Wort ist zulässig
- Wörter können in jede der 8 Richtungen gehen
- Wörter können nicht umbrochen werden
- Sie können ein beliebiges Zeichen für die leeren Stellen verwenden
Sie müssen eine Wortsuche erstellen, die diese 10.000 Wörter in Englisch enthält (laut Google). Ihre Punktzahl entspricht der Anzahl der Zeichen in Ihrer Wortsuche (ohne nicht verwendete Zeichen). Wenn es ein Unentschieden gibt oder sich eine Einsendung als optimal herausstellt, gewinnt die Einsendung, die zuerst veröffentlicht wird.
quelle
Antworten:
Rust,
3143030081 verwendeten ZeichenDies ist eine Art gieriger Algorithmus: Wir beginnen mit einem leeren Gitter und fügen wiederholt das Wort hinzu, das mit den wenigsten neuen Buchstaben hinzugefügt werden kann, wobei die Bindung unterbrochen wird, indem längere Wörter bevorzugt werden. Damit dies schnell ausgeführt werden kann, wird eine Prioritätswarteschlange mit Wortplatzierungskandidaten eingerichtet (implementiert als Vektor von Deques-Vektoren mit einem Vektor für jede Anzahl neuer Buchstaben, der ein Deque für jede Wortlänge enthält). Für jeden neu hinzugefügten Brief werden alle Kandidaten-Placements in die Warteschlange gestellt, die diesen Brief durchlaufen.
Kompilieren und ausführen mit
rustc -O wordsearch.rs; ./wordsearch < google-10000-english.txt
. Auf meinem Laptop dauert dies mit 531 MiB RAM 70 Sekunden.Die Ausgabe passt in ein Rechteck mit 248 Spalten und 253 Zeilen.
Code
quelle
C ++, 27243-Zeichenraster (248 x 219, 50,2% gefüllt)
(Dies als neue Antwort posten, da ich die 1D-Bindung beibehalten möchte, die ich ursprünglich als Referenz gepostet habe.)
Dieser
reißt eklatant offdurch ist stark inspiriert @ AndersKaseorg Antwort in seiner Hauptstruktur, hat aber ein paar Verbesserungen. Zuerst verwende ich mein ursprüngliches Programm, um Zeichenfolgen zusammenzuführen, bis die beste verfügbare Überlappung nur noch 3 Zeichen beträgt. Dann benutze ich die von AndersKaseorg beschriebene Methode, um ein 2D-Gitter mit diesen generierten Zeichenfolgen fortlaufend zu füllen. Die Einschränkungen sind auch ein wenig anders: Es wird immer noch versucht, jedes Mal die wenigsten Zeichen einzufügen, aber Bindungen werden unterbrochen, indem zuerst quadratische Gitter, dann kleine Gitter und schließlich das längste Wort hinzugefügt werden.Das Verhalten, das angezeigt wird, besteht darin, abwechselnd Leerstellen auszufüllen und das Raster schnell zu erweitern (leider waren kurz nach einer schnellen Ausbaustufe keine Worte mehr zu finden, sodass an den Rändern eine Menge Leerstellen vorhanden sind). Ich vermute, dass mit einigen Optimierungen der Kostenfunktion eine Raumausfüllung von mehr als 50% erzielt werden könnte.
Hier gibt es 2 ausführbare Dateien (um zu vermeiden, dass der gesamte Prozess erneut ausgeführt werden muss, wenn der Algorithmus iterativ verbessert wird). Der Ausgang von einem kann direkt in den anderen geleitet werden:
Und zum Schluss das Ergebnis:
Alternatives Ergebnis (nachdem einige Fehler im Programm behoben wurden, die bestimmte Richtungen beeinflussten und die Kostenfunktion optimierten, erhielt ich eine kompaktere, aber weniger optimale Lösung): 29275 Zeichen, 198x195 (75,8% gefüllt):
Ich habe wieder nicht viel getan, um diese Programme zu optimieren, also dauert es eine Weile. Aber Sie können zusehen, wie es das Gitter ausfüllt, was ziemlich hypnotisch ist.
quelle
C ++, 34191 Zeichen "Gitter" (mit minimalem menschlichem Eingriff können 6 oder 7 leicht gespeichert werden)
Dies sollte eher als Grenze für den 2D-Fall verstanden werden, da die Antwort immer noch eine 1D-Zeichenfolge ist. Es ist nur mein Code aus der vorherigen Herausforderung, aber mit der neuen Möglichkeit, beliebige Zeichenfolgen umzukehren. Dies gibt uns viel mehr Spielraum für das Kombinieren von Wörtern (insbesondere, weil es den schlimmsten Fall nicht überlappender Superstrings auf 26 begrenzt; einen für jeden Buchstaben des Alphabets).
Für eine leichte 2D-Darstellung werden Zeilenumbrüche in das Ergebnis eingefügt, wenn dies kostenlos möglich ist (dh zwischen Wörtern mit 0 Überlappungen).
Ziemlich langsam (immer noch kein Caching). Hier ist der Code:
Ergebnis: http://pastebin.com/UTe2WMcz (4081 Zeichen weniger als die vorherige Herausforderung)
Es ist ziemlich klar, dass einige geringfügige Einsparungen erzielt werden können, wenn die Linien
xd
undwv
vertikal angeordnet werden und die Monsterlinie schneiden. Dannhhidetautisbneudui
kann schneiden mit demd
undlxwwwowaxocnnaesdda
mitw
. Das spart 4 Zeichen.nbcllilhn
kann in eine vorhandenes
Überlappung eingesetzt werden (wenn eine vorhanden ist), um weitere 2 zu speichern (oder nur 1, wenn keine solche Überlappung vorhanden ist und diese stattdessen vertikal hinzugefügt werden muss). Zummjjrajaytq
Speichern kann der Wert schließlich irgendwo vertikal hinzugefügt werden 1. Dies bedeutet, dass mit minimalem menschlichem Eingriff 6 bis 7 Zeichen aus dem Ergebnis gespeichert werden können.Ich würde dies gerne mit der folgenden Methode in 2D umsetzen, aber ich habe Mühe, einen Weg zu finden, um es zu implementieren, ohne den Algorithmus O (n ^ 4) zu erstellen, der recht unpraktisch zu berechnen ist!
quelle
PHP
dieser macht den Job theroratisch; aber 10000 sind wahrscheinlich zu viele Wörter für eine Rekursion. Das Skript wird jetzt ausgeführt. (lief noch 24 Stunden später)
funktioniert gut auf kleinen Verzeichnissen, aber ich kann eine iterative Version nächste Woche machen.
$f=array("pen","op","po","ne","pro","aaa","abcd","dcba"); will output
abcdalthough this is not an optimal result (scoring was changed ... I´m working on a generator). One optimal result is this:
openEs ist auch nicht sehr schnell; Entfernt nur Teilzeichenfolgen und sortiert die Überreste nach Länge,
der Rest ist Brute Force: Versuchen Sie, die Wörter in ein Rechteck einzufügen, versuchen Sie es mit einem größeren Rechteck, wenn dies fehlschlägt.
Übrigens: Der Teil des Teilstrings benötigt auf meinem Computer 4,5 Minuten für das große Verzeichnis
und reduziert es auf 6.190 Wörter. Die Sortierung dauert 11 Sekunden.
quelle