Das Ziel dieser Herausforderung ist es, ein Programm zu schreiben, das in der Lage ist, ein Wort in möglichst wenigen Versuchen zu erraten. Es basiert auf dem Konzept der Lingo-TV-Show ( http://en.wikipedia.org/wiki/Lingo_(US_game_show) ).
Regeln
Bei einer Wortlänge, die als erstes Argument in der Befehlszeile übergeben wurde, stehen dem Player-Programm fünf Versuche zur Verfügung, das Wort zu erraten, indem auf die Standardausgabe eine Schätzung gefolgt von einem einzelnen \n
Zeichen geschrieben wird.
Nachdem eine Vermutung durchgeführt wurde, erhält das Programm eine Zeichenfolge in der Standardeingabe, gefolgt von einem einzelnen \n
Zeichen.
Die Zeichenfolge hat die gleiche Länge wie das zu erratende Wort und besteht aus einer Folge der folgenden Zeichen:
X
: was bedeutet, dass der angegebene Buchstabe nicht in dem zu erratenden Wort enthalten ist?
: was bedeutet, dass der angegebene Buchstabe im zu erratenden Wort vorhanden ist, aber an einer anderen StelleO
: was bedeutet, dass der Brief an dieser Stelle richtig erraten wurde
Wenn das Wort zu erraten , ist zum Beispiel dents
, und das Programm sendet das Wort dozes
, wird es erhalten , OXX?O
weil d
und s
richtig ist, e
ist fehl am Platz, und o
und z
ist nicht vorhanden.
Achten Sie darauf, dass ein Buchstabe, der mehr als das zu erratende Wort vorkommt, nicht mehr als ?
und O
mehr als die Anzahl der Vorkommen des Buchstabens im zu erratenden Wort markiert wird . Wenn das zu erratende Wort beispielsweise lautet cozies
und das Programm sendet tosses
, wird es empfangen, XOXXOO
da nur eines gefunden werden kann s
.
Wörter werden aus einer englischen Wortliste ausgewählt. Wenn das vom Programm gesendete Wort kein gültiges Wort der richtigen Länge ist, wird der Versuch als automatischer Fehler gewertet und es werden nur X
die zurückgegeben.
Das Player-Programm sollte davon ausgehen, dass eine Datei mit dem Namen wordlist.txt
und einem Wort pro Zeile im aktuellen Arbeitsverzeichnis vorhanden ist und bei Bedarf gelesen werden kann.
Vermutungen sollten nur aus alphabetischen Kleinbuchstaben bestehen ( [a-z]
).
Für das Programm sind keine anderen Netzwerk- oder Dateivorgänge zulässig.
Das Spiel endet, wenn eine Zeichenfolge, die nur aus O
besteht, zurückgegeben wird oder nachdem das Programm 5 Versuche unternommen hat und das Wort nicht erraten konnte.
Wertung
Die Punktzahl eines Spiels ergibt sich aus der angegebenen Formel:
score = 100 * (6 - number_of_attempts)
Wenn das Wort also beim ersten Versuch richtig geraten wurde, werden 500 Punkte vergeben. Der letzte Versuch ist 100 Punkte wert.
Wenn Sie das Wort nicht erraten, erhalten Sie null Punkte.
Die Grube
Spielerprogramme werden bewertet, indem versucht wird, 100 zufällige Wörter für jede Wortlänge zwischen einschließlich 4 und 13 Zeichen zu erraten .
Die zufällige Wortauswahl erfolgt im Voraus, sodass alle Einträge die gleichen Wörter erraten müssen.
Das Gewinnerprogramm und die akzeptierte Antwort sind diejenigen, die die höchste Punktzahl erzielen.
Programme werden in einer virtuellen Ubuntu-Maschine ausgeführt, wobei der Code unter https://github.com/noirotm/lingo verwendet wird . Implementierungen in einer beliebigen Sprache werden akzeptiert, sofern angemessene Anweisungen zum Kompilieren und / oder Ausführen bereitgestellt werden.
Ich stelle ein paar Testimplementierungen in Ruby im Git-Repository zur Verfügung. Lassen Sie sich gerne von ihnen inspirieren.
Diese Frage wird regelmäßig mit Ranglisten für veröffentlichte Antworten aktualisiert, damit Herausforderer ihre Einträge verbessern können.
Die offizielle Abschlussbewertung findet am 1. Juli statt .
Aktualisieren
Einträge können nun das Vorhandensein von wordlistN.txt
Dateien annehmen , um das Lesen der Wortliste für die aktuelle Wortlänge für N zwischen einschließlich 4 und 13 zu beschleunigen.
Beispielsweise gibt es eine wordlist4.txt
Datei, die alle vier Buchstabenwörter und wordlist10.txt
alle zehn Buchstabenwörter usw. enthält.
Ergebnisse der ersten Runde
Zum Datum des 01.07.2014 wurden drei Einsendungen mit folgenden Ergebnissen eingereicht:
4 5 6 7 8 9 10 11 12 13 Total
./chinese-perl-goth.pl 8100 12400 15700 19100 22100 25800 27900 30600 31300 33600 226600
java Lingo 10600 14600 19500 22200 25500 28100 29000 31600 32700 33500 247300
./edc65 10900 15800 22300 24300 27200 29600 31300 33900 33400 33900 262600
** Rankings **
1: ./edc65 (262600)
2: java Lingo (247300)
3: ./chinese-perl-goth.pl (226600)
Alle Einreichungen verliefen konsistent, mit einem klaren Sieger als C ++ - Einreichungen von @ edc65.
Alle Teilnehmer sind ziemlich genial. Ich konnte @ chinese-perl-goth noch nicht einmal schlagen.
Bei weiteren Einsendungen erfolgt eine erneute Bewertung. Aktuelle Einträge können auch verbessert werden, wenn Sie das Gefühl haben, es besser zu machen.
quelle
Antworten:
C ++ 267700 Punkte
Eine Portierung von einer alten MasterMind-Engine.
Unterschiede zu MasterMind:
Die Grundidee ist, das Wort zu wählen, das den Lösungsraum minimiert. Der Algorithmus ist für die erste Vermutung (ich meine "Tage") sehr langsam, aber die beste erste Vermutung hängt nur vom Wort len ab, so dass es in der Quelle fest codiert ist. Die anderen Vermutungen sind in Sekunden erledigt.
Der Code
(Kompilieren mit g ++ -O3)
Meine Punkte
Auswertung mit Jargon, 100 Runden:
Gesamt 265'100
Selbstbewertete Partituren
Hier sind meine Durchschnittspunkte für die gesamte Wortliste. Nicht vollständig zuverlässig, da sich einige Details des Algorithmus während der Tests geändert haben.
Nach diesen Zahlen sollte meine durchschnittliche Punktzahl in der Nähe von 257'800 liegen
PIT SCORE
Als letztes habe ich Ruby installiert, und jetzt habe ich eine "offizielle" Punktzahl:
quelle
Java, 249700 Punkte (schlägt in meinem Test Chinese Perl Goth)
Rangliste aktualisiert:
Hier ist die alte Rangliste mit
pit.rb
:Im Vergleich zu @chineseperlgoth verliere ich in kürzeren Worten (<6 Zeichen), gewinne aber in längeren Worten (> = 6 Zeichen).Die Idee ist ähnlich wie bei @chineseperlgoth. Meine Hauptidee ist nur, die Vermutung zu finden (kann jedes Wort der gleichen Länge sein, nicht unbedingt eine der verbleibenden Möglichkeiten), die die meisten Informationen für die nächste Vermutung liefert.
Derzeit spiele ich immer noch mit der Formel, aber für die obige Anzeigetafel wähle ich das Wort aus, das das Minimum ergibt für:Die neueste Version verwendet unterschiedliche Bewertungen, um die nächstbeste Schätzung zu finden, wodurch die Anzahl der "einzelnen Möglichkeiten" nach der aktuellen Schätzung maximiert wird. Dies geschieht, indem alle Wörter in der verkürzten Wortliste (um Zeit zu sparen) auf alle möglichen Kandidaten überprüft werden und ermittelt wird, welche Vermutung wahrscheinlicher ist, um eine "einzelne Möglichkeit" zu ergeben (dh nach dieser Vermutung wird es nur eine mögliche Antwort geben) nächste Vermutung.
Also zum Beispiel diesen Lauf:
Aus den ersten drei Vermutungen haben wir bereits irgendwo "* oo * s" mit einem "n" und wir müssen noch einen weiteren Buchstaben herausfinden. Das Schöne an diesem Algorithmus ist nun, dass er statt Wörter zu erraten, die dieser Form ähneln, das Wort errät, das überhaupt keine Beziehung zu früheren Vermutungen hat. Er versucht, mehr Buchstaben zu geben und hoffentlich den fehlenden Buchstaben zu enthüllen. In diesem Fall wird zufällig auch die Position für das fehlende "b" richtig ermittelt und mit der richtigen endgültigen Vermutung "boons" abgeschlossen.
Hier ist der Code:
quelle
Perl
Es gibt noch einiges an Verbesserungspotential, aber zumindest übertrifft es die enthaltenen Beispielspieler :)
Setzt Schreibzugriff auf das aktuelle Verzeichnis zum Zwischenspeichern von Wortlisten voraus (um die Ausführung zu beschleunigen); erstellt
wordlist.lenN.stor
Dateien mitStorable
. Wenn dies ein Problem ist, entfernen Sieread_cached_wordlist
den Code und ändern Sie ihn, um ihn nur zu verwendenread_wordlist
.Erläuterung
Zuerst erstelle ich ein Histogramm der Buchstabenhäufigkeiten in allen Wörtern der aktuellen Wortliste (
build_histogram
). Dann muss ich meine nächste Vermutung treffen - was gemacht wird vonfind_best_word
. Der Bewertungsalgorithmus addiert einfach die Histogrammwerte und überspringt die bereits gesehenen Buchstaben. Dies gibt mir ein Wort, das die häufigsten Buchstaben in der Wortliste enthält. Wenn es mehr als ein Wort mit einer bestimmten Punktzahl gibt, wähle ich eines nach dem Zufallsprinzip aus. Nachdem ich ein Wort gefunden habe, sende ich es an die Spiele-Engine, lese die Antwort und versuche, etwas Nützliches daraus zu machen :)Ich halte eine Reihe von Bedingungen aufrecht, dh Buchstaben, die an einer bestimmten Stelle in einem Wort vorkommen können. Beim Start ist dies nur einfach
(['a'..'z'] x $len)
, aber es wird basierend auf den in der Antwort gegebenen Hinweisen aktualisiert (sieheupdate_conds
). Ich baue dann einen regulären Ausdruck aus diesen Bedingungen und filtere die Wortliste durch.Bei Tests habe ich dann herausgefunden, dass die oben genannte Filterung nicht
?
allzu gut funktioniert , daher der zweite Filter (filter_wordlist_by_reply
). Dies nutzt die Tatsache aus, dass ein als?
in dem Wort markierter Buchstabe an einer anderen Position auftritt, und filtert die Wortliste entsprechend.Diese Schritte werden für jede Iteration der Hauptschleife wiederholt, es sei denn, die Lösung wurde gefunden (oder es ist nicht mehr möglich, von stdin zu lesen, was einen Fehler bedeutet).
Code
quelle