Partage
  • Partager sur Facebook
  • Partager sur Twitter

Aide algorithme brute force

    16 février 2020 à 17:11:19

    Bonjour à tous,

    Dans le cadre d'un exercice de cours dans lequel nous devons réaliser un solveur pour un jeu que nous avons programmé (je vous passe les détails du jeu). J'ai pensé à réaliser un algorithme qui affiche tous les mots de taille k sur l'alphabet 0,1,2,3. Par exemple pour les mots de taille 3 il existerai 000; 001; 010; 100; 101; 110 ect...

    Le problème est que je ne vois pas trop comment faire cela en c.

    • Partager sur Facebook
    • Partager sur Twitter
      16 février 2020 à 17:36:43

      Avant de chercher en C, comment ferais-tu avec un crayon et du papier ?
      • Partager sur Facebook
      • Partager sur Twitter

      Le crayon la gomme et le papier sont les meilleurs outils du programmeur !

        16 février 2020 à 17:38:52

        Salut,
        Comment fais-tu une addition de deux nombres en décimal?
        Tu additionne les unités, si ça dépasse 10, tu gardes les unités et tu gardes la retenue pour les dizaines ...
        Ce que tu demandes, c'est de faire des additions en binaire, mais de façon simulée.
        tu pourrais avoir un tableau de dimension 'k' fait de nombres 0 et 1.
        Tu fais la somme, si ça donne 2 ou 3, tu gardes le modulo 2 et tu gardes le quotient pour la puissance suivante.
        C'est ce qu'on appelle la retenue ou le "carry". Au départ, le carry est égal à 1.
        Tu auras:
        somme = nombre[i] + carry;
        carry = somme / 2;
        nombre[i] = somme % 2;
        Tu pourrais également additionner des nombres jusqu'à 2^k et extraire les bits avec des modulo et des quotients.
        Pour ce genre de problème, je trouve ça plus compliqué que la première façon.

        -
        Edité par PierrotLeFou 16 février 2020 à 19:15:44

        • Partager sur Facebook
        • Partager sur Twitter

        Le Tout est souvent plus grand que la somme de ses parties.

          16 février 2020 à 17:41:26

          Par exemple je commence par la combinaison 000 après je fais par exemple toutes les combinaisons qui commence par 1 donc 100 101 102 103 110 111 112 ect... Et ensuite je fais toutes les combinaisons qui commence par 2. Comme si j'essayais d'ouvrir un cadenas sans connaître le code
          • Partager sur Facebook
          • Partager sur Twitter
            16 février 2020 à 18:26:25

            J'ai mal compris le problème mais la solution est la même.
            ... j'ai modifié l'addition car on ajoute un au nombre, et non deux nombres ensemble.
            Au lieu d'être en base 2, on est en base 4.
            Tu fais une boucle de 4^k ittérations et tu ajoutes 1 à chaque ittération.
            Tu auras donc ici k=3, donc 4^3 = 64, c'est le nombre de possibilités.
            000, 001, 002, 003, 010, 011, 012, 013, ...
            Pour faire l'addition "simulée" comme j'ai montré, ou bien tu part de k-1 et tu vas vers 0, ou bien tu imprimes de k-1 à 0.
            Donc tu as 2 boucles imbriquées.

            -
            Edité par PierrotLeFou 16 février 2020 à 19:20:45

            • Partager sur Facebook
            • Partager sur Twitter

            Le Tout est souvent plus grand que la somme de ses parties.

              16 février 2020 à 19:30:48

              On va la faire "à l'ancienne" 

              combinaison <- "0000"
              tab[4] = {0,0,0,0}
              k <- 4
              tant que k > 0 
              faire
                  memoriser combinaison
                  incrementer tab[k]
                  tant que k > 0 && tab[k] == 4 
                  faire
                      tab[k] <- 0
                      decrementer k
                      si k > 0 alors
                          incrementer tab[k]
                      finsi
                  finfaire
                  pour i de 1 a 4 faire
                      combinaison[i] <- '0' + tab[i]
              finfaire

              Je ne crois pas mettre trompé.

              A toi de traduire en C!

              • Partager sur Facebook
              • Partager sur Twitter

              Le crayon la gomme et le papier sont les meilleurs outils du programmeur !

                17 février 2020 à 2:25:16

                Je l'ai essayé à ma manière. Je me suis fait un petit logiciel pour l'indentation.
                Ceci s'appelle un "registre circulaire", ou un "ring counter" en anglais.
                Je crois avoir compris pourquoi c'est plus facile en électronique d'ajouter la valeur 1 à un registre que d'en additionner deux.
                -
                1 // Simmuler un registre circulaire (ring counter).
                2 #include <stdio.h>
                3 #define RSIZE  3  // Grandeur du registre.
                4 #define NBASE  4  // Base des nombres.
                5 int main() {
                6   int nombre[RSIZE] = {0};
                7   int carry, i, l, nLoop;
                8   // Nombre de fois où on va incrémenter le registre.
                9   for(i = 0, nLoop = 1; i < RSIZE; i++)  nLoop *= NBASE;
                10   
                11   for(l = 0; l < nLoop; l++) {
                12     // Imprimer le registre.
                13     for(i = RSIZE - 1; i >= 0; i--) {
                14       printf("%d", nombre[i]);
                15     }
                16     printf("\n");
                17     // Calculer la nouvelle valeur du registre.
                18     carry = 1;
                19     for(i = 0; i < RSIZE; i++) {
                20       nombre[i] += carry;
                21       carry = nombre[i] / NBASE;
                22       nombre[i] %= NBASE;
                23     }
                24     
                25   }
                26   
                27   return(0);
                28 }
                -
                Je n'ai pas accès au bouton <code>

                -
                Edité par PierrotLeFou 17 février 2020 à 2:28:49

                • Partager sur Facebook
                • Partager sur Twitter

                Le Tout est souvent plus grand que la somme de ses parties.

                  17 février 2020 à 8:40:50

                  Deux façons de faire :

                  • en incrémentant
                  • en décomposant un nombre

                  Pour le premier, on garde le nombre dans un tableau. A un moment on arrive à 0212 par exemple. Le suivant, on l'obtient en à jouant 1 à droite; soit 0213. Celui d'après, pareil, sauf qu'on est arrivé à 3, alors on revient à 0 et on augmente le chiffre qui est à sa gauche.

                  Si on généralise, on voit que l'opération passer au suivant consiste à remplacer tous les 3 qui sont à droite par des 0, et incrémenter le chiffre de gauche, si il y en a.

                  * donnée : un tableau   chiffre[taille]
                  * initialiser à 0
                  
                  * opération : passer au suivant :
                  
                  position = taille - 1
                  tant que position >= 0 et  chiffre[position] = base-1
                  faire 
                    |  chiffre[position] = 0
                    |  position = position - 1
                  si position >= 0
                    |  chiffre[position] += 1
                  sinon
                    | c'est fini
                  


                  Autre approche, il y a  $base^{taille}$ manières de remplir le tableau. Il suffit d'avoir une boucle avec un indice qui va de 0 à $base^{taille}, et de décomposer l'indice sur la base (le chiffre de droite c'est indice%base, celui d'avant   (indice/base)% base, etc.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 février 2020 à 12:57:39

                    Merci à tous pour vos réponses. Je pense avoir maintenant les clés en main pour résoudre mon problème je reviendrai vous voir quand j'aurai réussi !
                    • Partager sur Facebook
                    • Partager sur Twitter
                      17 février 2020 à 18:17:58

                      @michelbillaud:
                      En dépit du format douteux de mon code, ça fait ce que tu suggères dans ta première approche.
                      En changeant RSIZE et NBASE, je peux changer à volonté la longueur du registre (nombre de digits) et la base (4 ici).
                      L'autre possibilité consiste à incrémenter un nombre de NBASE et de faire la conversion comme 'printf' le ferait, mais pour une base quelconque.
                      On se tape encore des modulo et des divisions.
                      Pour reprendre mes constantes, on augmentera NBASE^RSIZE fois.
                      Si NBASE vaut 4 et RSIZE vaut 3, j'aurai 4^3 = 64 incrémentations.
                      Cette dernière façon nous limite à la grandeur d'un 'int' ou d'un 'long long'.
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Le Tout est souvent plus grand que la somme de ses parties.

                      Aide algorithme brute force

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown