VBA Excel - Récursivité - Jeu du Boggle

Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
-
Bonjour Mesdames, Messieurs,

Il y a deux ans, j'ai voulu créer une fiche pratique, sur CCM, intitulée "le jeu du boggle". visible ICI. Comme vous pourrez le voir en y jetant un oeil, c'est pas mal, mais pas top...

A l'époque, je ne connaissais pas la récursivité et j'avais toutefois réussi à "bricoler" un code qui à défaut d'être parfait, fonctionnait à peu près.

Fini l'à peu près pour moi, je souhaites refonder ce code afin de le rendre réellement opérationnel.

Pour cela, je vais avoir besoin de vous...

Il faut, pour cette "appli", plusieurs codes. Je vais créer, dans ce sujet, une réponse par code. Suffira de suivre en commentant ces réponses pour améliorer les codes VBA proposés.

Les différents codes nécessaires :
- récupérer un dictionnaire extrait d'un fichier .txt dans une variable sous VBA (soit une variable tableau, soit un objet dictionary)
- tirage aléatoire des lettres,
- comparaison des lettres du tirage avec l'alphabet afin de voir qu'elles lettres sont manquantes,
- grâce aux lettres manquantes, épurer la liste des mots du dico,
- trouver peut être une seconde méthode d'épuration de cette liste...
- créer un code qui va trouver les mots du dico pouvant être formés à partir de lettres adjacentes de la grille.

Voici déjà le classeur de base, avec :
- un range nommé grille '-----> Menu Insertion/Noms/Définir
- trois boutons de commande :
=>tirage (il fonctionne) -- Code : Sub Tirage()
=>solutions (ne fonctionne pas) -- code : Sub RetirerMotsLettresManquantes()
=>efface (il fonctionne) -- Code : Sub Efface()

Le classeur : http://cjoint.com/?DBgpyvwtxf3

Pour celles et ceux qui n'aiment pas trop télécharger via des sites de pièce jointe, envoyez moi votre mail perso via MP, je vous ferais un envoi particulier.

Merci d'avance.
Cordialement,
Franck
Afficher la suite 

20/71 réponses

Meilleure réponse
Messages postés
14841
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
9 novembre 2019
2
2
Merci
Bonjour a vous tous,

A la demande de Pijaku, j'ai donc fait des test sur deux versions et cela donne les resultats suivants:

Test sous W8, Intel core I5--3210M 2.5GHz:

peu importe la version excel, resultats sensiblement identiques et seulement 32% occupation processeur

boggle-like_v0.43test.xls

XL 2007
- Charger dico : 3.38 s
- Détruire : 174.80 s

XL 2010
- Charger dico : 3.16 s
- Détruire : 173.30 s

XL 2013
- Charger dico : 3.45 s
- Détruire : 177.66 s


boggle-like_v0.43_v2_test.xls

XL 2007
- Charger dico : 3.41 s
- Détruire : 177.19 s

XL 2010
- Charger dico : 3.20 s
- Détruire : 176.68 s

XL 2013
- Charger dico : 3.31 s
- Détruire : 178.71 s


A+

Dire « Merci » 2

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 210 internautes nous ont dit merci ce mois-ci

f894009
Messages postés
14841
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
9 novembre 2019
2 -
Re,

172.71 s pour la destruction, reste dans la plage 173-179
carlvb
Messages postés
199
Date d'inscription
mercredi 23 avril 2003
Statut
Contributeur
Dernière intervention
25 mai 2017
2 -
Re,

Encore merci pour ces résultats. Il y a vraiment donc un problème lors de la destruction, la mémoire met trop de temps à se libérer chez quatre testeurs différents.

Bonne soirée.
f894009
Messages postés
14841
Date d'inscription
dimanche 25 novembre 2007
Statut
Membre
Dernière intervention
9 novembre 2019
2 -
Re;

a titre indicatif: 943873 passages dans

Private Sub Detruire_Noeud(ByRef Noeud As Classe_Noeud)

Normal ou pas ?????

si cela peut vous aidez .
ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213 -
pardonnez-moi, mais je persiste et signe : très rapide chez moi, tant au chargement (4 secondes en moyenne) qu'au "vidage "'en moins de deux secondes).
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Bonsoir,

Merci déjà à tout le monde pour ces tests.

Pour répondre à ucfoutu - 4 mars 2014 à 18:31 :
après l'avoir sauvegardé dans un autre dossier, fermé, puis ouvert à nouveau ?
C'est dingue ça tout de même!
J'ai suivi ta démarche et c'est nickel!
il faut donc :
- enregistrer les fichiers sous un dossier
- ouvrir le .xls
- indiquer le chemin du .txt en C3
- Enregistrer sous le fichier .xls dans un autre répertoire (avec ou pas changement de répertoire du .txt)
- fermer puis ouvrir le .xls et...
Destruction du dictionnaire en même pas 2 secondes.

Excel 2007. Je referais demain le test avec 2011...
C'est bluffant cette histoire.
Cela s'explique? Si oui, je suis bien curieux de comprendre...

Sur ce, bonne soirée à tous.
Commenter la réponse de f894009
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
1
Merci
Ta "charnière", pijaku , c'est la conjugaison des deux.
Il est adroit (même si lent) de réduire la liste les mots possibles.
Mais il n'est pas adroit, une fois établie cette liste "épurée", de travailler depuis elle plutôt que depuis les chemins de la grille.
Ta manière de retirer les mots impossibles n'est toutefois pas forcément la plus complète et la plus adroite.
Je vais m'atteler (après ma partie de pêche) à cette première étape que nous appellerons étape d'épuration.
Commenter la réponse de ucfoutu
Messages postés
13942
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
10 novembre 2019
316
1
Merci
Bonsoir, j'ai finit le mien, en C#, je suis plus à l'aise dans ce langage.

Comme Uc j'avais remarqué que la position des dés est figée dans ton xls. J'ai pensé à une erreur, et mon tirage est aussi aléatoire dans la position.
C'est corrigeable au besoin.

Pour le principe, je charge une fois le dictionnaire, passe tout en majuscule sans accent.
Mon chargement supprime les mots composés, mais je peux changer ça aussi

Ensuite j'initie chaque dés et effectue le tirage, chaque dé connait ses coordonnées pour la construction des mots.

Je commence par le dé en haut à gauche, je cherche les dés adjacents, j'en choisi un.
S'il existe des mots qui commence par ces deux lettres, je réduit le dico à ces mots (très gros gain de temps dans les recherches!)
je recherche les adjacents en excluants les deux premiers dés et ainsi de suite de manière récursive.
Si un chemin de plus de trois lettres est un mot connu, il est stocké.

Voici le code

Le dictionnaire
    /// <summary>
    /// Classe permettant de charger et de gérer le dictionnaire
    /// </summary>
    public class Dico
    {
        private List<string> dico;
        private IEnumerable<string> dicoAppure;

        public Dico(string path)
        {
            Ouvrir(path);
        }

        /// <summary>
        /// Charge le fichier en paramètre, passe tous les mots en majuscules sans accent, exclu les mots composés
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public List<string> Ouvrir(string path)
        {
            char[] separateurs = { ' ','/','\t', '\\', Convert.ToChar(10) };
            string[] tab = File.ReadAllText(path,Encoding.ASCII).Split(separateurs);

            Regex maRegex = new Regex("^[A-Z]{3,}$");
            
            dico = (from mot in tab
                                 let m = RemoveDiacritics(mot.Trim()).ToUpperInvariant()
                                 where m.Length > 2 && maRegex.IsMatch(m)
                                 select m
                                
                                
                                ).ToList<string>();



            return dico;                   
        }

        /// <summary>
        /// Methode qui supprime les accents, source http://www.developpez.net/forums/d286030/dotnet/langages/csharp/supprimer-accents-lettre/
        /// </summary>
        /// <param name="stIn"></param>
        /// <returns></returns>
        private string RemoveDiacritics(string stIn)
        {
            string stFormD = stIn.Normalize(NormalizationForm.FormD);
            StringBuilder sb = new StringBuilder();

            for (int ich = 0; ich < stFormD.Length; ich++)
            {
                UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
                if (uc != UnicodeCategory.NonSpacingMark)
                {
                    sb.Append(stFormD[ich]);
                }
            }

            return (sb.ToString().Normalize(NormalizationForm.FormC));
        }

        /// <summary>
        /// Liste de mots qui constitue ce dictionnaire
        /// </summary>
        public List<string> Liste { get { return dico; } }
    }



un dé

    public class De
    {
        private string faces;

        /// <summary>
        /// Construit un dé à partir d'un string listant chaque face
        /// </summary>
        /// <param name="Faces"></param>
        public De(string Faces)
        {
            faces = Faces;
        }

        /// <summary>
        /// Abscise du dé dans le tableau
        /// </summary>
        public int X { get; set; }

        /// <summary>
        /// Ordonnée du dé dans le tableau
        /// </summary>
        public int Y { get; set; }

        /// <summary>
        /// Face visible après le tirage
        /// </summary>
        public string FaceVisible { get; set; }

        /// <summary>
        /// Index du dé dans la liste
        /// </summary>
        public int Index { get; set; }

        /// <summary>
        /// Méthode choisant aléatoirement la face visible, les coordonnées du dé dans le plateau sont transférés par cette méthode
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        public void Tirage(int X, int Y)
        {
            Random rdm = new Random();
            FaceVisible = faces[rdm.Next(faces.Length-1)].ToString();
            this.X = X;
            this.Y = Y;
            Index = 4 * X + Y;
        }

        /// <summary>
        /// Retourne les dés adjacents à l'instance en cours, en sortant les dés contenus dans la liste exception
        /// </summary>
        /// <param name="Tirage">Tableau de dés correspond au tirage</param>
        /// <param name="excepetions">Liste de dés à exclure du resultat</param>
        /// <returns></returns>
        public List<De> Adjacents(List<De> Tirage, List<De> excepetions)
        {
            return (from De d in Tirage
                    where (d != this && Math.Abs(d.X - X) < 2 && Math.Abs(d.Y - Y) < 2)
                    select d
                    ).Except(excepetions).ToList<De>();
        }

        public override string ToString()
        {
            return FaceVisible;
        }

    }


le tirage et la recherche de solution
    public class Tirage
    {

        List<De> tires;

        /// <summary>
        /// Assure le tirage des disponibles 16 dés et la recherche de solutions
        /// </summary>
        /// <returns></returns>
        public Tirage(Dico MonDico)
        {
            this.MonDico = MonDico;

            Solutions = new List<string>();

            NouveauTirage();
        }

        public void NouveauTirage()
        {
            //dés disponilbes
            List<De> disponibles = new List<De>();
            disponibles.Add(new De("ETUKNO"));
            disponibles.Add(new De("EVGTIN"));
            disponibles.Add(new De("IELRUW"));
            disponibles.Add(new De("DECAMP"));
            disponibles.Add(new De("EHIFSE"));
            disponibles.Add(new De("RECALS"));
            disponibles.Add(new De("ENTDOS"));
            disponibles.Add(new De("OFXRIA"));
            disponibles.Add(new De("NAVEDZ"));
            disponibles.Add(new De("EIOATA"));
            disponibles.Add(new De("GLENYU"));
            disponibles.Add(new De("BMAQJO"));
            disponibles.Add(new De("TLIBRA"));
            disponibles.Add(new De("SPULTE"));
            disponibles.Add(new De("AIMSOR"));
            disponibles.Add(new De("ENHRIS"));
            
            //dés tirés
            tires = new List<De>();

            //effectue le tirage de la grille
            for (int x = 0; x < 4; x++)
                for (int y = 0; y < 4; y++)
                    UnDe(disponibles, tires, x, y);

            //List<Chemin> chemins1 = CalculChemins();
            List<Chemin> chemins2 = CalculCheminsRecursif();
        }


        /// <summary>
        /// Lance un dé de la liste des dés disponibles, et le place dans la liste des dés tirés
        /// </summary>
        /// <param name="disponibles"></param>
        /// <param name="tires"></param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        private void UnDe(List<De> disponibles, List<De> tires, int X, int Y)
        {
            Random rnd = new Random();
            De monDe = disponibles[rnd.Next(disponibles.Count)];

            monDe.Tirage(X, Y);
            tires.Add(monDe);
            disponibles.Remove(monDe);
        }

        /// <summary>
        /// retourne les dés tirés
        /// </summary>
        public List<De> Des 
        { 
            get { return tires; }
            set { tires = value; }
        }

        /// <summary>
        /// Calcul tous les chemins de 3 dés possibles par récursivité
        /// </summary>
        private List<Chemin> CalculCheminsRecursif()
        {
            List<Chemin> chemins = new List<Chemin>();

            foreach (De d in tires)
            {
                Chemin monChemin = new Chemin();
                monChemin.Des.Add(d);
                RechercheRecursive(monChemin, chemins, MonDico.Liste.FindAll(m => m.StartsWith(monChemin.Texte)));
            }

            Solutions = (from c in chemins
                         select c.Texte).ToList<string>();

            return chemins;
        }

        /// <summary>
        /// Recherche par progression successive dans la grille, on teste s'il existe encore des mots commencant par le chemin
        /// en cours avant d'enclencher une instance supplémentaire.
        /// </summary>
        /// <param name="chemin">Chemin en cours</param>
        /// <param name="chemins">Liste des chemins valide</param>
        /// <param name="dico">dictionnaire appuré à chaque instance</param>
        private void RechercheRecursive(Chemin chemin, List<Chemin> chemins, List<string> dico)
        {
            List<De> adjacents =chemin.DernierDe.Adjacents(tires, chemin.Des);
            if (adjacents.Count == 0) return;

            foreach (De d in adjacents)
            {
                Chemin monChemin = chemin.Clone();
                monChemin.Des.Add(d);

                int i;
                if (monChemin.Texte == "LUNE") 
                    i = monChemin.Des.Count;

                if (monChemin.Texte.Length > 2 && !chemins.Exists(m => m.Texte == monChemin.Texte) && dico.Exists(m => m == monChemin.Texte))//si le mot n'est pas déjà listé, et s'il existe on stocke le chemin
                    chemins.Add(monChemin);

                List<string> dicoReduit = dico.FindAll(m => m.StartsWith(monChemin.Texte));
                if (dicoReduit.Count > 0)
                    RechercheRecursive(monChemin, chemins, dicoReduit);//s'il existe des mots commencant par cette sequence on continue
                else
                    continue;//sinon on passe au dé adjacent suivant

            }
        }

        public Dico MonDico { get; set; }

        public List<string> Solutions { get; set; }

     }


J'ai fait quelques dizaines de tirages ça tourne en moyenne autour d'une seconde de calcul.


Penser aux balises de coloration syntaxique: bouton <>, préciser le langage :<code csharp>.
Quand la solution est trouvée, mettre la discussion Résolue.
Commenter la réponse de Whismeril
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
1
Merci
Bon...
Je vois que les choses sont en de TRES bonnes mains en ce qui concerne les fondements à proprement parler.
Je vais dans ce cas commencer à me pencher, de mon côté, au "camouflage" avancé par pijaku : à savoir "cacher" Excel et utiliser un userform.
Je vais essayer de le faire :
1) sans ne rien perdre de ce qui a été développé à partir d'une grille existante sur Excel
2) sans ne rien toucher aux traitements sur la base de cette grille
3) en "ouvrant" à pijaku la possibilité de choisir la taille et l'emplacement de ma "pseudo grille" à afficher sur l'userform (la seule que l'utilisateur verra finalement)
Je pense y parvenir sans trop de difficultés, mais vais devoir m' "isoler" un peu pour au moins 36 heures (essais obligent).

Je vais par ailleurs essayer (je dis bien essayer, car Excel et son VBA n'ont pas cette vocation) de "gimpiser" le Userform sans faire appel à l'importation d'une image.Je pense simplement à la discussion que pijaku a ouverte sur CCM ici
http://www.commentcamarche.net/forum/affich-29822256-realisation-d-une-image-pour-le-design-d-un-jeu#123
il souhaite une image non "gourmande". Je vais essayer de la réduire à un minimum, quitte à la rendre un peu moins "GIMP"
Je vais surtout m'efforcer d'éviter que des "images" ne viennent réduire à peau ce chagrin la place nécessaire à l'affichage des solutions, hein ...

A très bientôt.

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviend
Commenter la réponse de ucfoutu
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7
0
Merci
Re-

Le premier code est celui du tirage aléatoire des lettres formant la grille.
Le voici :
Sub Tirage()
Dim Cubes As Variant, Cel As Range, cpt As Byte, carac As Integer

cpt = 0
Sheets("feuil1").Range("grille").ClearContents
Cubes = Array("ETUKNO", "EVGTIN", "IELRUW", "DECAMP", "EHIFSE", "RECALS", "ENTDOS", "OFXRIA", "NAVEDZ", "EIOATA", "GLENYU", "BMAQJO", "TLIBRA", "SPULTE", "AIMSOR", "ENHRIS")
Randomize
For Each Cel In Range("grille")
    Do
        carac = CInt((6 * Rnd()) + 1)
        If carac < 6 And carac > 1 Then Cel.Value = Mid(Cubes(cpt), carac, 1)
    Loop While Cel.Value = ""
    cpt = cpt + 1
Next Cel
End Sub


L'array "Cubes" réponds aux contraintes de la règle du jeu, imposant les lettres sur les faces des différents dés...

Cordialement,
Franck
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Super!C'est en effet bien mieux... Plus besoin de tester...
La procédure de tirage est simplifiée :
cubes = Array("ETUKNO", "EVGTIN", "IELRUW", "DECAMP", "EHIFSE", "RECALS", "ENTDOS", "OFXRIA", "NAVEDZ", "EIOATA", "GLENYU", "BMAQJO", "TLIBRA", "SPULTE", "AIMSOR", "ENHRIS")
  touille_cubes cubes '================> voir cette proc plus bas
  Randomize
  For Each Cel In grille
      Cel.Value = Mid(cubes(cpt), CInt((5 * Rnd()) + 1), 1)
      cpt = cpt + 1
  Next Cel
ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213 -
" dans ta procédure touille_cubes, tu utilises Rnd sans avoir au préalable Randomize. Normal? "
Randomize initialise le générateur de nombres aléatoires.
Il est inutile de le réinitialiser. Une fois suffit pour toute ton appli.
Tu pourrais à ce propos l'initialiser d'où tu veux (à l'activate de la feuille, par exemple)
J'en profite pour perfectionner ce générateur, en le liant au chrono du pc :Randomize Timer au lieu de Randomize
J'ai par contre mal placé ce Randomize, qu'il faut générer avant "cubes = ....)
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Oui. Ok.
Dans ce cas, c'est moi qui ai mal adapté ton code, mon
Randomize 
n'arrivant qu'après. Je modifie.
Je ne connaissais pas
Randomize Timer
. Quel est son intérêt?
ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213 -
"Je ne connaissais pas Randomize Timer . Quel est son intérêt?"

le générateur travaille sur la base de valeurs "initiales"
La valeur initiale de randomize timer change sans cesse en fonction de la valeur de la fonction Timer.
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
ok.
Merci. Bien pratique donc.
Commenter la réponse de pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7
0
Merci
Re-

Le second code est celui permettant de retirer des mots de la liste, si une des lettres qui le compose est dans la liste des lettres manquantes.

Sub RetirerMotsLettresManquantes()
Dim lettresutilisees(), lettresmanquantes()
Dim ListeMotsTemp() As String, Lettr$, mot$
Dim i&, j&, k&, test As Boolean
Dim MonDico1 As Object, MonDico2 As Object, c

lettresutilisees = Range("grille") '-----> Menu Insertion/Noms/Définir
Set MonDico1 = CreateObject("Scripting.Dictionary")
For Each c In lettresutilisees
    MonDico1(c) = ""
Next c
Set MonDico2 = CreateObject("Scripting.Dictionary")
For Each c In Array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")
    If Not MonDico1.exists(c) Then MonDico2(c) = ""
Next c
lettresmanquantes = Application.Transpose(MonDico2.keys)
ListeMotsTemp = ListeMots
Erase ListeMots
For i = 0 To UBound(ListeMotsTemp)
    mot = ListeMotsTemp(i)
    For j = 1 To UBound(lettresmanquantes)
        Lettr = lettresmanquantes(j, 1)
        If InStr(mot, Lettr) = 0 Then
            test = True
            Exit For
        End If
    Next j
    If test = False Then
        ReDim Preserve ListeMots(k)
        ListeMots(k) = ListeMotsTemp(i)
        k = k + 1
    End If
Next i
End Sub

Commenter la réponse de pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7
0
Merci
Re-

Ici je souhaites voir avec vous comment extraire les mots se trouvant dans ce dictionnaire (pour info il s'agit du fichier fr.dic disponible avec Firefox... Je n'ai pas été cherché bien loin), pour les placer dans une variable de mon classeur...

http://cjoint.com/?DBgpIuve868

Première question, au vu des données, vous travailleriez avec un objet dictionary ou une variable tableau?

Voici un code réalisé grâce à Internet :
Sub Dictionnaire()
Dim Tb() As String, Chemin As String, num As Long, i As Long

Chemin = ThisWorkbook.Path
num = FreeFile
Open Chemin & "\DicoFirefoxFrancais.txt" For Input As #num
i = -1
While Not EOF(1)
  i = i + 1
  ReDim Preserve Tb(i)
  Line Input #1, Tb(i)
Wend
Close #num
End Sub


Maintenant, il faut traiter le résultat...
Or, le créateur du dico Firefox n'a pas mâché mon "travail". En effet, il n'y a, dans le fichier txt proposé, aucun retour chariot...
Donc, dans le code donné ci-dessus,
UBound(Tb) = 0
...

Cordialement,
Franck
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Voici ce que j'ai pu faire pour "traiter" les données issues du dictionnaire Firefox.

1- La procédure
Le début n'a que peu changé. J'ai juste ajouté un Timer pour chronométrer le temps d'exécution.

Par contre, comme le fichier txt ne comprends qu'une seule ligne, pour n'obtenir que des mots à l'arrivée, il a fallut scinder cette ligne.
La ligne est représentée dans le code par Tb(0).
Scindée :
- en séparant grâce aux "/" (Ligne 20 du code)
- en séparant grâce à des espaces insécables (Chr(9) Ligne 22 du code)
- en séparant grâce à des "passages à la ligne" (Chr(10) Ligne 23)

Option Explicit

Dim ListeMots

Sub Dictionnaire()
Dim Tb() As String, Chemin As String, num As Long, i As Long, PremierJet() As String
Dim Start As Single

Start = Timer
Chemin = ThisWorkbook.Path
num = FreeFile
Open Chemin & "\DicoFirefoxFrancais.txt" For Input As #num
i = -1
While Not EOF(1)
  i = i + 1
  ReDim Preserve Tb(i)
  Line Input #1, Tb(i)
Wend
Close #num
PremierJet = Split(Tb(0), "/")
For i = LBound(PremierJet) To UBound(PremierJet)
    PremierJet(i) = Split(PremierJet(i), Chr(9))(1)
    PremierJet(i) = Split(PremierJet(i), Chr(10))(1)
    PremierJet(i) = RemplaceCarSpec(PremierJet(i))
Next i
ListeMots = Affine(PremierJet)
MsgBox "Enregistrement en mémoire de : " & UBound(ListeMots) & " mots, en : " & Timer - Start & " secondes."
End Sub


Ainsi scindée, nous obtenons une variable tableau composée de mots...
Ou presque.
En fait, il reste des chiffres dans certains mots (ex : 1er = premier) et les caractères spéciaux.

2- Les Fonctions :
Nous allons donc traiter ces mots grâce à deux fonctions :

Fonction n°1 : RemplaceCarSpec (appel Ligne 24 du code) :
Function RemplaceCarSpec(monMot As String)
Dim motTemp As String
motTemp = Replace(monMot, "é", "e")
motTemp = Replace(motTemp, "ï", "i")
motTemp = Replace(motTemp, "è", "e")
motTemp = Replace(motTemp, "-", "")
motTemp = Replace(motTemp, "ç", "c")
motTemp = Replace(motTemp, "ë", "e")
motTemp = Replace(motTemp, "ê", "e")
motTemp = Replace(motTemp, "ü", "u")
motTemp = Replace(motTemp, "â", "a")
motTemp = Replace(motTemp, "ä", "ae")
motTemp = Replace(motTemp, "ô", "o")
motTemp = Replace(motTemp, "ÿ", "y")
motTemp = Replace(motTemp, "î", "i")
motTemp = Replace(motTemp, "Å""", "oe")
motTemp = Replace(motTemp, "û", "u")
motTemp = Replace(motTemp, "æ", "ae")
motTemp = Replace(motTemp, "Ã¥", "a")
motTemp = Replace(motTemp, "ö", "o")
motTemp = Replace(motTemp, "Ã", "a")
motTemp = Replace(motTemp, "É", "e")
motTemp = Replace(motTemp, "È", "e")
motTemp = Replace(motTemp, "Ã...", "a")
motTemp = Replace(motTemp, "Å'", "oe")
RemplaceCarSpec = UCase(motTemp)
End Function

Comme son nom l'indique, elle remplace les caractères spéciaux...

Fonction n°2 : Affine (Appel Ligne 26 du code de la Sub Dictionnaire)
Function Affine(Tbl)
Dim TbTemp(), i As Long, CptTbNum As Long, CptTemp As Long

For i = LBound(Tbl) To UBound(Tbl)
    If Len(Tbl(i)) > 2 And Len(Tbl(i)) < 17 Then
        If Not IsNumeric(Right(Tbl(i), 1)) And Not IsNumeric(Left(Tbl(i), 1)) Then
            ReDim Preserve TbTemp(CptTemp)
            TbTemp(CptTemp) = Tbl(i)
            CptTemp = CptTemp + 1
        End If
    End If
Next i
Affine = TbTemp
End Function

Cette fonction est un peu particulière car nous lui passons une variable tableau en paramètre, et elle nous retourne une variable tableau.
Elle sert à deux traitements :
- La longueur des mots (de 3 à 16 lettres) (cf ligne 5 du code)
- S'ils comportent des caractères numériques en début ou en fin de mot (ligne 6)

Voilà.
A vos avis.
Peut-on notamment améliorer la vitesse d'exécution?
Utilisation d'un objet dictionary?
Autre méthode?
Commenter la réponse de pijaku
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
Bonjour,
je ne connais pas ce jeu (ne suis pas joueur), mais tout me parait défini dans ce que je lis ici :
"Chaque joueur cherche des mots pouvant être formés à partir de lettres adjacentes du plateau. Par «adjacentes», il est sous-entendu horizontalement, verticalement, ou en diagonale. Les mots doivent être de 3 lettres au minimum, peuvent être au singulier ou au pluriel, conjugués ou non, mais ne doivent pas utiliser plusieurs fois le même dé pour le même mot."
A partir de là, si j'ai bien compris :
- tu as une grille composée aléatoirement de 16 lettres
- tu veux chercher si, en suivant un chemin horizontal, vertical ou diagonal tu peux composer un (ou plusieurs) mot(s) d'une liste préexistante.

Des précisions me manquent pour réfléchir :
1) chaque chemin peut-il être parcouru à l'envers ? (exemple dans "amonbc" : ai-je le mot "mon" uniquement ou également le mot "nom" ?)
2) les directions sont-elles "rigides" ou non ?
J'entends par rigide une direction qui, une fois prise, impose qu'elle reste une droite et non un parcours en zig-zag

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviend
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
Pour que tu comprennes bien mes questions :
Prenons l'exemple d'un jeu d'échecs :
- la reine peut s'y déplacer d'un point à un autre dans toutes les directions, mais une seule pour chacun de ses déplacements. Elle n'est pas autorisée à suivre, dans l'un de ses déplacements, un chemin en "zigzag" entre cellules contigües. C'est cela, que l'appelle la rigidité d'un déplacement.

Pour être plus clair :
regarde cette grille :
T P U C
F A O R
A O I J
I X M N
et dis-moi (réponse oui ou non) si tes règles font que le mot PAIX y est une solution admise.

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviend
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Salut,

Pour répondre clairement, oui. PAIX figure dans les réponses possibles, et, si on trouve le mot MON, NOM figurera également parmi les réponses possibles.
D'autres, dans la grille que tu proposes, seraient :
COUPAT
JOUR
MIAOU (à condition qu'il soit dans le dictionnaire)
PAT
PUAT
JOIN
MOI
PURIN
ROI
FAX
FAI (si fournisseur d'accès internet est dans le dico...)
FAIM
etc...
En fait, le chemin se fait en zigzag, en ligne droite ou en un mixe des 2, peu importe, l'important étant qu'une "case" ne peut être utilisée qu'une seule fois par mot. Dans l'exemple précédent, PAIX utilise le P et le A de COUPAT. Les 2 mot sont bons. Par contre, on ne peut pas faire le mot COURIR car le même R serait utilisé 2 fois...

Dis moi, tu t'attaques directement au noeud de mon problème, la fonction récursive qui cherche les mots dans la grille?

En fait, cette étape, que je réservais pour la fin, je souhaite vraiment la construire, ensemble, de A à Z. Y compris par l'établissement au préalable de l'algorithme etc... Vraiment ne louper aucune étape, car je compte m'en servir pour m'exercer à la récursivité...
Tout cela, tu l'auras compris, dans un but pédagogique pour moi, mais également pour les internautes.
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
"Dis moi, tu t'attaques directement au noeud de mon problème"
Oui. Et ne n'est pas par hasard.
Je t'explique :
- je suis fondamentalement "émotif-actif-primaire" (défaut ou qualité ? On va voir)
- le "noeud" d'un problème est pour moi à la fois ce que l'on doit faire en amont pour le traiter/définir/arrêter et ce que l'on "voit" d'utile en lui pour l'utiliser en aval.
Alors, ma foi ... je reste avec mes "élans" incontrôlés et ma pauvre "vision" très personnelle des ensembles.

Ton problème n'est pas simple, compte tenu de plusieurs aspects, parmi lesquels un nombre assez impressionnant de chemins possibles en partant de chacune des lettres de la grille, d'une part et, d'autre part, du fait qu'un "dé" utilisé ne peut l'être qu'une seule fois.****
Il importe de réfléchir très calmement à tout, avant de décider d'une méthode.
Il importe également de ne pas perdre de vue que cette appli est sous VBA/.Excel et que cette particularité pourrait conduire à certaines méthodes que ne permettraient ni VB6 ni VB.Net (qui imposeraient entre autres le traitement d'un tableau dynamique, sans autre possibilité).

*** à ce propos : je ne vois pas dans les "règles" s'il ne peut être utilisé qu'une seule fois en tout et pour tout, ou s'il ne peut être utilisé qu'une seule fois dans un chemin parcouru ====>> va falloir le préciser.

J'attends tes précisions avant de commencer à faire travailler mes pauvres neurones. Je sais d'ores et déjà que le temps de ma réflexion sera bien plus important que celui, une fois arrêtée ma "réflexion", du développement du mécanisme décidé.
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Comme vous le constatez à la lecture de mon post précédent, je part du postulat de chercher, dans la grille, des mots à partir de ma liste.

Une autre possibilité, évoquée par whismeril, consiste à essayer de former des mots dans la grille et comparer avec la liste.
Exemple avec la grille ci-dessus :
- départ en B2, la lettre K, j'élimine de ma liste initiale tous les mots ne commençant pas par K,
- je continue en C2, j'élimine tous les mots ne commençant pas par KI,
- je continue en D2, j'élimine tous les mots ne commençant pas par KIE
- je continue jusqu'à ce que ma liste se réduise à 1 mot ou à 0 mot...
- si 0 mot, je "remonte", ensuite à KI et tente avec D3 KIO...
- si 1 mot, on le stocke et on continue tout de même. On peut, en effet, trouver un autre mot ayant la même racine (exemple des mots conjugués, pluriels etc...)

Mais, à mon niveau de connaissance, je ne sais pas qu'elle méthode est la "meilleure". J'ai juste choisi celle qui, selon moi, est la plus simple...
ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213 -
partir de la liste pour rechercher des mots dans la grille est une méthode très pénalisante si la liste des mots est pléthorique.
C'est donc, quel que soit la méthode (avec ou sans les particularités de Excel) , le chemin "inverse" qu'il faut utiliser : chercher dans la liste si y existe la chaîne évoluant avec le chemin (comme l'entrevoit Whismeril).
Cette dernière méthode est complexe à coder, mais moins pénalisante que la première en cas de liste pléthorique de mots à chercher dans la grille.
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
OK.
Je me fourvoyais donc.
Il me faut donc retourner à ma réflexion, ressortir papier, crayon... et cerveau!
J'y vais de ce pas.
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Tout comptes faits, je ne suis pas sur d'être en accord avec toi.
Je penses que l'on aurait du, au préalable, se pencher sur le problème du dictionnaire à utiliser et surtout sur la manière d'épurer la liste des mots en fonction des lettres de la grille.
En fait, tu parles de liste pléthorique, mais cela dépend de la manière dont elle est traitée.
Afin de s'assurer de la méthode la plus rapide (soit : chercher dans la liste si y existe la chaîne évoluant avec le chemin, soit : chercher, dans la grille, des mots à partir de la liste), il convient de vérifier le nombre des possibilités que doit explorer chacune des méthodes.

J'ai testé le nombre de mots obtenus, à partir du dictionnaire Firefox (67 629 mots au départ), épuré en enlevant simplement les mots comportant une lettre qui n'est pas dans la grille.
Ce test, effectué avec 600 tirages différents, constate les statistiques suivantes :
entre 0 et 1000 mots : 224 tirages
entre 1000 et 2000 mots : 145 tirages
entre 2000 et 3000 mots : 96 tirages
entre 3000 et 4000 mots : 48 tirages
entre 4000 et 5000 mots : 42 tirages
entre 5000 et 6000 mots : 22 tirages
entre 6000 et 7000 mots : 8 tirages
entre 7000 et 8000 mots : 5 tirages
entre 8000 et 9000 mots : 4 tirages
entre 9000 et 10000 mots : 2 tirages
entre 10000 et 11000 mots : 1 tirage
entre 11000 et 12000 mots : 3 tirages

Le tirage qui a donné la liste la plus importante, a donné une liste de 11 736 mots, la moins importante étant de 35 mots.

Oui, je sais ça a été fastidieux. Mais je crois qu'il faut bien analyser ce souci dès le début.
On voit donc que, dans la grande majorité des cas, la liste des mots "possibles" est inférieure à 5000 mots (553 tirages sur 600).

On peut encore épurer cette liste.
Je n'ai, pour l'instant, fait qu'enlever les mots dont une des lettres ne fait pas partie de la liste des lettres contenues dans la grille.
On pourrait, par exemple, épurer encore en prenant en compte, non plus des lettres uniques, mais des "couples" de lettres possibles dans cette grille.
Il y a, en effet, dans la grille, 84 couples de lettres possibles.

Les cellules de couleur rouge ont 3 possibilités de couple, couleur jaune 5 possibilités et les violettes 8 possibilités. (4x3)+(8x5)+(4x8)=84.

En comparant la liste déjà épurée avec ces 84 couples de lettres, on peut donc encore la réduire.

Vous en pensez quoi?
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
J'ai testé l'épurement de la liste par rapport aux couples de 2 lettres possibles dans la grille.
Le résultat est insignifiant...
Mais on avance.
Je penses que les 2 méthodes (soit : chercher dans la liste si y existe la chaîne évoluant avec le chemin, soit : chercher, dans la grille, des mots à partir de la liste) sont à réaliser.

En effet, selon les tirages, j'ai obtenu des listes de mots variant de 33 mots à 15 747 mots...

Par conséquent, on se rends bien compte que sur un tirage qui ne laisse la place qu'à 33 mots, la méthode consistant à chercher, dans la grille, les mots de cette liste est la bonne.
Par contre, l'autre méthode (chercher dans la liste si y existe la chaîne évoluant avec le chemin) serait, peut être, plus profitable en cas de liste de 15000 mots...

A voir la "charnière", mais il nous faut (enfin il me faut, avec votre aide...) coder les deux.
Non?

Sur ce, je vais devoir m'absenter,..., pour le week end. Obligations familiales...
Je reviens sur ce sujet dès lundi.

Merci et bon week end à tous.
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
Je me suis pris au jeu, j'avance bien, mais voilà que j'ai des états d'âme fondamentaux qui m'empêchent de continuer sans une réponse très précise relative aux règles mêmes de ce jeu !
Exemple avec cette grille, dans laquelle je recherche le mot "PAIX" :
A P V X
Y A P I
I K I X
O X W Z
On y voit très clairement que ce mot y est trouvé plusieurs fois.
Et dans un tel cas : combien de mots trouvés comptabilises-tu (pour le score) ? Un seul ou tous ?
Il va de soi que ma continuation dépend GRANDEMENT de la réponse précise à cette question (car la suite du traitement diffère terriblement dans un cas et dans l'autre !)



________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviend
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Bonjour,

Aucune indication n'est donnée dans la règle du jeu.
Cependant, on peut déduire de ceci :
Lors du calcul des points, chaque joueur lit à haute voix les mots trouvés. Si deux joueurs ou plus ont trouvé le même mot, il est rayé des listes le contenant.
que les mots doivent être unique.
Pour moi, PAIX ne peut compter qu'une seule fois.

EDIT : trouvé ICI : Un même mot peut être formé dans différents endroits de la grille, il ne comptera qu'une fois. Comme ça c'est clair.
ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213 -
Voilà qui va me faciliter grandement le travail. Bonne nouvelle.
Je m'y replongerai ce soir.
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
Des nouvelles, quand-même ...
1) Tous mes essais faits de manière "conventionnelle", tant en récursivité qu'en procédures successives (en remontant les "noeuds") se traduisent par un temps d'exécution extrêmement long, compte tenu des possibilités de chemin en zigzag et des "combinaisons possibles" de chemins (sans parler du contrôle de la non réutilisation d'une cellule déjà utilisée dans le chemin) ===>>> A abandonner donc, sans la moindre hésitation.
2) je me suis donc dirigé (mon premier "élan" instinctif, que j'aurais dû suivre d'entrée de jeu) vers l'utilisation des objets Excel. Je n'ai pas terminé (loin s'en faut), mais je suis déjà parvenu à réduire considérablement (à moins du quart) le nombre des itérations qu'il faudra exercer. C'est déjà pour le moins appréciable et cela va nous donner une base bien plus réduite sur laquelle travailler.
Je reprends cette tâche demain (là, j'ai le tournis).

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviend
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Bonjour,

J'ai également eu une autre idée...
Mais bon, là c'est dimanche, et, famille oblige, je ne pourrais pas la creuser. Je tente ça demain et vous tiens informés.

Je reprends cette tâche demain (là, j'ai le tournis). C'est dimanche pour toi aussi, alors : repos... Le problème sera encore là demain!
Merci de ton implication, ça fais plaisir.

Amicalement,
Franck
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
Une remarque à propos de cette partie :
"Je n'ai, pour l'instant, fait qu'enlever les mots dont une des lettres ne fait pas partie de la liste des lettres contenues dans la grille. "
Elle n'est pas vraiment adroite.
Pourquoi ,? ===>>
parce-qu'elle nécessite à elle-seule une boucle préalable sur la liste totale des mots (en vue de retirer ceux "impossibles" en fonction de la grille). Or, elle aboutit certes à ,une liste X réduite, mais, pour la suite de ton traitement, tu vas devoir re-parcourir les mots de cette liste X (que tu avais déjà parcourus) ===>> soit nb leur nombre : tu auras ainsi parcouru 2 fois ces nb mots.
Pour être clair : soit une liste de départ de 20000 mots épurée à 600. De la manière dont tu procèdes, le nombre total de mots parcourus est dont : 20600.
Il vaut peut-être mieux traiter directement lors du premier parcours, et de d'autant que pour la même grille, un mot peut être trouvé "impossible" d'entrée de jeu. Dans ce cas-ci, par exemple :
la grille contient bien toutes les lettres du mot, mais, pour chaque lettre du mot, ne contient pas un nombre au moins égal au nombre de cette lettre dans le mot. Or, mes petits tests font ressortir que telle est la situation de très loin la plus fréquente.
Or, cette méthode qui consiste à "ignorer" un mot d'entrée de jeu ne saurait (par définition) s'appliquer globalement, puis cette décision d'ignorer est différente selon chaque mot.
Je vais continuer sur cette base, donc.
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Bonjour,

la grille contient bien toutes les lettres du mot, mais, pour chaque lettre du mot, ne contient pas un nombre au moins égal au nombre de cette lettre dans le mot.
L'idée est très intéressante. Je n'y ai jamais songé.
Il est vrai que l'épuration doit être maximale et réalisée en une seule fois.

Cependant, je voulais également, dans cette appli, "répartir" les longs temps de traitement VBA.
Je pensais à réaliser quelque chose comme cela :
1- à l'ouverture du classeur : chargement du dictionnaire
2- à chaque tirage (clic sur bouton tirage) : épuration du dictionnaire
3- à chaque clic sur le bouton "Solutions" : calcul des combinaisons possibles.
Ceci afin d'éviter les temps de chargement trop long pour l'utilisateur.
Mais s'il y a un quelconque moyen d'alléger l'appli, ne surtout pas hésitr.
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
Une chose m'inquiète par ailleurs, au niveau du remplissage aléatoire de la grille de jeu :
tel que tu le fais, il n'est pas exactement aléatoire, dans la mesure où la case A1 puise toujours parmi ETUKNO, la case A2 toujours parmi IELRUW, etc ...
Est-ce VOULU (une REGLE du jeu) ou une erreur ?
Si vraiment voulu, n'en parlons plus
Si erreur : je la corrige dès ta réponse

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviend
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Salut ucfoutu.

Pour cette question, il y a 16 dés dont les faces sont ETUKNO, IELRUW etc... Normalement, dans le jeu réel, les dés "tombent" sur une "case" de la grille aléatoirement. Il faut également le faire, C'est un aspect que j'avais zappé... Je m'en occupe de suite...
Il existe également des variantes du jeu informatiques qui utilisent un Random pour chaque dé sur l'alphabet en totalité. Cependant, je trouve que l'esprit du jeu n'est plus respecté.
A noter également qu'il existe une variante avec une grille de 5x5...
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
La correction du code de tirage aléatoire ICI
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
Bonsoir, Whismeril;
je ne comprends pas bien ton truc, là :
"Je commence par le dé en haut à gauche, je cherche les dés adjacents, j'en choisi un.
S'il existe des mots qui commence par ces deux lettres, je réduit le dico à ces mots (très gros gain de temps dans les recherches!)
je recherche les adjacents en excluants les deux premiers dés et ainsi de suite de manière récursive.
"
C'est ce que j'ai souligné, qui m'interpelle ...
Rassure-moi : tu recommences ensuite la totalité de cette opération en partant de chacune des autres cases ?
Commenter la réponse de ucfoutu
Messages postés
13942
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
10 novembre 2019
316
0
Merci
Bonsoir,

si la première ligne A B C D,

Je prends, A, je filtre le dictionnaire par les mots commençant par A (6620 entrées contre 72192 au départ).
Parmi les adjacents je choisis B, il y a 359 mots commençant par AB, on continue sur ce chemin.
Je choisis ensuite C, il reste 3 mots commençant par ABC, on continue.
Enfin je choisi D, il n'y a aucun mots commençant par cette suite, je remonte d'un noeud et change de direction on recommence.

J'ai comparé avec la force brute sur trois caractères, c'est plus rapide dans la mesure ou il n'y a pas autant de mots qu'il y a de chemins possibles.
Dans les essais que j'ai fait ça ne c'est pas présenté. Il y a 408 chemins de 3 lettres et je n'ai jamais trouvé plus d'une trentaine de mots de 3 lettres, en comprenant les doublons.

Penser aux balises de coloration syntaxique: bouton <>, préciser le langage :<code csharp>.
Quand la solution est trouvée, mettre la discussion Résolue.
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Re-

Résultats sur la 1ère grille :
Toi : 188 mots trouvés et triés en 5,1 s
Moi : 126 mots en 3 min 40 secondes

Résultats sur la 2nde grille :
Toi : 245 mots trouvés et triés en 4,1 s
Moi : 188 mots en 3 min 16 secondes

Autre précision, ma liste de mots trouvés comporte des doublons.

Bon, je le savais, cf mon message d'hier. En fait, c'est encore beaucoup trop tôt pour moi tester en réel...

J'ai du boulot, et, je vais, de ce pas, tenter quelques corrections. Si elles s'avèrent inefficaces, j'irais questionner ucfoutu... parce que je suis un peu bloqué là...
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Salut,

Je confirme ce que disait ucfoutu, c'est à dire :
La méthode consistant à réduire d'abord le dictionnaire aux mots commençant par le chemin en cours
est à abandonner sous VBA.
Je viens de tester, et les résultats sont, pour :
- 408 "préfixes" de 3 lettres,
- Passés tous dans une procédure réduisant le DicoComplet en DicoRéduit

Juste ce traitement, sans aucun traitement annexe, prends 3 minutes (178 secondes) sur ma machine.

J'ai utilisé ces codes :
[à noter :
* TroisLettres() est une variable tableau préalablement remplie des 408 combinaisons de 3 lettres contenues dans la grille. Elle est remplie au moment du "tirage",
* DicoComplet est un objet dictionary, également préalablement remplie des 323 783 mots du dictionnaire]


Public TroisLettres() As String, DicoComplet As Object, DicoReduit As Object

Sub test()
Dim i As Integer

For i = 0 To 407
    Call TriDicoEnFonctionTroisLettres(TroisLettres(i))
Next i
End Sub

Sub TriDicoEnFonctionTroisLettres(Prefix As String)
Dim Tb(), i As Long

Set DicoReduit = CreateObject("Scripting.Dictionary")
Tb = DicoComplet.keys
For i = LBound(Tb) To UBound(Tb)
    If Left(Tb(i), 3) = Prefix Then DicoReduit(Tb(i)) = ""
Next i
End Sub
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
En suivant les conseils d'ucfoutu, je suis parvenu à réduire les temps d'exécution.
Par contre, ma procédure ne trouve pas autant de mots que la tienne...
Voici les résultats du soir :

Toi : 245 mots trouvés et triés en 4,1 s
Moi : 188 mots trouvés en : 8,265625 secondes.

Toi : 188 mots trouvés et triés en 5,1 s
Moi : 126 mots trouvés en : 9,019531 secondes.

On avance, on avance... C'est une évidence!

Me reste à voir pourquoi cette $§*#¤$*&!§ de procédure ne me trouve pas tous les mots...
Demain!

Bonne soirée Messieurs.

ps : @ ucfoutu : La pêche fut bonne?
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Re-

@Whismeril :
Mes tests de ce matin trouvant davantage de mots, je reviens vers toi...
Ton code, dans la grille E E I D - E R E O - N E G B - T S A E, ne trouve pas les mots suivants :
ENTER
IODEE
RENES
RETS
TES

Bon, pour te rassurer, le mien ne trouve pas ceux-ci :
AGREEES
DEGREEES
GEREES
GERES
GREEES
NEREIDE
REEES
REGENT
REGENTS

Mais, voilà, je tenais à te communiquer ce résultat.
Commenter la réponse de Whismeril
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
Tiens, puisque l'on parle des règles du jeu ...
Une autre précision manque (et elle n'est pas négligeable du tout, car elle conditionne également le développement, de manière cruciale) :
Prenons par exemple le mot trouvé "MAINTENANT" sur un chemin x
Combien de mots sont à comptabiliser pour ce chemin ?
- un seul, le plus long (MAINTENANT) ?
- ou huit (MAI,MAIN, MAINTE, TENANT, NET,NIA,ANE,ANET,) ?
Et c'est même plus complexe lorsque la dernière lettre du mot le plus long est à une case de la première).
Alors ? Comment fait-on, ... ?

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviend
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Salut ucfoutu,

8 sont à comptabiliser : les 7 + maintenant.
Et selon, tu peut également trouver TENIA...
En fait, le chemin n'est valide que pour le mot "en cours". Il est réinitialisé à la fin de chaque mot trouvé.
Par conséquent, dans la grille ci dessous, tu trouves MAIN, réinitialise le chemin, et tu peux trouver MAINS. Ces deux mots sont comptabilisés...
M A I N
T U N S
Y P Z C
V B N J

Également une question subsidiaire réside dans les noms propres... Acceptés ou non?
Cela dépends de ce que nous choisirons, cette règle n'étant pas précisée.
Dans ton cas, on ajoutera AIN, ou pas...
Whismeril
Messages postés
13942
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
10 novembre 2019
316 -
tu trouves MAIN, réinitialise le chemin, et tu peux trouver MAINS. Ces deux mots sont comptabilisés


J'ai appliqué ce principe en créant un clone de chemin à chaque récursion (ça se dit récursion?). Ainsi si MAIN existe dans le dictionnaire, il est stcoké comme un premier chemin, que je clone et auquel j'ajoute le S, ect....
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213
0
Merci
A Pilaku :
Je viens, en tentant une autre approche, de m'apercevoir que ton dico contient des mots avec apostrophe. Il faut supprimer ce signe.

PS ; je m'en suis aperçu en comptabilisant (une fois pour toutes et en utilisant asc(65) ) le nombre de chaque lettre de chaque mot.
En précisant que j'importe le dico dans excel, ainsi que cette comptabilisation. Cette moulinette prend plusieurs minutes, mais n'est faite qu'une seule fois, puisque le classeur est ensuite enregistré et garde donc une fois pour toutes ces données. Ces données sont donc déjà présentes dès que l'on ouvre le classeur distribué.

l'apostrophe n'étant sur aucun des dés ===>> une décision est à prendre à propos de ces mots. ===>>
soit on ne les accepte pas du tout
soit on les accepte sans l'apostrophe (et on supprime alors l'apostrophe dans le dico).


________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviend
ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213 -
Et si on travaillait sur une table (le dico texte) sans autre sgdb que celui du système (son jet) lui-même ?
De sorte à pouvoir faire des requêtes (y compris avec like) sur une table ?
Est-ce possible ? ===>> oui
J'y suis presque totalement. Je parviens même à charger en un temps encore plus petit le dico "complété" dans le classeur et en un temps record le dico "simple" (à une seule colonne).
Mais je me demande s'il ne convient pas alors d'oublier cette importation, pour le coup ... et de travailler directement sur les recordsets que l'on peut obtenir
Là, j'ai le tournis... Je reprendrai plus tard, mais je crois que l'on tient un "bon bout"
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
Oui. En effet.
Cependant, pour être honnête, je ne vois pas ou tu veux en venir, en chargeant les 16 colonnes supplémentaires. J'ai bien vu la nécessité de charger 27 colonnes, c'est drôlement plus rapide après. Mais je ne vois pas du tout pourquoi les16 supplémentaires... Comme le chargement de 27 colonnes ne gène pas l'appli...

Bon, je suppose que c'est pour ta recherche des différents mots.
Il s'avère que ma méthode de recherche fonctionne avec les seules 27 colonnes. Bon ok, elle fonctionne mal (car ne trouve pas tous les mots), mais avec peut être encore quelques affinages, je devrais peut être résoudre ces soucis.

Mais.
Je pense qu'il serait bien que chacun de nous continue dans la voie dans laquelle il s'est engagé (en tenant les autres informés des progrès bien sur), pour peut être, au final, pouvoir bénéficier de plusieurs solutions, et, par conséquent, procéder à des choix.
Donc, ne m'en dit pas plus, et ... affaire à suivre...
ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213 -
Les 16 supplémentaires permettaient d'éviter de recalculer pour déterminer la lettre avant et celle après une lettre prise dans un mot déterminé.
Mais ce que je viens de découvrir va probablement bouleverser toute ma méthode d'approche
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7 -
ce que je viens de découvrir
Ravi pour toi que tu puisses encore découvrir des choses. Je ne pensais pas ça possible sur un problème posé par moi. Honnêtement.

bouleverser toute ma méthode d'approche
Aïe! ça te fais recommencer tout?...
ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
213 -
Oui, mais je prends cela comme un divertissement entre deux parties de pêche ...
Commenter la réponse de ucfoutu
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
7
0
Merci
Re-

J'ai une solution relativement stable...

Dites moi ce qu'il convient de faire?

Mon avis : attendre tranquillement qu'ucfoutu rentre de la pêche, le féliciter pour ses prises du jour, attendre qu'il ait sa solution et tester chacun son appli.
Si vous préférez que je donne directement ma solution, pas de souci. Je préfères attendre, pour ne pas gêner la réflexion d'ucfoutu (c'est toujours un peu troublant de lire un code en en cherchant un autre...).

Vous dites...
Whismeril
Messages postés
13942
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
10 novembre 2019
316 -
Salut, ça me va, tout comme Uc je fais ça pour m'amuser entre deux journées de boulot (j'irai à la pêche quand je serais retraité moi aussi)!

Je travaille un peu la présentation, car si je poste le projet complet, il ne faut pas que ce soit trop moche quand même.

Et j'essaye de trouver une belle requête ou combinaison de requêtes, pour passer mes listes de mots (une de 3 lettres, une de 4 etc....) en une belle grille, comme je l'exporte dans le csv.
Pour l'instant je fais une boucle for.
Whismeril
Messages postés
13942
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
10 novembre 2019
316 -
Ha, au fait dans ce message, je voulais écrire que je charge le fichier avec un split, mais le p**** de correcteur d'orthographe m'a mit "salit".

J'ai aussi une petite correction à faire dans mes algos, j'ai inversé le X et le Y quand je saisie les coordonnées des dés.
Dans l'absolue ça ne change rien, mais le futur lecteur pourrait s'en émouvoir.
Commenter la réponse de pijaku
Messages postés
29630
Date d'inscription
samedi 12 mai 2007
Statut
Webmaster
Dernière intervention
10 novembre 2019
2
0
Merci
Salut à tous,

Je lis votre post depuis le début et CHAPEAU ; je trouve cela assez génial, l'enthousiasme que vous avez tous dégagé pour arriver au résultat.
Un beau travail d'équipe ;-)
Commenter la réponse de noctambule28