rekursion stack globale variable - probleme



  • hallo an alle.
    ich hab mir mal als einstiegsaufgabe einen sudoku löser aufgegeben.

    #include <stdio.h>
    #include <stdlib.h>
    
    long int count;
    
    short zeile, spalte, x;
    short z,s,kand;
    
    /*
    int blatt[9][9] = {{0 ,0 ,0 ,0 ,16,0 ,0 ,0 ,0},
                       {0 ,0 ,14,15,0 ,0 ,12,0 ,0},
                       {0 ,0 ,0 ,0 ,17,12,13,0 ,0},
                       {0 ,17,0 ,0 ,0 ,13,0 ,12,0},
                       {0 ,13,0 ,12,0 ,16,19,0 ,0},
                       {0 ,0 ,19,0 ,0 ,0 ,0 ,0 ,13},
                       {0 ,0 ,0 ,0 ,11,0 ,17,0 ,0},
                       {18,14,0 ,0 ,13,17,0 ,0 ,0},
                       {0 ,0 ,0 ,0 ,0 ,18,0 ,15,0}};
    */
    short blatt[9][9]={{0 ,13,0 ,0 ,0 ,0 ,0 ,0 ,0},
                       {0 ,0 ,0 ,11,19,15,0 ,0 ,0},
                       {0 ,19,18,0 ,0 ,0 ,0 ,16,0},
                       {18,0 ,0 ,0 ,16,0 ,0 ,0 ,0},
                       {14,0 ,0 ,0 ,0 ,13,0 ,0 ,11},
                       {0 ,0 ,0 ,0 ,12,0 ,0 ,0 ,0},
                       {0 ,16,0 ,0 ,0 ,0 ,12,18,0},
                       {0 ,0 ,0 ,14,11,19,0 ,0 ,15},
                       {0 ,0 ,0 ,0 ,0 ,0 ,0 ,17,0}};
    
    ausgabe() {
       int i;
       int j;
       printf("\n");
       for (j=0;j<9;j++){
           if (j==3 | j==6) {
           printf("-----------------------------\n");}
           for (i=0;i<9;i++){
               if (i==3 | i==6) {
                  printf("| ");}
                  if (blatt[j][i]>10){
                     printf("%d ",blatt[j][i]);
                  }
                  else if(blatt[j][i]<10){ 
                       printf("%d  ",blatt[j][i]);
                  }
           }
       printf("\n");
       }
    }
    
    /*returns 1 for correct ; 0 for not correct  */
    is_correct(short x ,short zeile, short spalte){ //x-kandidat
       short j,i,k,l,treffer;
       if (x==10) treffer=1;
       for (j=0;j<9;j++){            //sucht in der zeile
           if (x==(blatt[zeile][j])%10) treffer=1;
       }
    
       for (i=0;i<9;i++){           //sucht in der spalte
           if (x==(blatt[i][spalte])%10) treffer=1;    
       }
    
       //sucht im kleinen quadrat
       for (l=zeile/3*3;l<(((zeile/3)*3)+3);l++){       
           for (k=spalte/3*3;k<spalte/3*3+3;k++){
               if (x==(blatt[l][k])%10) treffer=1;
             //printf("zeile:%d ",l);
             //printf("spalte:%d ",k);
           }
       //printf("\n");
       }
       if (treffer != 1) return 1;
       else return 0;
    }
    
    fill(short x,short zeile,short spalte){
       short abbruch;
       //if (count==65094)printf("debug");
       //z = zeile; 
       //s = spalte;
       //kand = x;
       count = count + 1;
       //printf("count: \%d");
       if ((zeile==0)&&(spalte==9)) abbruch=1;
       if (count<20){//die grosse abbruchbed.???
          if (blatt[zeile][spalte]<10) {             //vorgabe zahl
             if (zeile==9) fill(x,0,spalte + 1);     //zeile9? ->neue spalte
             else{                                   // 
                 if (is_correct(x,zeile,spalte)){     //wenn der kandidat passt -eintragen
                    blatt[zeile][spalte]=x;
                 }
                 else {                               //kandi passt net
                    if (x<10){                        //wenn kand <=9 probieren
                       fill(x+1,zeile,spalte);        //
                    }
                    else{                            //wenn kand =10 
                       blatt[zeile][spalte]=0;           //zelle zurücksetzen
                       if (zeile==0) {                  //spalte nach links springen
                          zeile=8;
                          spalte=spalte-1;
                          fill((blatt[zeile][spalte])+1,zeile,spalte);
                       }
                       else {
                          zeile=zeile-1;                //zeile nach links springen
                          fill((blatt[zeile][spalte])+1,zeile,spalte); 
                       }
                    }
                 }
             fill(1,zeile+1,spalte);
             }     
          }
    
          else if (blatt[zeile][spalte]>10) {     // wenn vorgabezahl alles lassen
             if (x>11) fill((blatt[zeile-1][spalte])+ 1,zeile -1,spalte);
             else{
                 if (zeile==8) fill(x,0,spalte + 1);    // neue spalte
                 else fill(x,zeile +1 ,spalte);
             }
          }
       }
    }
    
    main(void) {
       ausgabe();
       fill(1,0,0);
       ausgabe();
       //fill(1,5,1);
       printf("count:%d\n",count);
       //printf("zeile:%d\n",z);
       //printf("spalte:%d\n",s);
       //printf("kandidat:%d\n",kand);
       //ausgabe();
       //printf("%d ",blatt[4][0]);
       //printf("rueckgabe:%d ",is_correct(1,0,0));
       system("pause");
       return EXIT_SUCCESS;
    }
    

    ich glaube, dass das inhaltlich stimmen könnte, abgesehen davon dass mein hauptspeicher nicht für die lösung reicht.
    was mich wundert: ich lasse in fill() den counter hochzählen und bei 20 abbrechen. lasse ich nach ausführung count ausgeben steht er auf 33?
    weiter: versuchte ich die globale variable z zu belegen. leider funktioniert das nur beim ersten rekursiven aufruf der funktion fill.
    ich bitte um meinungen.



  • Hi,

    ich habe mir mal deinen Code angesehen und reporte dir hier ein paar
    Fehler, die mir aufgefallen sind:

    - In C sieht die Funktionsdeklaration wie folgt aus:
         Rückgabewert Funktionsname (Parameterliste)
      Zum Beispiel sieht deine Funktion ausgabe dann so aus:
         void ausgabe(void)    oder         void ausgabe()
    - In der Funktion ausgabe() fragst du in einer If-Anweisung folgendes:
         if (j==3 | i==6)
      Dieses | (oder) ist eine Bitoperation. Du meintest aber: ||
      richtig wäre also:  if (j==3 || i==6)
    

    Du verwendest die folgenden globale Variablen, die du nicht wirklich
    brauchst:

    short zeile, spalte, x;
    short z,s,kand;
    

    Nun noch zu deiner Frage: warum count am Ende 33 ist.
    Du brichst zwar nach count == 20 ab, hast aber immer noch ein paar Aufrufe
    innerhalb der Rekursion. Da du count vor dem Abbruch erhöhst, wächst count
    weiter an.

    Ob dein Programm ansonsten korrekt arbeitet, habe ich nicht überprüft.

    Gruß mcr

    PS: Die Kommentierung mit // ist nicht Ansi-C like.



  • mcr schrieb:

    PS: Die Kommentierung mit // ist nicht Ansi-C like.

    isse wohl!
    🙂


Anmelden zum Antworten