$maxi=8;
$qry = "SELECT DISTINCT mot FROM dico WHERE length(mot)<$maxi and length(mot)>=$mini order by length(mot) ";
$requete = mysql_query($qry) or die('Erreur MySQL :
' . mysql_error());
$nb_resultats = mysql_num_rows($requete);
Mots trouvés, Nombre de lettre, Points, ';
while($data = mysql_fetch_array($requete))
{
$taille = strlen($data['mot']);//Détermination de la longeur du mot
if($taille == 7)//Pour les mots de 7 lettres par tirage affiche scrabble
{
$scrabble=' scrabble ';
}
elseif($taille ! =7)
{
$scrabble=$taille; //affiche la taille
}
for($i=0;$i<$taille;$i++)
{
$dico[$i] = substr($data['mot'],$i,1);//Création de l'array du mot du dico
}
$nbjuste = 0;
for($j=0;$j<7;$j++)
{
for($h=0;$h<$taille;$h++)//Pour chaque lettre de chaque mot puis on compare a l'array envoyé en POST
{
if($lettre[$j] == $dico[$h])
{
$dico[$h] = \"0\";
$nbjuste = $nbjuste + 1;
$h = $taille + 1;
}
}
$mot= $data['mot'];
$chaine = strtoupper(\"$mot\");
if ($nbjuste==$taille)
{
echo '----
' . $chaine.', '.$scrabble.' , , ';//On crée une ligne de tableau par mot trouvé...
}
}
}
?>
</td></tr></table>
</html>
benlaminefradj
Messages postés1Date d'inscriptionvendredi 4 mai 2007StatutMembreDernière intervention18 novembre 2007 18 nov. 2007 à 22:16
mot de passe pour le fichier Mysql
opossum_farceur
Messages postés147Date d'inscriptionlundi 16 août 2004StatutMembreDernière intervention14 novembre 2009 14 nov. 2007 à 22:12
Pour améliorer le rendement, il faudrait peut-être commencer par supprimer les doublons de la table; en entrant les lettres du mot "memoire", on obtient 3 fois "meme", 2 fois "memoire", 3 fois "mer", etc...
Ensuite, puisque seuls les mots comportants 7 caractères au plus sont intéressants, pourquoi ne pas les sélectionner directement dans ta requête :
SELECT * FROM `dico` WHERE length(mot)<8
Cas extrême, si ta table ne sert que pour cette requête, tu peux même envisager la suppression de tous les mots de longeur supérieure à 7 caractères.
cs_spoonisback
Messages postés72Date d'inscriptionvendredi 14 mai 2004StatutMembreDernière intervention 5 février 2010 13 nov. 2007 à 13:18
Salut
Merci de tous ces commentaires.
Pour pouvoir completer un mot tel que entendu, il faudrai entrer tous les mots présents sur le plateau de jeux...ca risque d'etre assez bazard à la fin tout ça, ou alors il faut faire tout le jeux en php, avec le plateau, les lettres les cases triple..Etc...
Vu le newbie que je suis je pense que d'ici 15 ou 20 ans j'y serai arrivé ;-)
En fais j'ai fais ce code pour ma copine qui me saoule quand elle joue genre 'tu voit pas un mot avec ca !?' donc le but premier est en fait de 'tricher' au scrabble, mais si on devai faire un jeux complet en php, il ne faudrait surtout pas reprendre mon code, mais comme je l'ai dis ce n'était pas mon attention non plus !!
Merci encore de vos commentaire (PS: en tant que Newbie, l'utilisation des classes est encore floue pour moi !!)
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 12 nov. 2007 à 23:55
Plusieurs choses quant à ce que tu dis...
Effectivement, le fait que ton algo ne trouve pas tous les mots peut être vu comme une limitation. J'ai bien dit, PEUT, parce que c'est proche de ce que fait l'humain : rares sont les personnes capables de trouver TOUS les mots possibles avec un tirage en moins de XX secondes. Cependant, ce n'est peut-être pas ce qu'on attend d'un logiciel.
Tu dis qu'il ne trouvera pas malus à mettre sur le u de entendu. Certes. Mais était-ce bien là le but de cette source ? Si j'ai bien compris ce que j'ai vu, elle sert surtout à dire quels sont les mots possibles avec un tirage. Après, ce serait à l'humain de voir lesquels peuvent être placés, combien de points chacun rapporte, comment gêner l'adversaire en prenant le mot compte triple avant lui, etc.
Pour la construction de malentendu à partir de entendu, je ferais pas comme ça... Partant de ce mot, je cherche ceux qui existent qui le contiennent. Je vérifie pour chaque mot quelles sont les lettres nécessaires et une simple regex me dit si je les ai ou pas. Je ne comprends pas ton histoire d'alternance gauche/droite... C'est pas de la politique au moins ?
malalam
Messages postés10839Date d'inscriptionlundi 24 février 2003StatutMembreDernière intervention 2 mars 201025 12 nov. 2007 à 23:44
Tout dépend du but : non ce n'est pas -facilement- applicable dans ce cas-là. cet algo ne trouve pas tous les mots, clairement. Mais il en trouvera beaucoup, et au fil de l'avancement du jeu, il en trouvera de plus en plus (parce que plus on avance dans le jeu, plus il est difficile de placer un mot ne commençant ni ne terminant par une lettre déjà placée sur le plateau de jeu).
Enfin, ce cas là est tendancieux en fait lol...
si j'ai "entendu" et que je veux faire "malentendues", il le trouvera sans doute si on fait du backward.
Ce qu'il ne trouvera sans doute pas c'est à partir de "entendu", placer "malus" sur le "u".
Mais encore une fois, tout dépend de comment on le gère. On peut partir à gauche ou à droite...ou les deux (en fait il faut faire les deux, il faut faire du backward). Ca n'a pas vraiment d'importance.
Il est facile dans le 1er cas, de partie de "entendu" et d'arriver à "malentendues" : je vérifie à gauche mon chemin : lentendu, j'ai le "l". Je continue "alentendu", j'ai le a. je continue...malentendu, j'ai le m. Je vérifie si le chemin peut continuer : à gauche, non. A droite ; j'ai le e..j'ai le s. Evidemment, on fera sans doute les deux (gauche - droite) alternativement...c'est à tester.
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 12 nov. 2007 à 23:27
Au scrabble, on peut aussi rajouter des lettres avant et après. Autour donc. Parfois, on connait les lettres du milieu.
ENTENDU => MALENTENDUES
Donc l'idée de l'arbre, ouais, mais c'est applicable dans ce cas là ?
Perso, c'est pas que le jeu de scrabble m'intéresse à développer en PHP, mais je trouve que la problématique est fichtrement intéressante.
malalam
Messages postés10839Date d'inscriptionlundi 24 février 2003StatutMembreDernière intervention 2 mars 201025 12 nov. 2007 à 23:18
Hello,
je m'incruste :-)
Moi je pense qu'en l'état, avec une simple liste de mots, on ne peut pas s'en sortir facilement et surtout rapidement.
L'idée de Neige sur les anagrammes est une bonne idée.
Mais il y a mieux je pense. Il faut représenter le dico sous forme d'arbre.
Par exemple : talus et tasse commence par la même syllable (ta, pour ceux qui n'auraient pas suivi ;-)).
On aurait donc un chemin t -> a -> l...
ou t -> a -> s...
Difficile de représenter un arbre ici hein...mais bon, la racine est la même pour les deux mots, et leur chemin se sépare vers d'autres feuilles à partir de la 3ème lettre.
salut et talus ne sont du coup plus du tout sur le même chemin.
Par contre, cela permet d'une part d'économiser beaucoup de place, et d'autre part cela accélère les traitements ! il suffit de commencer par chercher les débuts possible pour chaque lettre, puis d'avancer et d'abandonner (ou d'afficher si on a un mot complet) en fonction des lettres suivantes.
Je pense que c'est rapide, en tous cas dans un langage applicatif...
Par contre cela impose de se passer de base de données (je me vois mal représenter un arbre avec une bdd relationnelle).
C'est un algorithme connu, écrit il y a fort longtemps...et si c'était efficace il y a fort longtemps, il y a des chances pour que ça le soit toujours ;-) Il me semble d'ailleurs que c'était pour le scrabble!
audayls
Messages postés373Date d'inscriptionsamedi 9 juillet 2005StatutMembreDernière intervention11 août 2008 12 nov. 2007 à 22:27
Je vais essayer de mon côté et je te tiens au courant ;-)
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 12 nov. 2007 à 21:57
Bon en fait, MATCH(...) AGAINST(...) n'est à utiliser qu'avec des mots à chercher dans des phrases, des textes entiers...
En plus, il faut que le moteur soit MyISAM, la recherche FULL-TEXT ne fonctionne pas avec une table InnoDB...
Moi, je cale...
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 12 nov. 2007 à 21:43
Cette regexp sort tous les enregistrements... Puisqu'ils correspondent tous... Si aucune lettre demandée n'est présente, ils sont quand même retournés...
Vais faire quelques tests avec AGAINST, histoire de voir...
audayls
Messages postés373Date d'inscriptionsamedi 9 juillet 2005StatutMembreDernière intervention11 août 2008 12 nov. 2007 à 20:53
Hum pas mal l'idée de l'anagramme ^^ Mais je ne sais pas si la recherche MySQL en texte intégral sera interessante puisqu'elle effectue une double recherche...
A la rigueur on peut utiliser les anagramme avec une recherche de type REGEXP du genre "a{0,1}d{0,1}e{0,2}i{0,1}r{0,1}v{0,1}" cela permettra de récupérer uniquement les mots ayant tes lettres en bonne quantité.
Enfin faudrais bencher pour savoir si c'est AGAINST ou REGEXP qui remporte le concours parce que j'en ai aucune idée XD
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 12 nov. 2007 à 14:11
"Par contre je ne comprends pas ton exemple avec la fréquence d'apparition de lettre... Comment peut-on faire celà ?"
Ben justement, je cherche aussi...
On pourrait faire une regexp avec toutes les possibilitées permutations sans répétition des lettres (ça fait 7! , soit 5040). Je pense pas que ce soit pertinent...
Peut-être que la base de données telle qu'elle est conçue ne permet pas d'optimiser à mort le traitement.
Je suis en train de penser que si les mots étaient stockées sous forme d'anagrammes, les lettres de ces anagrammes étant par ordre croissant, ça pourrait peut-être faciliter les choses. Il faudrait alors deux tables, une pour les anagrammes, une pour les mots (à un même anagramme peut correspondre plusieurs mots)
Ainsi le mot bonjour serait associé à l'anagramme bjnoour
salut et talus => alstu
A partir de là, la fonction native de recherche de MySQL en texte intégral (AGAINST) pourrait permettre de faire de bonnes choses (mais j'ai pas trop creusé, donc je me gourre peut-être complètement)
http://dev.mysql.com/doc/refman/5.0/fr/fulltext-search.html http://dev.mysql.com/doc/refman/5.0/fr/fulltext-query-expansion.html
audayls
Messages postés373Date d'inscriptionsamedi 9 juillet 2005StatutMembreDernière intervention11 août 2008 12 nov. 2007 à 11:51
Aque Salut Neigedhiver =)
"Ouhaaaaaaaa alors elle peut vraiment servir à quelque chose !?" J'arriverai bien à lui trouver une utilité à ta classe parce que perso je la trouve chouette XD
Sinon je suis assez content car le code que j'ai envoyé par MP contient pas mal de tes recommandations =P
J'effectue une recherche dans la base de donnée en enlevant toutes les lettres qui ne sont pas parmis les 7 lettres (grâce à un REGEXP), puis je trie les résultats en vérifiant si on a assez de lettres pour former le mot.
Bon je n'ai pas utiliser FilteredIterator (puisque ce code n'est pas une classe) mais c'est vrai que celà aurait été plus pratique =P
Par contre je ne comprends pas ton exemple avec la fréquence d'apparition de lettre... Comment peut-on faire celà ?
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 12 nov. 2007 à 05:31
@spoonisback :
"Audalys, je suis d'accord pour faire une requete qui contient au moins une des lettres mais, je ne vois pas quelle requete faire..."
Quelque chose qui ressemble à ça ?
// $lettres est un tableau des lettres du tirage du genre $lettres = array('a', 'e', 'n', 'b', 'o', 'j', 'n');
$motif = '(' . implode('|', $lettres) . ')';
$sql = sprintf('SELECT mot FROM dico WHERE mot REGEXP \'(%s)\' GROUP BY mot', $liste_lettres);
On peut faire une requête qui sort les mots qui ont deux lettres du tirage :
$motif = str_repeat('('.implode('|', $lettres).')', 2);
$sql = sprintf('SELECT mot FROM dico WHERE mot REGEXP \'%s\' GROUP BY mot', $liste_lettres);
Avec autant de lettres qu'on veut, même. Le seul problème, c'est que la requête ne tient pas compte d'une utilisation précédente d'une lettre.
Ainsi, si le tirage contient un seul E, la requête s'en cogne et sort tous les mots qui contiennent un E, ou deux, ou trois...
En répétant le motif de recherche 3 fois avec les lettres données en exemple, j'obtiens 4308 résultats sur la table que tu fournis, contre plus de 42000 s'il n'est recherché qu'une seule fois.
Par contre, le temps de traitement...
Après, pour épurer ça, un FilteredIterator ça devrait faciliter le travail. Mais en terme de performances... Ca devrait déjà être mieux que ton script d'origine ;)
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 12 nov. 2007 à 05:16
Salut,
audayls : "Ensuite pour analyser les mots en selectionner ceux qui peuvent fonctionner, tu peux fortement simplifier ton code en utilisant la class "STRING ITERATOR" récemment postée."
=> Ouhaaaaaaaa alors elle peut vraiment servir à quelque chose !?
audayls : "Au lieu de selectionner tous les mots il faudrait uniquement selectionner les mots contenant au moins une des 7 lettres."
=> Pour ça, il pourrait être pertinent de trier les lettres du tirage par ordre croissant de fréquence dans le vocabulaire français. Puisqu'il y a peu de mots avec Z, mais beaucoup plus avec E, si on trouve un Z, on limite au maximum les résultats, et ainsi de suite.
Teclis01 : "
foreach($_POST as $sNameInputLettre=>$sLettre{
$sQuery.=" mot=%'$lettre%' and";
}
"
=> J'aime pas trop. Je préfère utiliser implode(), c'est plus propre, et certainement plus rapide puisque c'est une fonction C.
Ca donnerait :
$sQuery = implode(' AND ', $_POST);
1 seule ligne au lieu d'une boucle... Je crois que y'a pas photo.
Mais je crois effectivement qu'une requête avec des AND n'est pas judicieuse.
Et avec une regexp dans la requête SQL, on devrait pouvoir faire des choses intéressantes...
audayls
Messages postés373Date d'inscriptionsamedi 9 juillet 2005StatutMembreDernière intervention11 août 2008 11 nov. 2007 à 23:16
"Merci encore de ne pas m'avoir flagellé !!!" Bah pourquoi tant de haine ? XD
Regarde dans tes MP c'est noël avant l'heure =P
cs_spoonisback
Messages postés72Date d'inscriptionvendredi 14 mai 2004StatutMembreDernière intervention 5 février 2010 11 nov. 2007 à 19:09
Salut
Heu...débutant je suis...bon c'est pas que je suis contre vos idées, mais y'a des trucs que je pige pas en fait..!
En fait Teclis01, je n'ai pas trouver d'autre moyen que l'imbriquage de boucle pour chercher tous les mots : 7 et inférieurs à 7 lettres. POur la suite de ton code...j'ai rein compris...désolé...je vois que tu a fabriquer un autre type de query, c'est à partir du 'foreach' que je pige pas..;
Audalys, je suis d'accord pour faire une requete qui contient au moins une des lettres mais, je ne vois pas quelle requete faire...
Merci encore de ne pas m'avoir flagellé !!!
audayls
Messages postés373Date d'inscriptionsamedi 9 juillet 2005StatutMembreDernière intervention11 août 2008 11 nov. 2007 à 18:45
Salut,
Je ne pense pas que ta méthode soit bonne Teclis01. Il se peut que tes 7 lettres ne puissent pas faire un mot de 7 lettres.
Ce qu'il faudrait faire, je pense vu la taille de la table, c'est deja d'améliorer la requête MySQL. Au lieu de selectionner tous les mots il faudrait uniquement selectionner les mots contenant au moins une des 7 lettres.
Ensuite pour analyser les mots en selectionner ceux qui peuvent fonctionner, tu peux fortement simplifier ton code en utilisant la class "STRING ITERATOR" récemment postée.
Pour finir tu pourrais classer les mots possible en les classant selon les points qu'ils rapportent.
Teclis01
Messages postés1423Date d'inscriptionmardi 14 décembre 2004StatutMembreDernière intervention29 décembre 20124 11 nov. 2007 à 18:26
hum
if($data['long'] <= 7)//Pour les mots <= à 7 (7 lettres par tirage au Scrabble)
$taille = $data['long'];
tant qu'a faire hein ;)
Mon dieu ce que c'est lourd... huhu j'aime les boucles mais il y a des limites ^^
Heureusement que tu as pas 27 boucles imbriquées sinon tu n'aurais plus de lettres pour tes compteurs de boucle :p
Non franchement je vais pas être chiant sur le typage mais au moins des variables explicites ...ça mange pas de pain
Ensuite je me demande si il n'y a pas plus simple ... du genre...
$iLettres=count($_POST);
$sQuery='select mot from dico where';
foreach($_POST as $sNameInputLettre=>$sLettre{
$sQuery.=" mot=%'$lettre%' and";
}
substr($sQuery,0,strlen($sQuery)-3)); //on vire le dernier and
mysql_query($sQuery);
(je peux me tromper puisque c'est une idée a vif)
24 janv. 2010 à 07:53
Qui a une solution pour supprimer les doublons dans les résultats et en compter le nombre. Merci par avance.
Cordialement à tous les phpistes.
CODE index.html ça peut intéresser quelqu'un !
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns= "http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>SCRABBLE</title>
<STYLE>
.over{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FFFF00}
.down{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FF0000}
.out{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input.btn{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input{text-align:center;font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input.nx{text-align:center;font-size:14;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FFFFFF}
textarea{text-align:left;font-size:12;font-weight:demi-bold;font-family:Verdana;color:#F0F0F0;background:#000000}
HR {color:#FFFF00}
</STYLE>
</head>
<center>
<form action="scrabble.php" method="get">
<fieldset>
<legend>TIRAGE</legend>
<label> Entrez vos 7 lettres : </label>
Tirage minimum <select name="mini">
<option value='2'>2 lettres</option>
<option value='3'>3 lettres</option>
<option value='4'>4 lettres</option>
<option value='5'>5 lettres</option>
<option value='6'>6 lettres</option>
<option value='7'>Scrabble</option>
</select>
</fieldset>
</form>
</html>
CODE scrabble.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>SCRABBLE</title>
<style>
a:link {color: #FFEFB5; text-decoration: none}
a:visited {color: #000000; text-decoration: none}
a:hover {color: #ffffff; text-decoration: none}
</style>
<script type="text/javascript">
/*
SCRIPT DE L'EDITEUR JAVASCRIPT
http://www.editeurjavascript.com
*/
go_visibility = new Array;
function goblink()
{
if(document.getElementById && document.all)
{
blink_tab = document.getElementsByTagName('blink');
for(a=0;a
<STYLE>
.over{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FFFF00}
.down{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FF0000}
.out{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input.btn{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input{text-align:center;font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input.nx{text-align:center;font-size:14;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FFFFFF}
textarea{text-align:left;font-size:12;font-weight:demi-bold;font-family:Verdana;color:#F0F0F0;background:#000000}
HR {color:#FFFF00}
</STYLE>
</head>
<center>
<center>
<?php
include('conf/mysql.php');//Inclusion du script de connexion
$lettre[0] = $_GET['lettre1'];
$lettre[1] = $_GET['lettre2'];
$lettre[2] = $_GET['lettre3'];
$lettre[3] = $_GET['lettre4'];
$lettre[4] = $_GET['lettre5'];
$lettre[5] = $_GET['lettre6'];
$lettre[6] = $_GET['lettre7'];
$mini = $_GET['mini'];
?>
<?php
$maxi=8;
$qry = "SELECT DISTINCT mot FROM dico WHERE length(mot)<$maxi and length(mot)>=$mini order by length(mot) ";
$requete = mysql_query($qry) or die('Erreur MySQL :
' . mysql_error());
$nb_resultats = mysql_num_rows($requete);
$lettre1= $lettre[0];
$chaine1 = strtoupper("$lettre1");
$lettre2= $lettre[1];
$chaine2 = strtoupper("$lettre2");
$lettre3= $lettre[2];
$chaine3 = strtoupper("$lettre3");
$lettre4= $lettre[3];
$chaine4 = strtoupper("$lettre4");
$lettre5= $lettre[4];
$chaine5 = strtoupper("$lettre5");
$lettre6= $lettre[5];
$chaine6 = strtoupper("$lettre6");
$lettre7= $lettre[6];
$chaine7 = strtoupper("$lettre7");
echo'Recherche parmis '.$nb_resultats.' mots
avec les lettres
<table align="middle" valign="middle" border="0" cellspacing="0" cellpadding="0">----, <center>'.$chaine1.' </td>
<center>'.$chaine2.',
<center>'.$chaine3.',
<center>'.$chaine4.',
<center>'.$chaine5.',
<center>'.$chaine6.',
<center>'.$chaine7.'
| [javascript:history.go(-1) Retour] |';
echo'
Mots trouvés, Nombre de lettre, Points, ';
while($data = mysql_fetch_array($requete))
{
$taille = strlen($data['mot']);//Détermination de la longeur du mot
if($taille == 7)//Pour les mots de 7 lettres par tirage affiche scrabble
{
$scrabble=' scrabble ';
}
elseif($taille ! =7)
{
$scrabble=$taille; //affiche la taille
}
for($i=0;$i<$taille;$i++)
{
$dico[$i] = substr($data['mot'],$i,1);//Création de l'array du mot du dico
}
$nbjuste = 0;
for($j=0;$j<7;$j++)
{
for($h=0;$h<$taille;$h++)//Pour chaque lettre de chaque mot puis on compare a l'array envoyé en POST
{
if($lettre[$j] == $dico[$h])
{
$dico[$h] = \"0\";
$nbjuste = $nbjuste + 1;
$h = $taille + 1;
}
}
$mot= $data['mot'];
$chaine = strtoupper(\"$mot\");
if ($nbjuste==$taille)
{
echo '----
' . $chaine.', '.$scrabble.' , , ';//On crée une ligne de tableau par mot trouvé...
}
}
}
?>
</td></tr></table>
</html>
18 nov. 2007 à 22:16
14 nov. 2007 à 22:12
Ensuite, puisque seuls les mots comportants 7 caractères au plus sont intéressants, pourquoi ne pas les sélectionner directement dans ta requête :
SELECT * FROM `dico` WHERE length(mot)<8
Cas extrême, si ta table ne sert que pour cette requête, tu peux même envisager la suppression de tous les mots de longeur supérieure à 7 caractères.
13 nov. 2007 à 13:18
Merci de tous ces commentaires.
Pour pouvoir completer un mot tel que entendu, il faudrai entrer tous les mots présents sur le plateau de jeux...ca risque d'etre assez bazard à la fin tout ça, ou alors il faut faire tout le jeux en php, avec le plateau, les lettres les cases triple..Etc...
Vu le newbie que je suis je pense que d'ici 15 ou 20 ans j'y serai arrivé ;-)
En fais j'ai fais ce code pour ma copine qui me saoule quand elle joue genre 'tu voit pas un mot avec ca !?' donc le but premier est en fait de 'tricher' au scrabble, mais si on devai faire un jeux complet en php, il ne faudrait surtout pas reprendre mon code, mais comme je l'ai dis ce n'était pas mon attention non plus !!
Merci encore de vos commentaire (PS: en tant que Newbie, l'utilisation des classes est encore floue pour moi !!)
12 nov. 2007 à 23:55
Effectivement, le fait que ton algo ne trouve pas tous les mots peut être vu comme une limitation. J'ai bien dit, PEUT, parce que c'est proche de ce que fait l'humain : rares sont les personnes capables de trouver TOUS les mots possibles avec un tirage en moins de XX secondes. Cependant, ce n'est peut-être pas ce qu'on attend d'un logiciel.
Tu dis qu'il ne trouvera pas malus à mettre sur le u de entendu. Certes. Mais était-ce bien là le but de cette source ? Si j'ai bien compris ce que j'ai vu, elle sert surtout à dire quels sont les mots possibles avec un tirage. Après, ce serait à l'humain de voir lesquels peuvent être placés, combien de points chacun rapporte, comment gêner l'adversaire en prenant le mot compte triple avant lui, etc.
Pour la construction de malentendu à partir de entendu, je ferais pas comme ça... Partant de ce mot, je cherche ceux qui existent qui le contiennent. Je vérifie pour chaque mot quelles sont les lettres nécessaires et une simple regex me dit si je les ai ou pas. Je ne comprends pas ton histoire d'alternance gauche/droite... C'est pas de la politique au moins ?
12 nov. 2007 à 23:44
Enfin, ce cas là est tendancieux en fait lol...
si j'ai "entendu" et que je veux faire "malentendues", il le trouvera sans doute si on fait du backward.
Ce qu'il ne trouvera sans doute pas c'est à partir de "entendu", placer "malus" sur le "u".
Mais encore une fois, tout dépend de comment on le gère. On peut partir à gauche ou à droite...ou les deux (en fait il faut faire les deux, il faut faire du backward). Ca n'a pas vraiment d'importance.
Il est facile dans le 1er cas, de partie de "entendu" et d'arriver à "malentendues" : je vérifie à gauche mon chemin : lentendu, j'ai le "l". Je continue "alentendu", j'ai le a. je continue...malentendu, j'ai le m. Je vérifie si le chemin peut continuer : à gauche, non. A droite ; j'ai le e..j'ai le s. Evidemment, on fera sans doute les deux (gauche - droite) alternativement...c'est à tester.
12 nov. 2007 à 23:27
ENTENDU => MALENTENDUES
Donc l'idée de l'arbre, ouais, mais c'est applicable dans ce cas là ?
Perso, c'est pas que le jeu de scrabble m'intéresse à développer en PHP, mais je trouve que la problématique est fichtrement intéressante.
12 nov. 2007 à 23:18
je m'incruste :-)
Moi je pense qu'en l'état, avec une simple liste de mots, on ne peut pas s'en sortir facilement et surtout rapidement.
L'idée de Neige sur les anagrammes est une bonne idée.
Mais il y a mieux je pense. Il faut représenter le dico sous forme d'arbre.
Par exemple : talus et tasse commence par la même syllable (ta, pour ceux qui n'auraient pas suivi ;-)).
On aurait donc un chemin t -> a -> l...
ou t -> a -> s...
Difficile de représenter un arbre ici hein...mais bon, la racine est la même pour les deux mots, et leur chemin se sépare vers d'autres feuilles à partir de la 3ème lettre.
salut et talus ne sont du coup plus du tout sur le même chemin.
Par contre, cela permet d'une part d'économiser beaucoup de place, et d'autre part cela accélère les traitements ! il suffit de commencer par chercher les débuts possible pour chaque lettre, puis d'avancer et d'abandonner (ou d'afficher si on a un mot complet) en fonction des lettres suivantes.
Je pense que c'est rapide, en tous cas dans un langage applicatif...
Par contre cela impose de se passer de base de données (je me vois mal représenter un arbre avec une bdd relationnelle).
C'est un algorithme connu, écrit il y a fort longtemps...et si c'était efficace il y a fort longtemps, il y a des chances pour que ça le soit toujours ;-) Il me semble d'ailleurs que c'était pour le scrabble!
12 nov. 2007 à 22:27
12 nov. 2007 à 21:57
En plus, il faut que le moteur soit MyISAM, la recherche FULL-TEXT ne fonctionne pas avec une table InnoDB...
Moi, je cale...
12 nov. 2007 à 21:43
Vais faire quelques tests avec AGAINST, histoire de voir...
12 nov. 2007 à 20:53
A la rigueur on peut utiliser les anagramme avec une recherche de type REGEXP du genre "a{0,1}d{0,1}e{0,2}i{0,1}r{0,1}v{0,1}" cela permettra de récupérer uniquement les mots ayant tes lettres en bonne quantité.
Enfin faudrais bencher pour savoir si c'est AGAINST ou REGEXP qui remporte le concours parce que j'en ai aucune idée XD
12 nov. 2007 à 14:11
Ben justement, je cherche aussi...
On pourrait faire une regexp avec toutes les possibilitées permutations sans répétition des lettres (ça fait 7! , soit 5040). Je pense pas que ce soit pertinent...
Peut-être que la base de données telle qu'elle est conçue ne permet pas d'optimiser à mort le traitement.
Je suis en train de penser que si les mots étaient stockées sous forme d'anagrammes, les lettres de ces anagrammes étant par ordre croissant, ça pourrait peut-être faciliter les choses. Il faudrait alors deux tables, une pour les anagrammes, une pour les mots (à un même anagramme peut correspondre plusieurs mots)
Ainsi le mot bonjour serait associé à l'anagramme bjnoour
salut et talus => alstu
A partir de là, la fonction native de recherche de MySQL en texte intégral (AGAINST) pourrait permettre de faire de bonnes choses (mais j'ai pas trop creusé, donc je me gourre peut-être complètement)
http://dev.mysql.com/doc/refman/5.0/fr/fulltext-search.html
http://dev.mysql.com/doc/refman/5.0/fr/fulltext-query-expansion.html
12 nov. 2007 à 11:51
"Ouhaaaaaaaa alors elle peut vraiment servir à quelque chose !?" J'arriverai bien à lui trouver une utilité à ta classe parce que perso je la trouve chouette XD
Sinon je suis assez content car le code que j'ai envoyé par MP contient pas mal de tes recommandations =P
J'effectue une recherche dans la base de donnée en enlevant toutes les lettres qui ne sont pas parmis les 7 lettres (grâce à un REGEXP), puis je trie les résultats en vérifiant si on a assez de lettres pour former le mot.
Bon je n'ai pas utiliser FilteredIterator (puisque ce code n'est pas une classe) mais c'est vrai que celà aurait été plus pratique =P
Par contre je ne comprends pas ton exemple avec la fréquence d'apparition de lettre... Comment peut-on faire celà ?
12 nov. 2007 à 05:31
"Audalys, je suis d'accord pour faire une requete qui contient au moins une des lettres mais, je ne vois pas quelle requete faire..."
Quelque chose qui ressemble à ça ?
// $lettres est un tableau des lettres du tirage du genre $lettres = array('a', 'e', 'n', 'b', 'o', 'j', 'n');
$motif = '(' . implode('|', $lettres) . ')';
$sql = sprintf('SELECT mot FROM dico WHERE mot REGEXP \'(%s)\' GROUP BY mot', $liste_lettres);
On peut faire une requête qui sort les mots qui ont deux lettres du tirage :
$motif = str_repeat('('.implode('|', $lettres).')', 2);
$sql = sprintf('SELECT mot FROM dico WHERE mot REGEXP \'%s\' GROUP BY mot', $liste_lettres);
Avec autant de lettres qu'on veut, même. Le seul problème, c'est que la requête ne tient pas compte d'une utilisation précédente d'une lettre.
Ainsi, si le tirage contient un seul E, la requête s'en cogne et sort tous les mots qui contiennent un E, ou deux, ou trois...
En répétant le motif de recherche 3 fois avec les lettres données en exemple, j'obtiens 4308 résultats sur la table que tu fournis, contre plus de 42000 s'il n'est recherché qu'une seule fois.
Par contre, le temps de traitement...
Affichage des enregistrements 0 - 29 (4 308 total, traitement: 0.9857 sec.)
Après, pour épurer ça, un FilteredIterator ça devrait faciliter le travail. Mais en terme de performances... Ca devrait déjà être mieux que ton script d'origine ;)
12 nov. 2007 à 05:16
audayls : "Ensuite pour analyser les mots en selectionner ceux qui peuvent fonctionner, tu peux fortement simplifier ton code en utilisant la class "STRING ITERATOR" récemment postée."
=> Ouhaaaaaaaa alors elle peut vraiment servir à quelque chose !?
audayls : "Au lieu de selectionner tous les mots il faudrait uniquement selectionner les mots contenant au moins une des 7 lettres."
=> Pour ça, il pourrait être pertinent de trier les lettres du tirage par ordre croissant de fréquence dans le vocabulaire français. Puisqu'il y a peu de mots avec Z, mais beaucoup plus avec E, si on trouve un Z, on limite au maximum les résultats, et ainsi de suite.
Teclis01 : "
foreach($_POST as $sNameInputLettre=>$sLettre{
$sQuery.=" mot=%'$lettre%' and";
}
"
=> J'aime pas trop. Je préfère utiliser implode(), c'est plus propre, et certainement plus rapide puisque c'est une fonction C.
Ca donnerait :
$sQuery = implode(' AND ', $_POST);
1 seule ligne au lieu d'une boucle... Je crois que y'a pas photo.
Mais je crois effectivement qu'une requête avec des AND n'est pas judicieuse.
Et avec une regexp dans la requête SQL, on devrait pouvoir faire des choses intéressantes...
11 nov. 2007 à 23:16
Regarde dans tes MP c'est noël avant l'heure =P
11 nov. 2007 à 19:09
Heu...débutant je suis...bon c'est pas que je suis contre vos idées, mais y'a des trucs que je pige pas en fait..!
En fait Teclis01, je n'ai pas trouver d'autre moyen que l'imbriquage de boucle pour chercher tous les mots : 7 et inférieurs à 7 lettres. POur la suite de ton code...j'ai rein compris...désolé...je vois que tu a fabriquer un autre type de query, c'est à partir du 'foreach' que je pige pas..;
Audalys, je suis d'accord pour faire une requete qui contient au moins une des lettres mais, je ne vois pas quelle requete faire...
Merci encore de ne pas m'avoir flagellé !!!
11 nov. 2007 à 18:45
Je ne pense pas que ta méthode soit bonne Teclis01. Il se peut que tes 7 lettres ne puissent pas faire un mot de 7 lettres.
Ce qu'il faudrait faire, je pense vu la taille de la table, c'est deja d'améliorer la requête MySQL. Au lieu de selectionner tous les mots il faudrait uniquement selectionner les mots contenant au moins une des 7 lettres.
Ensuite pour analyser les mots en selectionner ceux qui peuvent fonctionner, tu peux fortement simplifier ton code en utilisant la class "STRING ITERATOR" récemment postée.
Pour finir tu pourrais classer les mots possible en les classant selon les points qu'ils rapportent.
11 nov. 2007 à 18:26
if($data['long'] <= 7)//Pour les mots <= à 7 (7 lettres par tirage au Scrabble)
$taille = $data['long'];
tant qu'a faire hein ;)
Mon dieu ce que c'est lourd... huhu j'aime les boucles mais il y a des limites ^^
Heureusement que tu as pas 27 boucles imbriquées sinon tu n'aurais plus de lettres pour tes compteurs de boucle :p
Non franchement je vais pas être chiant sur le typage mais au moins des variables explicites ...ça mange pas de pain
Ensuite je me demande si il n'y a pas plus simple ... du genre...
$iLettres=count($_POST);
$sQuery='select mot from dico where';
foreach($_POST as $sNameInputLettre=>$sLettre{
$sQuery.=" mot=%'$lettre%' and";
}
substr($sQuery,0,strlen($sQuery)-3)); //on vire le dernier and
mysql_query($sQuery);
(je peux me tromper puisque c'est une idée a vif)