C++ fonction récursive plante si appelée 32436 fois
neo781
Messages postés
2
Date d'inscription
Statut
Membre
Dernière intervention
-
Utilisateur anonyme -
Utilisateur anonyme -
Bonjour,
J'ai fait un sudoku solveur avec fonction récursive en backtraking. Elle plante pour les grilles difficiles où elle doit s'appeler plus de 32436 fois. Quelqu'un peut-il me dire pourquoi ? merci.
J'ai fait un sudoku solveur avec fonction récursive en backtraking. Elle plante pour les grilles difficiles où elle doit s'appeler plus de 32436 fois. Quelqu'un peut-il me dire pourquoi ? merci.
#include <iostream> #include <cstdio> using namespace std; const int avance = 1; const int recule = 7; int compteur = 0; void affiche (int t[9][9]); bool teste (int t[9][9], int nb, int x, int y); int remplit (int tab[9][9], int t1 [81]); bool calcule (int tab [9][9], int t1[81], int c, int nbcat, int val, int av_rec); bool fin (int tab [9][9], int t1[81], int nbcat); int main() { // facile int tab[9][9]= {{0,1,0,0,2,4,0,0,9},{0,3,0,0,0,8,0,0,0},{2,9,4,6,7,3,0,0,8},{0,0,2,0,1,0,9,6,5},{0,0,8,0,4,0,2,0,0}, {9,7,1,0,6,0,3,0,0},{4,0,0,9,5,2,6,7,1},{0,0,0,7,0,0,0,4,0},{6,0,0,4,8,0,0,9,0}}; //int tab[9][9]= {{0,0,0,0,0,0,0,1,2},{0,0,0,0,0,0,0,0,3},{0,0,2,3,0,0,4,0,0},{0,0,1,8,0,0,0,0,5},{0,6,0,0,7,0,8,0,0}, // {0,0,0,0,0,9,0,0,0},{0,0,8,5,0,0,0,0,0},{9,0,0,0,4,0,5,0,0},{4,7,0,0,0,6,0,0,0}}; //int tab[9][9]= {{0,3,2,0,0,1,0,0,6},{0,0,8,0,2,5,0,3,4},{7,0,0,4,0,0,8,1,0},{0,0,0,2,0,0,1,6,0},{0,0,1,3,0,7,4,0,0}, // {0,7,9,0,0,6,0,0,0},{0,4,3,0,0,2,0,0,8},{8,1,0,6,3,0,5,0,0},{2,0,0,7,0,0,3,4,0}}; // le plus difficile du monde ?? //int tab[9][9] = {{1,0,0,0,0,7,0,9,0},{0,3,0,0,2,0,0,0,8},{0,0,9,6,0,0,5,0,0},{0,0,5,3,0,0,9,0,0},{0,1,0,0,8,0,0,0,2}, // {6,0,0,0,0,4,0,0,0},{3,0,0,0,0,0,0,1,0},{0,4,0,0,0,0,0,0,7},{0,0,7,0,0,0,3,0,0}}; // difficile // int tab[9][9] = {{0,1,0,0,0,4,0,9,7},{0,0,7,0,0,0,0,4,8},{0,8,9,0,5,0,2,0,3},{5,0,0,6,0,2,0,0,0},{0,0,0,0,0,0,0,0,0}, // {0,0,0,5,0,3,0,0,8},{1,0,2,0,8,0,6,5,0},{0,6,0,0,0,0,1,0,0},{3,0,0,4,0,0,0,7,0}}; int t81 [81]; int r; r=remplit (tab,t81); affiche (tab); calcule (tab, t81, 0, r, 1, avance); affiche (tab); return 0; } /*** Teste la valeur nb en x,y dans t renvoie true si valeur possible, false autrement ***/ bool teste (int t[9][9], int nb, int x, int y) { int i,j; if (nb > 9) return false; for (i=0;i<9;i++) { if (t[i][y] == nb) return false; if (t[x][i] == nb) return false; } int _x = x - (x % 3), _y = y - (y % 3); for (i = _x ; i < _x + 3 ; i++) for (j = _y ; j < _y + 3 ; j++) { if (t[i][j] == nb) return false; } return true; } /*** Remplit le tableau t81 avec toutes les références des cases à compléter forme : i = c / 9; j = c % 9; avec respectivement i ordonnée et j abscisse de la case sous la forme tab [i][j] ***/ int remplit (int tab[9][9], int t1 [81]) { int c,i,j,k; for (c=0;c<81;c++) t1[c] = 0; k = 0; for (c=0;c<81;c++) { i = c / 9; j = c % 9; if ((tab [i][j]) == 0) { t1[k] = c ; k++; } } return k; // k : nombre de cases à trouver } /*** Affiche la grille tab [9][9] ***/ void affiche (int t[9][9]) { int i,j,l; cout << endl; cout << " **********************************************" <<endl; for (i=0;i<9;i++){ for (j=0;j<9;j++){ if (j == 0) cout << " * "; if (t[i][j] != 0) {cout <<t[i][j] <<" ";} else {cout <<" ";} if ((j+1)%3 == 0) cout << "* "; } cout << endl; if ((i+1)%3 == 0) cout << " **********************************************" <<endl; } } /*** Fonction principale récursive (vers l'avant et vers l'arrière) ***/ bool calcule (int tab [9][9], int t81[81], int c, int nbcat, int val, int av_rec ) { int i,j,k; k = t81 [c]; i = k / 9; j = k % 9; compteur ++; cout << "compteur : " << compteur << " c : " << c << " val : "<< val << " " << endl; /***Avance et remplit tab [9][9]***/ if ((av_rec) == avance) { if (val > 9) {tab [i][j] = 0; calcule (tab, t81, c - 1, nbcat, val, recule);} // S'il n'est pas possible d'avancer, c'est qu'il faut reculer. else { if (teste (tab, val, i, j) == false) calcule (tab, t81, c, nbcat, val + 1, avance); else { tab [i][j] = val; if (fin (tab, t81, nbcat) == true) return true; calcule (tab, t81, c + 1, nbcat, 1, avance); } } } if ((av_rec) == recule) { val = tab [i][j]; if (val == 9) {tab [i][j] = 0; calcule (tab, t81, c - 1, nbcat, val, recule);} else calcule (tab, t81, c, nbcat, val + 1, avance); } } /*** Renvoie true si la dernière case est remplie ***/ bool fin (int tab [9][9], int t81[81], int nbcat) { int i,j,c; c = t81[nbcat-1]; i = c / 9; j = c % 9; if (tab [i][j] == 0) return false; return true; }
A voir également:
- C++ fonction récursive plante si appelée 32436 fois
- Fonction si et - Guide
- Fonction miroir - Guide
- Mon telephone plante que faire - Guide
- Plante - Guide
- Fonction moyenne excel - Guide
2 réponses
Salut,
Les fonctions récursives ne peuvent aller au délà d'une certaine profondeur pour une histoire de taille de pile (heap size).
Chaque instruction que tu appelles est stockée dans une pile et ensuite les instructions sont traitées. Cependant, les fonctions récursives font appel à elles-même jusqu'à une certaine profondeur. Malheureusement, la pile ne peut stocker indéfiniment les instructions à résoudre. C'est un peu comme un vase que tu remplis trop sans le vider à chaque fois.
Plus d'information : https://franckh.developpez.com/tutoriels/c-ansi/recursivite/
Les fonctions récursives ne peuvent aller au délà d'une certaine profondeur pour une histoire de taille de pile (heap size).
Chaque instruction que tu appelles est stockée dans une pile et ensuite les instructions sont traitées. Cependant, les fonctions récursives font appel à elles-même jusqu'à une certaine profondeur. Malheureusement, la pile ne peut stocker indéfiniment les instructions à résoudre. C'est un peu comme un vase que tu remplis trop sans le vider à chaque fois.
Plus d'information : https://franckh.developpez.com/tutoriels/c-ansi/recursivite/
Merci Jason.
Du coup j'ai réécrit mon programme en remplaçant la fonction récursive
par une boucle while. Et là ça a marché tout de suite.
Je donne la version de mon sudoku solver avec la boucle while si ça peut intéresser quelqu'un.
Du coup j'ai réécrit mon programme en remplaçant la fonction récursive
par une boucle while. Et là ça a marché tout de suite.
Je donne la version de mon sudoku solver avec la boucle while si ça peut intéresser quelqu'un.
#include <iostream>
#include <cstdio>
using namespace std;
const int avance = 1;
const int recule = 0;
int compteur = 0;
void affiche (int t[9][9]);
bool teste (int t[9][9], int nb, int x, int y);
int remplit (int tab[9][9], int t1 [81]);
bool calcule (int tab [9][9], int t1[81], int c, int nbcat, int val, int av_rec);
bool fin (int tab [9][9], int t1[81], int nbcat);
int main()
{
// facile
//int tab[9][9]= {{0,1,0,0,2,4,0,0,9},{0,3,0,0,0,8,0,0,0},{2,9,4,6,7,3,0,0,8},{0,0,2,0,1,0,9,6,5},{0,0,8,0,4,0,2,0,0},
// {9,7,1,0,6,0,3,0,0},{4,0,0,9,5,2,6,7,1},{0,0,0,7,0,0,0,4,0},{6,0,0,4,8,0,0,9,0}};
//int tab[9][9]= {{0,0,0,0,0,0,0,1,2},{0,0,0,0,0,0,0,0,3},{0,0,2,3,0,0,4,0,0},{0,0,1,8,0,0,0,0,5},{0,6,0,0,7,0,8,0,0},
// {0,0,0,0,0,9,0,0,0},{0,0,8,5,0,0,0,0,0},{9,0,0,0,4,0,5,0,0},{4,7,0,0,0,6,0,0,0}};
//int tab[9][9]= {{0,3,2,0,0,1,0,0,6},{0,0,8,0,2,5,0,3,4},{7,0,0,4,0,0,8,1,0},{0,0,0,2,0,0,1,6,0},{0,0,1,3,0,7,4,0,0},
// {0,7,9,0,0,6,0,0,0},{0,4,3,0,0,2,0,0,8},{8,1,0,6,3,0,5,0,0},{2,0,0,7,0,0,3,4,0}};
// le plus difficile du monde ??
int tab[9][9] = {{1,0,0,0,0,7,0,9,0},{0,3,0,0,2,0,0,0,8},{0,0,9,6,0,0,5,0,0},{0,0,5,3,0,0,9,0,0},{0,1,0,0,8,0,0,0,2},
{6,0,0,0,0,4,0,0,0},{3,0,0,0,0,0,0,1,0},{0,4,0,0,0,0,0,0,7},{0,0,7,0,0,0,3,0,0}};
// difficile
// int tab[9][9] = {{0,1,0,0,0,4,0,9,7},{0,0,7,0,0,0,0,4,8},{0,8,9,0,5,0,2,0,3},{5,0,0,6,0,2,0,0,0},{0,0,0,0,0,0,0,0,0},
// {0,0,0,5,0,3,0,0,8},{1,0,2,0,8,0,6,5,0},{0,6,0,0,0,0,1,0,0},{3,0,0,4,0,0,0,7,0}};
int t81 [81]; int r;
r=remplit (tab,t81);
affiche (tab);
calcule (tab, t81, 0, r, 1, avance);
affiche (tab);
return 0;
}
/************************************************************************************************************************
Teste la valeur nb en x,y dans t
renvoie true si valeur possible, false autrement