Dans un jeu de mots similaire à la ruée ou à la typographie, où les utilisateurs doivent construire des mots sur un ensemble donné de lettres:
p>
Je garde mon dictionnaire dans une simple table SQL: p> car la durée du jeu est très courte ne veulent pas vérifier tous les mots saisis en appelant un script PHP, ce qui aurait l'air de ce mot dans la table à la place, je voudrais télécharger tous les mots possibles par Un script PHP appelle avant que le tour commence - puisque toutes les lettres sont connues. P> et faire le mot correspondant à l'intérieur d'un script PHP (contre à l'intérieur de la base de données) prendrait probablement trop de temps (à cause de bande passante: devrait aller chercher à chaque rangée de la base de données sur le script php). P> Toute suggestions ou informations s'il vous plaît? p> Utilisation de PostgreSQL-8.4.13 avec CENTOS Linux 6.3. p> mise à jour: strong> p> Autres idées J'ai: P> Good_words code>. p>
Good_words CODE> TABLE, qui aurait la même lettre que dans le mot
Word code> colonne, mais triés alphabétiquement ... mais je Je ne peux toujours pas penser à un moyen de faire correspondre un ensemble de lettres. P>
A code>,
b code>, ...,
z code> et chaque fois que je stocke un mot code> dans
Good_words CODE>, stockez la lettre se terminant. Je me demande S'il est possible de créer un déclencheur d'insertion dans PL / PGSQL A> Pour ça? Li>
ol> p>
7 Réponses :
Créer une table qui comporte des entrées (ID, CHAR), nez le nombre de caractères que vous interrogez. ou (correspondant partiel) P> select id, count(char) AS count from chartable where (char = x or char = y or char = z ...) group by id order by count;
Cela pourrait être un début, sauf que cela ne vérifie pas si nous avons suffisamment de lettres, uniquement s'il a les bonnes lettres.
WITH words AS (SELECT word, substring(word,s,1) as sub from (select word,generate_series(1,length(word)) as s from ( SELECT word from (select word,generate_series(1,length(word)) as s from good_words) as q GROUP BY word HAVING array_agg(substring(word,s,1)) <@ ARRAY['t','e','s','e','r','e','r','o','r','e','m','a','s','d','s','s'] )as q) as q) SELECT DISTINCT w.word FROM ( SELECT word,words.sub,count(DISTINCT s) as cnt FROM (SELECT s, substring(array_to_string(l, ''),s,1) as sub FROM (SELECT l, generate_subscripts(l,1) as s FROM (SELECT ARRAY['t','e','s','e','r','e','r','o','r','e','m','a','s','d','s','s'] as l) as q) as q) as let JOIN words ON let.sub=words.sub GROUP BY words.word,words.sub) as let JOIN (select word,sub,count(*) as cnt from words GROUP BY word, sub) as w ON let.word=w.word AND let.sub=w.sub AND let.cnt>=w.cnt GROUP BY w.word HAVING sum(w.cnt)=length(w.word) ORDER BY w.word;
Wow, essayant de comprendre cela en testant des extraits dans le violon SQL ... L'instruction SQL avec des mots comme (Sélectionnez ....) CODE> - Cela crée-t-il une table temporaire appelée
mots code>? Et l'utilise dans un
rejoindre code>?
@Alexandrefarber Oui, il fait. C'est un CTE ( Postgresql.org/docs/8.4/static/queries- avec.html ).
Nice question, j'ai suscité.
Qu'est-ce que vous êtes à la hauteur, c'est une liste de toutes les permutations possibles des lettres données d'une longueur donnée. Comme décrit dans le PostgreSQL Wiki , vous pouvez créer une fonction et l'appeler comme ceci (correspond aux lettres en surbrillance Dans votre capture d'écran): p> maintenant, pour interroger le Good_words code> Utilisez quelque chose comme: p>
SELECT gw.word, gw.stamp
FROM good_words gw
JOIN permute('{E,R,O,M}'::text[]) s(w) ON gw.word=array_to_string(s.w, '');
Comme une jointure avec une temp. Table générée par ce procéder? Bonne idée! Cependant, je pense qu'il est préférable d'avoir la liste de bons mots comme Origine i> Vs. générant une liste de toutes les permutations de toutes lettres possibles - dont beaucoup ne seront pas des mots valides ...
ne fonctionne pas dans 8.4. Probablement 9.1+ seulement. SQL FIDELLE
select word from ( select unnest(string_to_array(word, null)) c, word from good_words intersect all select unnest(string_to_array('TESTREROREMASDSS', null)) c, word from good_words ) s group by word having array_agg(c order by c) = (select array_agg(c order by c) from unnest(string_to_array(word, null)) a(c))
Le violon manquant: sqlfiddle.com/#!12/b9764/1 le Quatrième bouton VOUS CHANGEZ DELIMITER afin que cela ne s'engage pas sur le point-virgule (mais tout en tapissant dans une ligne fonctionne aussi)
@Jakub merci. Le corrigé pour 8.4
Vous pouvez ajouter la colonne avec des lettres SORTERD formatées comme '% A% C% T%'. Ensuite, utilisez la requête: pour trouver des mots pouvant être construits à partir de lettres 'Abcttx'. Je ne sais pas sur la performance, mais la simplicité ne peut probablement pas être battu :) p> p>
Il attraperait acte code> mais pas
CTA code>. Essayez
Sélectionnez 'Abctx' comme '% C% T% A%' code>
@Clodoaldoneto Oui, c'est pourquoi vous devez trier les lettres avant de les stocker dans la colonne (afin de ne jamais stocker '% C% T% A' Là). Aussi les lettres de la requête doivent être triées
C'est très simple lorsque le mot est déjà trié. Avez-vous essayé de trier une chaîne en 8.4? Et insérer le % code>? J'ai essayé et j'ai dû construire une fonction de PLPGSQL non triviale.
@Clodoaldoneto un petit piratage: Sélectionnez '%' || Array_to_string (tableau (Sélectionnez Regexp_split_to_Table ('Cat', '. *?') Commander par 1), '%') || '%' code>
Vous devriez inclure cela dans votre réponse car le OP ne peut probablement pas le comprendre. À propos de la performance La seule chose que je peux deviner est qu'un comme code> d'expression commençant par un
% code> est mauvais. Seul l'OP peut compenser tout cela. Je fais tous ces commentaires sur votre réponse juste parce que cela a attiré mon attention et je l'aime beaucoup. Je ne votons tout simplement pas comme ma politique de ne pas voter sur les réponses où j'ai également répondu.
Voici une requête qui trouve les réponses qui peuvent être trouvées en parcourant des champs adjacents.
with recursive input as (select '{{"t","e","s","e"},{"r","e","r","o"},{"r","e","m","a"},{"s","d","s","s"}}'::text[] as inp), dxdy as(select * from (values(-1,-1),(-1,0),(-1,1),(0,1),(0,-1),(1,-1),(1,0),(1,1)) as v(dx, dy)), start_position as(select * from generate_series(1,4) x, generate_series(1,4) y), work as(select x,y,inp[y][x] as word from start_position, input union select w.x + dx, w.y + dy, w.word || inp[w.y+dy][w.x+dx] from dxdy cross join input cross join work w inner join good_words gw on gw.word like w.word || '%' ) select distinct word from work where exists(select * from good_words gw where gw.word = work.word)
+1 Merci! Mais je pense que cela a le même problème que la suggestion de Vyegorov: vous générez d'abord toutes les combinaisons de lettre possibles (qui sont beaucoup, en particulier pour les plus grandes cartes - et beaucoup d'entre eux ne sont pas valides), puis correspondent au Good_words code> . Il me semble plus efficace de commencer à partir de l'autre extrémité: passer par le
Good_words code> et (en quelque sorte, qui fait l'objet de ma question) essayez de faire correspondre les lettres du tableau.
Remarque Il y a une taille dans la mesure où elle élimine les mots générés pour lesquels il n'y a pas de préfixe dans Good_words. Mais je viens de l'essayer sur une liste de mots réelle et c'est très lent, alors pas vraiment utilisable. Voir mon autre réponse :)
Ma propre solution consiste à créer Un déclencheur d'insertion , qui écrit des fréquences de lettre dans une colonne de matrice: puis je génère une matrice similaire pour la chaîne de carte aléatoire Toutes les nouvelles idées ou améliorations sont toujours les bienvenues! p> p> Tesereroremasss code>
et comparez les deux tableaux à l'aide du Array contient opérateur
@ > code> p>
A) Cela va probablement toujours être une liste très longue i> de mots qui doit être téléchargée là-bas, B) qui donne à un utilisateur technique un excellent moyen de tricher. ;)
En fait, non: Roulez les rapports Nombre de mots possibles à la fin des rondes et que le nombre dépasse rarement 300. Même avec une longueur de mots supposée de 10 lettres qui seraient simplement de 3 kbyte - avant la gzipping.
Pouvez-vous télécharger une vidange CSV de
Good_words CODE> Table d'un endroit pour jouer avec? Ou fournir une autre source, s'il vous plaît?
Ce sera vraiment inefficace. Vous devriez presque certainement cacher la liste de mots de la base de données en tant que fichier compressé que le client effectue une demande HTTP simple. Vous pouvez définir des en-têtes HTTP modifiés si vous éviterez la récupération si elle n'a pas changé. Si cette liste de mots devient trop grosse, ce que vous faites est de créer un sous-ensemble de mots les plus fréquemment essayés (pas nécessairement corrects de mots) que vous avez mis dans le cache du client, et si le cache du client ne connaît pas le mot qui lui demande le serveur. via une demande de service Web. Le client peut ajouter la liste de mots téléchargée à SQLite, BDB ou similaire pour la recherche rapide.
+1 pour une idée intéressante sur la pré-mise en cache des mots communs dans l'application :-)