2009-07-02 6 views
3

J'ai créé une anagramme créant une application, en créant un champ d'anagramme dans ma base de données, avec une chaîne de caractères alphabétiquement plus bas. Par exemple, l'aspiration devient cinostu, l'oreille devient aer et ainsi de suite.Comment créer des mots de sous-ensembles pour une application anagramme (php)?

Ce que je veux faire maintenant, c'est créer des sous-mots à partir de l'anagramme original recherché. Exemple: Comment procéder pour extraire les mots du sous-ensemble d'une recherche de 'arrêt', c'est-à-dire 'repos' et 'regarder'.

Répondre

0

Bonjour Bork. essayé d'adapter votre code en PHP, et j'ai ce qui suit:

$ LetterCount = tableau ("a" => 1, "b" => 1, "c" => 1, "d" => 1, "e" => 0, "f" => 1, "g" => 1, "h" => 1, "i" => 1, "j" => 1, "k" => 1 , "l" => 1, "m" => 1, "n" => 1, "o" => 1, "p" => 1, "q" => 1, "r" => 1, "s" => 1, "t" => 1, "u" => 1, "v" => 1, "w" => 1, "x" => 1, "y" => 1, " z "=> 1); Je ai codé en dur le bit de déclaration de tableau pour gagner du temps.

Quoi qu'il en soit, il n'a pas l'air de travailler et m'a donné cette erreur: Notice: Undefined offset: 1

Voici une capture d'écran des erreurs que je reçois, j'ai également ajouté echos pour chaque var ou tableau dans la boucle pour voir si vous pouvez comprendre ce qui se passe.

http://i42.tinypic.com/11ryz4g.png

Je pense qu'il isnt identifier la lettre aplhabet dans le tableau correctement, et est donc l'ajout de numéros mal à la fin du tableau. Laissez-moi savoir ce que vous pensez que je devrais faire.

1

Inclure un espace à la fin du mot d'origine. Chaque itération où l'espace se termine au milieu des lettres, vous obtiendrez deux mots. Ensuite, vous pouvez tester ces deux mots. Si l'espace est au début ou à la fin du motif d'itération, coupez-le et testez ce mot.

+0

Ce serait probablement, mais il semble un long chemin. Je ne peux penser à rien de mieux en ce moment, mais je * pense * qu'il y a un moyen plus facile ... en quelque sorte. Bonne idée. –

+0

J'essaie de comprendre exactement ce que vous voulez dire. Voulez-vous dire que l'arrestation reviendrait en tant que regard, oreille ou repos? Ou qu'un mot se combinerait avec un autre, égalant toujours le nombre de caractères dans l'anagramme original. –

+0

Alors "arrestation" devient "arrestation" avant de commencer. Notez le nouvel espace à la fin. Certaines itérations vont revenir "r staer". Aucun mot n'a de sens. L'itération suivante retournera "r regard". Aha! "regard"! Finalement, on retournera "ar rest". Un autre retournera "star re". Etc. –

0

Cette approche est légèrement différente de la vôtre, mais je crois qu'il sera facile à mettre en œuvre par programme. Je ne suis pas sûr que c'est la performance optimale sage, mais je vais vous laisser :-)

D'abord vous avez besoin d'un dictionnaire de tous les mots juridiques que vous voulez être en mesure de faire correspondre. Créez une table "Dictionary" ou "Words" dans votre base de données, avec la première colonne stockant le mot actuel, la deuxième colonne stockant le mot converti en majuscules ou minuscules pour faciliter la comparaison, puis une colonne entière pour chaque lettre dans l'alphabet AZ.

Importez votre fichier de dictionnaire dans cette table, et comptez par programme le nombre de fois que chaque lettre de l'alphabet apparaît dans ce mot, et stockez ce nombre dans la colonne pour cette lettre.

Exemple Parole: aide-comptable

Mémorisez le mot "comptable" dans la colonne de texte, 1 dans votre "b", "p" et "r" colonnes, 2 dans votre "o" et " k "colonnes, et 3 dans votre colonne" e ".

Une fois que vous avez votre dictionnaire entier importé avec nombre de lettres, vous pouvez déterminer assez facilement tous les sous-mots possibles en un mot donné en utilisant la méthode suivante:

  • Compter les lettres dans votre chaîne.
  • Composer une requête SQL qui renvoie tous les mots de votre table de dictionnaire qui n'utilisent pas les lettres non trouvées dans votre mot donné, ou qui ont plus d'une lettre particulière qu'existe dans votre mot.

Vous pouvez y parvenir en faisant une en mémoire tableau avec 26 positions représentant l'alphabet

Exemple mot: véhicule

SELECT Word FROM Dictionary WHERE NOT (
    (a >= 1) OR (b >= 1) OR (c >= 2) ... OR (z >= 1) 
) 

Ainsi un mot dans votre dictionnaire qui a un ' a 'ou' z 'sont exclus, car la requête filtrera tous les mots dont le compte' a 'ou' z 'est au moins un, et tout mot qui utilise plus d'un' c 'est filtré .

Vous pouvez facilement générer toutes les conditions "OR" par programmation en utilisant un tableau de 26 entiers, tous commençant à 1, puis parcourir votre mot, en ajoutant 1 à la valeur tableau appropriée de chaque lettre que vous trouvez.

MISE À JOUR - décompte final exemple de code

Pardonnez mon exemple de code ci-dessous - il va être en ASP (VBScript) - mais vous devriez être en mesure de saisir et de traduire en PHP, ou une personne aimable le faire pour toi sinon.

Const AsciiCodeLowerCaseA = 97 
InputWord = "Carrots" 
LowerCaseInputWord = LCase(InputWord) 

Dim LetterCount(26) 

for i = 1 to 26 
    LetterCount(i) = 1 
next 

for j = 1 to Len(InputWord) 
    CurrentLetter = Mid(InputWord, j, 1) 
    AsciiCode = Chr(CurrentLetter) 
    AlphabetPos = AsciiCode - AsciiCodeLowerCaseA + 1 
    LetterCount(AlphabetPos) = LetterCount(AlphabetPos) + 1 
next 

En convertissant chaque lettre du mot à sa valeur ASCII, puis en soustrayant le code ascii pour en minuscules « a » et en ajoutant 1, vous obtenez la position de cette lettre dans l'alphabet de 1 à 26. Vous Maintenant, ajoutez 1 à cette position dans le tableau.

Il semble contre-intuitif, mais initialise toutes les lettres à 1 dans votre tableau. Lorsque vous générez l'instruction SQL, vous éliminez tous les mots dont le nombre de lettres est supérieur à votre mot d'entrée. Ainsi, si une lettre n'apparaît pas dans le mot d'origine, vous filtrez les mots contenant une ou plusieurs lettres. Si la lettre apparaît une fois, vous filtrez les mots qui ont deux lettres ou plus, et ainsi de suite.

+0

Je me suis vraiment levé pour avoir tous les a-z dans ma base de données. Je travaillais dans ce sens. C'était juste la question sur laquelle je me débattais. C'est peut-être la réponse que je cherchais. Je vais essayer et vous faire savoir comment je m'entends. Merci Bork. –

+0

J'ai donc créé un tableau de 26 touches: $ alpha_array = array ("a" => 0, "b" => 0, "c" => 0) et ainsi de suite. Ce que je veux faire est de parcourir ma chaîne d'entrée explosée ... celle que l'utilisateur entre, et si un char existe, je veux éditer le $ alpha_array et en ajouter un au tableau dans cette instance. Ensuite, je peux construire une instruction SQL après cela. Des idées? –

+0

Je vais modifier ma réponse pour essayer de l'expliquer. –

1

Je n'ai pas encore pensé à cela de manière significative, désolé (travail à faire!), Mais peu importe comment vous générez les mots, n'oubliez pas que cela mettra en cache comme un motherlover, alors n'allez pas générer ces à la volée chaque fois que quelqu'un cherche.

CS.

2

Voici une approche que j'ai utilisée auparavant qui utilise votre liste de mots classés par ordre alphabétique.

1) Prenez votre mot cible (arrêt) et triez-le (aerrst). 2) Puis, à partir du mot trié, générer de nouvelles chaînes où chaque lettre est incluse ou exclue. Pour un mot de N lettres cela donne 2 ** N chaînes possibles. (Je ne connais pas PHP mais je peux vous donner un pseudo-code ou par exemple Python si vous le souhaitez.Pour votre mot cible, nous avons: a, e, r, r, s, t, st, rs, rt, rst, rr, rs, rt , es, et, est, ers, ert, erst, err, ers, ert, erst, erreurs, errt, errst, ae, ar, ar, comme, à, ast, ars, art, arst, arr, ars, art , arst, arrs, arrt, arrst, aer, aer, aes, aet, aest, aers, aert, aerst, aerr, aers, aert, aerst, aerrs, aerrt, aerrst

3) Ensuite, vérifiez ces chaînes contre votre liste triée. Ceux qui apparaissent dans votre liste triée correspondent aux mots de sous-ensembles que vous voulez.

par exemple aerrst correspond à anagrammes plein (arrêt, plus rare, raster, ...)
par exemple aerst seront dans votre liste triée (regard, larmes, ...)
par exemple RCV ne sera pas dans votre trié liste

0

Andy,

Je pense que vous avez besoin de convertir le code ASCII de nouveau dans un caractère - vous indexez le tableau avec des lettres, mais vous accédez avec des valeurs ASCII.

Voici votre code, légèrement modifié:

$ LetterCount = array ("a" => 1, "b" => 1, "c" => 1, "d" => 1, « e "=> 0," f "=> 1," g "=> 1," h "=> 1," i "=> 1," j "=> 1," k "=> 1," l " => 1, "m" => 1, "n" => 1, "o" => 1, "p" => 1, "q" => 1, "r" => 1, "s" = > 1, "t" => 1, "u" => 1, "v" => 1, "w" => 1, "x" => 1, "y" => 1, "z" => 1);

$AsciiCodeLowerCaseA = 97; 

for ($j = **0**; $j < strlen($string); $j++) { 
    $CurrentLetter = $string[$j]; 
    $AsciiCode = ord($CurrentLetter); 
    $AlphabetPos = **chr($AsciiCode - $AsciiCodeLowerCaseA + 1);** 
    $LetterCount[$AlphabetPos] = $LetterCount[$AlphabetPos] + 1; 
} 

Aussi je viens de remarquer que vous êtes l'indexation des caractères de la chaîne de 1, mais les tableaux sont zéro idexed.

Je pense que cela pourrait être beaucoup plus simple aussi bien (à moins que je me manque quelque chose)

for($j = 0; $j < strlen($string); $j++) { 
$LetterCount[$string[$j]]++; 
} 
+0

Merci Rob. Son fonctionnement maintenant ... Prend 20 secondes pour exécuter la page indépendamment de la longueur du nombre de lettres que la requête est. La vitesse acceptable, cherchera à l'améliorer maintenant. Merci encore à tous! –

+0

Jusqu'à 1 sec maintenant :) Trié. –

Questions connexes