L'écriture d'un algorithme pour le scrabble
Je suis en train de travailler sur une grille de mots-croisés comme problème, mais je ne sais pas comment faire pour la conception de l'algorithme.
Par exemple:
- il y a des mots comme "voiture", "pomme" dans le dictionnaire.
- le mot "application" est donné au conseil d'administration.
- il y a des lettres comme 'l' 'e' 'c' 'r'....pour faire des mots.
Si l'algorithme a pour tâche de faire de bons mots qui sont stockés dans le dictionnaire.
app -> lapp -> leapp -> lecapp -> .... -> lappe -> eappc -> ... -> appl -> apple (réponse correcte)
Quelle est la meilleure solution pour cet algorithme?
Vous devez vous connecter pour publier un commentaire.
Vous pourriez être intéressé par Googler le document de recherche "Le plus Rapide du Monde de Scrabble Programme" par Appel et Jacobson (1988). Les algorithmes sont décrits dans le pseudo-code, donc ça prend un peu de travail à moule en forme utilisable et de la colle tous ensemble; toutefois, le programme, les auteurs contour fonctionne très bien.
Stocker votre dictionnaire comme un arbre, par exemple:
Grâce paxdiablo pour faire mon arbre plus lisible.
Cet arbre a les mots d'une, application, d'appel, de pomme, de demander, de perles, de haricot, de l'être et de l'abeille. Les nœuds marqués d'un astérisque indiquent "Si je devais arrêter là, ce serait un mot valide", comme le 'e' en dessous de 'b' pour 'être'.
Lorsque vous trouvez une lettre que vous ne connaissez pas, utilisez un caractère générique (c'est à dire, choisir tous les enfants et boucle vers le bas tous les chemins d'accès).
Vous dit des mots croisés, mais alors, vos "lettres...pour faire des mots" semble indiquer Scrabble. Ce serait le travail soit. Pas le plus rapide, mais beaucoup rapide.
Grâce Andreas pour nous rappeler que ce qui est appelé un trie.
Si vous voulais dire "la deuxième lettre est un P", vous devez démarrer à partir du nœud racine et profiter de chaque branche (ce qui serait chaque lettre de l'alphabet, en supposant que c'est un bon dictionnaire) et puis le "P" de la branche et ensuite aller à partir de là.
En fait, j'ai écrit un mots croisés programme avant (cryptique, mais la théorie qui sous-tend la construction est identique).
J'avais une base de données de mots et de leurs indices qui peuvent être triés par les temps utilisés (que je n'aurais pas tendance à obtenir un double des mots croisés sur les exécutions ultérieures).
La première chose que vous devez faire est de concevoir vos modèles (les noirs où vous ne pouvez pas mettre les lettres et les blancs, où vous pouvez). En essayant d'intégrer des mots dans une grille lors de la création du modèle à la volée est très chronophage et source d'erreurs. Si vous regardez la plupart des mots croisés, ils ont tendance à suivre certaines règles pour le rendre plus facile. Des choses comme étant symétrique autour de l'une des diagonales et interdisant d'un carré de quatre cases blanches (pour faciliter la tâche de la sélection des mots).
Une fois que vous avez le modèle, puis vous commencez à trouver des mots à la place. De cette façon, vous savez que "app" était le commencer de la parole et être en mesure de limiter vos recherches à ceux commençant par "application", et pas à chaque mot qui a "app" en elle. De même pour les mots où vous avez connu des lettres à toutes les positions. C'est beaucoup plus facile de localiser des mots avec des lettres à des positions connues que d'évaluer ces lettres à la position de départ à l'intérieur d'un mot.
Le mien a fini par être écrit en script shell (croyez-le ou pas) et en utilisant le dictionnaire qui venait de Linux en tant que mot de recherche. Si vous savez que vous avez un 5-lettre de mot commençant par "application", c'est assez facile à utiliser:
pour obtenir une liste de toutes les possibilités.
Et de, car chaque mot a été trouvé, il a été copié sur un clues.txt fichier qui contient à la fois la parole et de multiples indices possibles. Le format a utiliser {count, un mot, un indice}, où le même mot peut exister sur plusieurs lignes avec une autre idée - cela a permis à la tuyauterie de la
grep
parsort
de sorte que moins utilisé des mots/des indices flotté vers le haut (à chaque fois qu'un mot/indice a été utilisé, son compte a été incrémenté, ce qui rend moins susceptibles d'être utilisés la prochaine fois).Une fois que le fichier a une taille décente, le programme serait de l'utiliser d'abord localiser les mots, et si l'un n'était pas trouvé ne serait-il revenir au fichier de mots (sans indices) où une intervention manuelle serait nécessaire.
Il en fait a fini par être tout à fait bon à faire le travail. Il n'était absolument pas vite, mais je n'ai pas besoin de générer un toutes les trois secondes - c'était pour une communauté bulletin d'information envoyé une fois par semaine.
Maintenant que vous avez changé la question pour un Scrabble variante, qui est en réalité beaucoup plus difficile.
Vous avez besoin de prendre en compte les lettres que vous avez, les lettres sur le plateau et le fait qu'il y a beaucoup plus d'endroits que vous avez à évaluer. Ce qui fait une force brute méthode beaucoup plus difficile.
Ce que je voudrais faire comme un coupe initiale serait de sélectionner les possibilités (position de départ et la direction sur la carte) choisis de manière aléatoire, puis utiliser le même algorithme que pour les mots croisés de la variante ci-dessus pour rechercher tous les mots qui peuvent s'y insérer. Alors, si vous avez les lettres pour satisfaire la parole, de la stocker (avec son score) dans une liste.
Gardez à l'esprit que vous avez besoin pour regarder dehors pour interférer avec d'autres mots sur le conseil d'administration.
Je voudrais continuer à examiner les possibilités jusqu'à ce que l'un d':
Ce dernier est important - si vous jouez à un débutant, vous ne voulez pas de manière exhaustive examiner des millions de possibilités.
Ensuite, choisissez le meilleur coup de votre liste (ou peut-être pas le meilleur, si vous jouez au niveau débutant - tout dépend de la façon dont vous souhaitez que l'ordinateur soit).
Steven A. Gordon a écrit un document intéressant sur la façon de rechercher possible de Scrabble(tm, je suppose) se déplace (voir Gordon est en papier sur GADDAG). Bien qu'il existe un grand fossé entre la recherche de mouvements et gagner au Scrabble - que le document mentionne - ce n'est pas pertinente pour la question d'origine.
Dans le cas où vous trouver le plus utile juste pour aller directement à la lecture du code, il y a un bon open-source lecteur,
Quackle.
La plupart du Scrabble documents de parler de la recherche au conseil d'administration, pour le meilleur mot à jouer. Mais pour résoudre votre problème, comme l'a dit, il est assez simple de l'algorithme.
Tout d'abord, vous savez que le mot que vous voulez contient 'app', et vous savez que le plus grand mot que vous pouvez faire est de sept lettres (3 lettres déjà sur le conseil d'administration, et 4 dans votre barre des tâches). Ainsi, la recherche de votre base de données avec une instruction sql tels que:
Sélectionnez mot de dictionnaire où le mot LIKE '%app% " et len(mot) <= 7
Ensuite, mettre tous les sept lettres dans un tableau {l,e,c,r,a,p,p}
Lire chaque mot à partir de la base de données,un à la fois. Puis regarder chaque caractère du mot du dictionnaire et de voir s'il existe dans le tableau. Si la première lettre du mot du dictionnaire est trouvé dans le tableau, puis de les supprimer cet élément dans le tableau et de passer à côté du dictionnaire lettre.
Si aucun mot du dictionnaire de la lettre ne se trouve pas dans le tableau, alors le mot n'est pas admissible, donc, de passer à côté du mot.
Si vous avez regardé toutes les lettres dans le dictionnaire et tous ont été trouvés dans le tableau, alors le mot est admissible, et si vous écrivez à la liste.
Note, la raison que vous mettez vos tuiles dans un tableau est qu'une fois que vous correspondre à une lettre du mot dictionnaire une tuile de votre tableau, vous aurez besoin de retirer la lettre de la poursuite de l'examen, par la suppression de cet élément dans le tableau.
Ainsi, par exemple, le dictionnaire de la base de données renvoie le mot "appel". Les quatre premières lettres sont trouvés dans votre tableau, et ces éléments sont supprimés, laissant seulement {l,c,r} à gauche dans le tableau. Lorsque vous recherchez la cinquième lettre " a " vous ne trouvez pas, donc, le mot est disqualifié.
Le mot "pomme" est admissible, laissant {c,d} à gauche de votre tableau.
Il est assez facile de ce code dans n'importe quelle langue. Cependant, il n'est pas le moyen le plus rapide de le faire. Je suis à la recherche d'un moyen plus rapide de moi-même!
Si vous essayez de créer un index de mots de telle sorte que vous pourraient tenter de "résoudre" (ou créer) des mots croisés alors je crois que vous pourriez commencer avec un dictionnaire de mots indexés par la longueur. Ensuite, vous devez créer un autre dictionnaire des dictionnaires de dictionnaires... le premier indice est par le total de la longueur des mots, tandis que la seconde est en fonction de la longueur, puis par lettre de position, et enfin par une lettre (de six lettres des mots avec un deuxième lettre de "je" par exemple).
Après que vous avez construit cet index vous pouvez ensuite exprimer chaque étape en essayant de définir ou de résoudre un casse-tête en termes de l'ensemble des opérations effectuées sur ces. (Par exemple un 8 lettre mot commençant par "w" et se terminant par "k" serait l'intersection de tous les 8 lettre des mots commençant par "w" et tous ceux se terminant par un "k" --- qui a, sans surprise comprendrait des "devoirs"). Après avoir construit les données indexées structure que j'ai décrit, bien sûr, de permettre beaucoup plus efficace de recherche des correspondances possibles serait alors possible en effectuant des balayages linéaires seulement de la mondial de de la liste de mots ou même des balayages linéaires de la longueur des listes séparées).
Une fois que vous avez cette structure de base de données, puis le reste du programme, sans doute, être un arbre de la génération et de la traversée (avec le recul, bien sûr). Créer un programme qui génère chaque possibilité (à l'aide de la structure de données décrite) et a chaque fois qu'il se "bloque" faire revenir jusqu'à ce qu'il trouve de nouvelles possibilités.
Implicitement par paxdiablo, vous devrez inclure une grande piscine de "mots" pour le générateur pour avoir une chance raisonnable de la création d'une "solution". Toute personne qui a de l'expérience avec des mots croisés se rend compte qu'ils permettent le setter de prendre quelques libertés (tels que l'utilisation fréquente des points cardinaux, archaïque termes et poétique contrats) afin d'obtenir eux-mêmes o'er la bosse, comme elle l'avait fait.
Je n'ai pas personnellement écrit un générateur de mots croisés. J'ai écrit que le cryptogramme solveurs qui a utilisé un similaire, mais beaucoup plus simple indexation de la structure. (Pour trouver tous les mots qui zyzxw pourrait être dans un cryptogramme vous "résumé" de motif: abacd. Votre dictionnaire contient tous les mots indexés par son abstraction, et vous pouvez facilement trouver que "tous" les matchs "zyzxw"). Dans ce cas linéaire de la recherche par les listes démarré à chaque abstraction est assez rapide même lorsque vous êtes à la corrélation de découvrir que "uvz" avec "zyzxw" pourrait, en effet, être "la" ... par exemple). J'ai aussi écrit un simple "Jotto" jeu qui ne bénéficient pas de l'indexation à tous --- linéaire de la numérisation à travers les quelques milliers de 5 ou 6 lettres à chaque étape d'élimination utilisée pour prendre moins d'une seconde sur mon vieux de 6 Mhz XT dans la pré-histoire des PC modernes de l'informatique).
Look pour la thèse de Doctorat de papier appelé "Vers le Parfait Jeu de Scrabble" par Brian Sheppard (auteur de Maven). C'est instructif et très intéressant. Mais aussi très longtemps.
Si j'ai compris correctement à la question (vous commencez w indice de lettres, une sous-chaîne de la parole, et que vous essayez de réorganiser les lettres pour obtenir un bon mot) voici une autre solution:
Vous pouvez commencer par aller en arrière.
Vous avez déjà les mots dans le dictionnaire et de la nécessité de montrer la partie du mot (une sous-chaîne) et une liste de lettres à partir de la parole, les gens peuvent s'organiser entre eux. Compte tenu de tout cela, vous commencez avec le mot dans le dictionnaire, et de créer un graphe de mots de 1 modifier la distance.
Que vous enlevez la lettre, vous la placez dans une liste des indications.
Que le joueur utilise les lettres de la liste pour former le mot d'origine, vous n'acceptez que des entrées correctes qui sont des nœuds qui conduisent à un parent précédent. Vous venez de parcourir le graphe en arrière pour trouver le mot original.
Ce que vous cherchez, c'est la capacité de votre anagramme solveur pour trouver des "génériques" des lettres pour voir ce que plus de mots qu'il peut faire avec d'autres lettres. J'ai un anagramme solveur j'ai écrit ce qui n'cette chose exacte. Une chose importante que j'ai découvert pour faire cela, et aussi pour la rapidité de l'exécution du solveur est de définir combien de lettre et le score de chaque mot dans votre tableau de mots.
Par Exemple, le tableau doit être structurée comme suit
Comme vous pouvez le voir il y a une colonne séparée pour le mot, la lettre et la façon dont beaucoup de la lettre qu'ils contiennent et le score du mot. J'ai créé cette avance avec un script séparé que tout simplement manqué de chaque mot et rempli pour moi jusqu'à ce qu'il a fait.
Voici le script que j'ai écrit pour calculer le nombre de lettres ont été dans chaque mot, ainsi que la note et mis à jour chaque enregistrement. Vous devez commencer avec une table qui ne contient que les mots avant d'exécuter ce script. Une fois que vous l'exécutez, vous avez terminé et ne pas avoir à l'exécuter à nouveau, sauf si vous ajoutez de nouveaux mots.
Une fois que c'est fait, alors tout ce que vous avez à faire est de faire un script qui compte le nombre de lettres dans les colonnes et les compare avec les lettres que vous lui donnez. Vous allez avoir à faire exploser les lettres et savoir combien de chaque lettre que vous avez. Alors exécuter une instruction sql qui découvre les montants de la lettre ou moins.