onjour,
J'ai réalisé un logiciel en C# et Sqlite pour m'aider au jeu "4 images et 1 mot", et ça fonctionne plutôt pas mal.
Afin de pouvoir partager mon outil et avoir quelque chose de multiplateforme j'ai décidé d'en faire une version web et tout coder en php avec Mysql.
Le principe est simple, j'ai créé une table contenant plus de 700 000 mots de la langue française (elle contient les variantes, verbes et adjectifs quand c'est le cas pour chaque mot de base rassurez vous!), qui est constituée du mot, de sa taille et de sa signature: une colonne pour chaque caractère (donc 26) + une pour les jokers (j'inclus les espaces, tirets et apostrophes etc.). et pour chaque colonne je renseigne le nombre de fois où le caractère apparait dans le mot... exemple: coco -> a = 0, b = 0, c = 2, d = 0 [...] o = 2, [...] z = 0
Pour chaque planche du jeu 4 img et 1 mot, on a un jeu de lettres proposés et une taille de mot (plus petite que le jeu de lettres).
Je calcule donc l'ensemble des combinaisons alliant le jeu de lettre et la taille du mot (pas les permutations, c'est important pour les performances) et pour chaque combinaison je génére la signature, chaque signature étant stockée j'ai ensuite un beau tableau... et donc
il suffit de faire avec sql un sélect pour chaque signature de combinaison avec en clé supplémentaire la taille du mot, et de récupérer les mots qui correspondent, et cela avec l'ensemble des combinaisons pour avoir le mot qu'on doit trouver dedans (ensuite c'est l'humain qui a l'aide des images indices fait le tri).
ça marche bien, par contre j'ai un facteur 10 niveau performance entre mon appli C# (la plus rapide) et mon appli Php, et j'aimerais savoir comment optimiser ça.
pour un mot de 6 lettres dans la séquence iqnafpgdelru, il y a 924 combinaisons à tester, en C# ça me prend 2'10, en Php il m'a fallu plus de 22'.
En C# je fais continuellement des ouvertures/fermeture de la base (un fichier Sqlite pour rappel... je pense pas que ce soit aussi performant qu'un sgbd) pour chaque combinaison, en Php avec Mysql j'utilise les requêtes préparées et je déclare un seul objet PDO que j'utilise du début à la fin, et malgré ça les résultats sont une catastrophe...
Une idée?
Code de ma fonction de recherche de mots:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public static function fetchWords2($signs,$size) // $signs est un 2dim tableau, chaque élément est un tableau qui a la signature d'un mot, $size est un int { // query de la requête préparée $reqselsign = "select * from word where length=? and a=? and b=? and c=? and d=? and e=? and f=? and g=? and h=? and i=? and j=? and "; $reqselsign .= "k=? and l=? and m=? and n=? and o=? and p=? and q=? and r=? and s=? and t=? and u=? and v=? and w=? and x=? and y=? and z=?;"; if(!isset($size) or $size <2 or !isset($signs)) return array(); try { $db = new PDO(self::$connectionstring, self::$username, self::$pwd); } catch(Exception $e) { die('DB error, stop! : '.$e->getMessage()); } $wordslist = array(); // notre tableau de liste des mots à retourner à la fin $req = $db->prepare($reqselsign); foreach($signs as $signa) // pour chaque sous-tableau "signature d'un mot" $signa { // $param est la liste des paramètres de ma requête, sur plusieurs lignes uniquement pour plus de visibilité $param = array($size,$signa["a"],$signa["b"],$signa["c"],$signa["d"],$signa["e"],$signa["f"],$signa["g"],$signa["h"],$signa["i"],$signa["j"],$signa["k"]); $param = array_merge($param, array($signa["l"],$signa["m"],$signa["n"],$signa["o"],$signa["p"],$signa["q"],$signa["r"],$signa["s"],$signa["t"])); $param = array_merge($param, array($signa["u"],$signa["v"],$signa["w"],$signa["x"],$signa["y"],$signa["z"])); $req->execute($param); while ($data = $req->fetch()) { $wordslist[] = $data["name"]; // récupérer le mot stocké dans la colonne name et l'ajouter à notre liste résultat } $req->closeCursor(); } return $wordslist; }