Reduction liste candidat : sudoku

Fermé
Julie - 8 mai 2008 à 23:59
 Mahmah - 17 mai 2008 à 21:56
Bonjour,
Au premeir abord mon message parait lnog mais en fait c'est pas long :-p ( en gros je cherche à écrire 3 fonctions en me servant de celle que j'ai écrite )

je devais faire cette fonction :


Écrivez la fonction int reduitCandidatsCase(Grille g, int ligne, int colonne, int val) qui
élimine le candidat de valeur val dans la case de coordonnées (ligne, colonne). Cette fonction
retourne le nombre de candidats éliminés (i.e. 0 ou 1).

j'ai écris cette fonction :

int reduitCandidatsCase ( Grille g, int lig, int col, int n) {
int i; /* position de n dans le tableau des candidats */
int ne; /* nombre de candidats éliminés */
lig = lig - 1;
col = col - 1;
ne = 0;
i = rechercheTabInt(g[lig][col].candidats, g[lig][col].nbCandidats, n);
if ( i != -1) {
g[lig][col].nbCandidats = g[lig][col].nbCandidats - 1;
while (i < g[lig][col].nbCandidats) {
g[lig][col].candidats[i] = g[lig][col].candidats[i+1];
i = i + 1;
}
ne = 1;
}
return ne;
}

elle marche bien mais maintenant j'aimerais écrire 3 autres fonctions qui ressemble à celle là :

Il faut écrire la fonction int reduitCandidatsLigne(Grille g, int ligne, int val) qui parcourt les cases
vides de la ligne d'indice ligne et qui y élimine les candidats de valeur val. Cette fonction
retourne le nombre de candidats éliminés sur toute la ligne.

Il faut écrire la fonction int reduitCandidatsColonne(Grille g, int colonne, int val) qui parcourt les
cases vides de la colonne d'indice colonne et qui y élimine les candidats de valeur val. Cette
fonction retourne le nombre de candidats éliminés sur toute la colonne.

Iil faut écrire la fonction int reduitCandidatsRégion(Grille g, int region, int val) qui parcourt les
cases vides de la région d'indice region et qui y élimine les candidats de valeur val. Cette
fonction retourne le nombre de candidats éliminés sur toute la région.


Si quelqun a une idée je le remercie d'avance :)
bioux a tous
A voir également:

33 réponses

Bonjour,

Je vais répondre en deux parties : L'idée des fonction à mettre en place pour la solution suggérée et le choix que j'aurais fait si j'avais réalisé le projet.

1)
Avec la solution actuelle, on a une réponse immédiate des candidats disponible ou non pour une case. Par contre il faut une mise à jour lourde car il faut une fonction qui mette à jour les neuf cases de la ligne, les neuf de la colonne et les neuf de la région. Ce que je vois à faire ici c'est simplement une fonction qui pour traiter une ligne contient une boucle sur les colonnes. Pour chaque colonne de la ligne on rappelle ta fonction précédente. Idem pour les colonnes et les régions.


2)
Dans la solution choisie, on stoque jusqu'à neuf candidats pour chaque case, soit 9 lignes * 9 colonnes * 9 candidats, soit 729 entiers. De plus la mise à jour n'est pas évidente et demande de parcourir un certain nombre de cases. Je propose d'avoir les mêmes informations avec 27 entiers pour toute la grille. (On va faire du C ^^)
L'idée est assez simple. 1) on ne conserve en mémoire que les candidats disponible pour chaque ligne, chaque colonne et chaque région et non plus pour chaque case. 2) Un candidat est disponible ou ne l'est pas, c'est donc une valeur booléenne (0 ou 1) et ça on peut l'écrire sur un seul bit. Ainsi un entier peut garder l'information de disponibilité pour les 9 candidats.

En somme on a :
Un tableau de neuf entiers pour les neuf lignes.
Un tableau de neuf entiers pour les neuf colonnes.
Un tableau de trois par trois pour les neuf régions.

Pour connaître la disponibilité d'une valeur, on fait de recoupement des trois tableaux. Tu verras, c'est plus facile qu'on ne pense ;-)

Pour les bits j'avais fait une première explication par là bas : "Pour ce qui est de mon choix de stocker les coups possibles/impossibles par des flags..."

Généralement ce qui dérange c'est les define pour les valeurs. Ou plutôt le fait que ce soit écrit en hexadécimal.... question d'habitude. on peut très bien écrire 1, 2, 4, 8, 16, 32 etc ou 1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5 en utilisant le décalage de bit.

Pour parcourir les valeurs ainsi définies : une boucle
unsigned int v;

for ( v = 1 ; v != _VALUE_9_ << 1 ; v <<= 1 )
    v & .... ou v | ....

On ne parcourt pas des valeurs décimales mais des bits. On pourrait(/devrait) rajouter deux defined pour avoir des constantes plus compréhensibles. Une pour la première valeur et une pour la dernière (ici après la dernière, soit le bit bit après celui qui représente le 9) L'incrémentation est également modifiée... on fait habituellement un i++, ici on décale et on réaffecte. soit v = v << 1 ou encore v <<= 1.

On a le droit de pas aimer et/ou de poser des questions ;-)

Bye.
0
merci zizag mais ca fait 3 semaines que je fais du C et j'ai rien compris à ce que t'a dis.

Je veux juste écrire 3 fonctions sous le modèle de la première que j'ai faite ( même si elle utilise beaucoup de bit :p )
0
Dans ce cas il faut les trois fonctions qui font juste une boucle et je suppose une fonction supplémentaire pour chapeauter le tout et rendre l'utilisation plus immédiate.

Du style : éliminer les candidats d'une case pour une valeur c'est : éliminer les candidats de la ligne de cette case, ceux de la colonne, ceux de la région. Ce sera une fonction qui sera utilisée plus tard et qui consiste en gros à jouer une valeur.

Eliminer les candidats d'une ligne c'est : pour chaque case de la ligne concernée, appeler reduitCandidatsCase et renvoyer la somme des réponses obtenues.


J'ai un petit peu de mal à voir ce qui gène, c'est plus la façon de faire ou plutôt comment écrire un code qui le fait ?
0
Comment écrire le code en fait ....

je sais ce que le code signifie mais j'arrive pas à les écrire en C ( je sais qu'il faut utiliser la fonction supprimer-valeur_d1_tableau donc j'admet que je l'ai déja écrite )

si vous avez des idées pour écrire le code en se servant du 1 er que j'ai écris
0
Dans ce cas on peut le faire en pseudo code pour bien poser les étapes puis tu les traduiras en code C.

Fonction de retrait d'un candidats pour une case :
// déjà faite
int reduitCandidatsCase ( Grille g, int lig, int col, int n)
{
    ...
}


Fonction de retrait d'un candidat pour une ligne :
int reduitCandidatLigne( Grille g, int lig, int candidat )
{
   Entier nombreCandidats = 0 : Le nombre de candidats retirés.
   Entier col : variable de boucle.

   Pour chaque : case de la ligne lig
         à partir de col = 0
         avec col < NOMBRE_COLONNES
         avec un pas de 1
   faire :
      nombreCandidats = nombreCandidats + reduitCandidatsCase( g, lig, col, candidat )
   

   retourner nombreCandidats
}


La fonction pour la réduire les candidats d'une colonne devrait ressembler beaucoup, pour ceux d'une région il y a un choix à faire pour les paramètres, je te laisse le faire. Soit on désigne la région comme si on avait un tableau de 3 par 3. Soit on désigne la région par la case (donc avec deux indice entres 0 et 8)

{
   Entier i : indice de la ligne d'une case, de 0 à 2 ou de 0 à 8 selon le choix
   Entier j : colonne
   Entier nombreCandidats : Le nombre de candidats retirés.

   Pour Chaque : ligne
         à partir de i = [selon choix]
         avec i < [selon choix]
         avec un pas de 1
   faire :
   {
      Pour Chaque : colonne de la ligne i
         à partir de j = [selon choix]
         avec j < [selon choix]
         avec un pas de 1
      faire :
      {
         nombreCandidats = nombreCandidats + reduitCandidatsCase( g, [selon choix], [selon choix], candidat )
      }
   }

   retourner nombreCandidats
}


On ajoutera certainement une fonction plus générale :
int réduire( Grille g, int lig, int col, int candidat )
{
   return reduireCandidatLigne( g, lig, col, candidat ) + reduireCandidatColonne( g, lig, col, candidat ) + reduireCandidatRegion( g, lig, col, candidat );
}


Voilou, si tu as un doute sur tes boucles for tu peux toujours les poster ici.


Il y a un point très important qui n'apparaît pas ici, il faudrait voir la déclaration de la structure Grille pour vérifier. Si les tableaux de cases sont alloués (malloc) ça marche sinon il faudra faire une petite correction sur les paramètres des fonctions. Une bien belle histoire sur le mode de passage des paramètres en C, mais comme à l'accoutumée : l'héroïne triomphera à la fin ;-)

A bientôt.
0
merci beaucoup zigzag !!!!

je vais essayer de le traduire :



int candidatures( Grille g, int lig, int candidat )
{

int nbdecandidat;
int j;

j=0;

while ( j < 9 ) {

nbdecandidat = nbdecandidat + reduitCandidatsCase( g, lig, col, candidat )

j=j+1
return ( nbdecandidat )

}


pour la région je fais un truc aussi si tu pourrais me dire ce que t'en pense
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Il manquait deux p'tits point-virgules et une accolade mais c'est tout bon.
Aussi le col dans l'appel à reduitCandidatsCase qui en fait est j. Une histoire de copié-collé à mon avis. ;-)

int candidatures( Grille g, int lig, int candidat )
{
    int nbdecandidat;
    int j=0;

    while ( j < 9 ) 
    {
        nbdecandidat = nbdecandidat + reduitCandidatsCase( g, lig, j, candidat );

        j = j + 1;
    }

    return ( nbdecandidat );
}


On peut aussi l'écrire avec un for qu'on utilise plus facilement avec les compteurs comme ton j.

int candidatures( Grille g, int lig, int candidat )
{
    int nbdecandidat;
    int j;

    for ( j = 0 ; j < 9 ; j = j + 1 ) 
    {
        nbdecandidat += reduitCandidatsCase( g, lig, j, candidat );
    }

    return ( nbdecandidat );
}


Pourras-tu montrer aussi la déclaration du type Grille s'il te plaît ?

Je trouve en passant que reduireCandidatLigne est plus compréhensible que candidatures mais ce n'est pas moi l'artiste. ^^

A bientôt Julie-Marie032.

Tu es née en février 2003 ?
^^"



Ton compilateur ne t'avait pas dit pour les ; et l' } ?
(Oups, un message caché :-))
0
#include <stdio.h>
#include <stdbool.h>

/

typedef struct {
int val; /* Contenu de la case (0 si vide)*/
int candidats[9]; /* la "liste" des candidats */
int nbCandidats; /* Nombre de candidats possibles */
} Case;

typedef Case Grille[9][9];


voila ^^

mais je suis très contente de l'aide que tu m'a aporté , merci beaucoup zizag ( et je te rassure j'ai pas 5 ans , mais plutôt 20 et je suis a la fac :) )

bisoux a+
0
Et aussi pour la colonne ca ferait :

int reduitCandidatsColonne(Grille g, int ligne, int val)

{
int nbdecandidat;
int j=0;

while ( j < 9 )
{
nbdecandidat = nbdecandidat + reduitCandidatsCase( g, j ,colonne , val );

j = j + 1;
}

return ( nbdecandidat );
}



et poru la régino j'avais pensé à ca :

nt reduitCandidatsRégion(Grille g, int region, int val) (int i,int j,sudoku grille)
{
int k,l,pos_ligne,pos_colonne;

if((0<=i)&&(i<=2))
{
pos_ligne=0;
}
if((3<=i)&&(i<=5))
{
pos_ligne=3;
}
if((6<=i)&&(i<=8))
{
pos_ligne=6;
}
if((0<=j)&&(j<=2))
{
pos_colonne=0;
}
if((3<=j)&&(j<=5))
{
pos_colonne=3;
}
if((6<=j)&&(j<=8))
{
pos_colonne =6;
}

for(k=pos_ligne;k<(pos_ligne+3);k++)
{
for(l=pos_colonne;l<(pos_colonne+3);l++)
{
if(grille[k][l].val!=0)
{

supprimer_val_d1tableau(grille[i][j].taille_tableau,grille[i][j].tab,grille[k][l].val­);
}
}
}
}


mais je suis pas sure et puis ca retourne pas le nombre de candidat éliminé sur la région ^^
0
et aussi un dernierc truc vu que t'a l'air trop fort ( j'en profite :) )

je dois écrire ces deux autres fonctions

la premeire
Ecrire la fonction int chercheCandidatCacheLigne(Grille g, int ligne, int val) qui pour la ligne ligne
retourne le numéro de la colonne où se trouve le candidat caché val, ou -1 si il n'y en a pas.

j'ai fais ca :

define NB_COLONNES 9
#define NB_LIGNES 9

int cherchecandidatcacheligne ( grille g , int ligne , int val ) {
for( int colonne_courante=0; colonne_courante<NB_COLONNES; colonne_courante++) {
if (grille[ligne][colonne_courante] == val)
return colonne_courante;
}
return -1;
}


j'avais une autre fonction à écrire

Ecrire la fonction int candidatsCachesLigne(Grille g) qui trouve et note les candidats cachés sur les lignes
puis retourne le nombre de candidat cachés notés.

je sais pas trop comment l'écrire , quelqun a une idée ? c'est toujours un sudoku et les canddiats caché sont les candidats qui n'aparaisse pas dans la grille initiale ( le sudoku quand il n'est pas remplie quoi ) enfin je crois :p
0
Je mets les réponses aux trois à la suite (comme dirait Julien. Ah non, lui c'est quatre...)

Réponse 1)

C'est okay pour le typedef Case Grille[9][9]; J'aurais peut-être pu le voir aux crochets ^^"

Hmmm pas cinq ans alors... Ha je sais ! Ta soeur Marie est née un 26 !


Réponse 2)

Pour reduitCandidatsColonne ... mon message caché devait-être trop bien caché :oP Ca ne compile pas. Mais presque donc je ne vais pas râler, le compilo le fera pour moi. :D


Ah bah pour reduitCandidatsRégion par contre là je vais râler !
nt reduitCandidatsRégion(Grille g, int region, int val) (int i,int j,sudoku grille) ?? Va te falloir un bon avocat pour gagner sur un coup pareil ;-)

(int i,int j,sudoku grille) C'est la rencontre du troisième type ^^" (qui semble tout droit venu d'ailleurs, Lalalaaaa...) Avec une fonction clonée qui débarque également et aussi un membre d'une structure qui n'est pas la tienne. Désolé, un doute plane :'( Moi, c'est toi que je veux aider. Hooooop, allez, j'arrête. Continuons, je t'accorde le bénéfice du doute ;-)

Pour les if, on peut faire plus court.
pour i:
0, 1, 2 -> 0
3, 4, 5 -> 3
6, 7, 8 -> 6
soit : (i / 3) * 3 en se servant de la division entière. ( 2 / 3 = 0 ; 5 / 3 = 1... )

Avec ça on peut simplifier.

int reduitCandidatsRegion( <Panpan qq> )
{
    int i;
    int j;
    int pos_ligne = (lig / 3) * 3;
    const int pos_colonne = (col / 3) * 3;
    const int nbCandidatsElimines = 0;

    for( i = pos_ligne ; i < pos_ligne + 3 ; i++ )
    {
        for( j = pos_colonne ; j < pos_colonne + 3 ; j++ )
        {
            // Pas compris ce que tu voulais ici.
            // ...
        }
    }

    return nbCandidatsElimines;
} 


Réponse 3)

Eh béh...au rique de décevoir Julie-Maria :'( Je n'ai pas compris ce qu'était un "candidat caché". Je ne sais pas si c'est la solution pour la case ou la liste des indices où une valeur donnée peut être insérée dans la ligne.
A préciser s'il te plaît.

Bonne soirée à toi!
0
je répond tant que t'es la :

un candidat caché c'est par exemple sur une ligne t'a :

3-vide-vide-vide-5-vide-vide-6-vide-9-8

les candidats caché c'est les cases qu'il faut remplir pour finir le sudoku ici le vide ^^

dans mon exemple il y a 6 candidats cachés
0
et pour répondre aux restes :


int reduitCandidatsRégion(Grille g, int region, int val)


int i;
int j;
int pos_ligne = (lig / 3) * 3;
const int pos_colonne = (col / 3) * 3;
const int nbCandidatsElimines = 0;

for( i = pos_ligne ; i < pos_ligne + 3 ; i++ )
{
for( j = pos_colonne ; j < pos_colonne + 3 ; j++ )
{
// je sais pas quoi mettre car je sais pas comment utilisé reductioncase ^^ car une fois qu'on a les possibilité je ne sais pas comment faire pour savoir combien ya nbdecandidats éliminés


}
}

return nbCandidatsElimines;
}


enfin merci beaucoup quand meme je t'adore ( et pour le compilateur j'en ai pas ... ceci expliquerais cela ^^ )
0
et pour marie en fait c'est mon " faux pseudo " c'est parce que je voulais posais une autre question mais je ovulais pas qu'on pense que je suis trop nulle en posant des tas de question

et pour la première fonction j'ai demandé a une amie de m'aider et elle m'avait fait ca mais je me doutias que ca allait pas
0
Ah, vi , d'accord.

Pour les candidats cachés je ferais alors une fonction qui recherche la colonne où une valeur est insérée et qui renvoie -1 si la valeur n'est pas dans cette ligne. Techniquement j'ai juste changé le nom de ta fonction mais je trouve bizarre de faire une fonction qui renvoie -1 en cas de succès (candidat caché trouvé) et des nombres positifs en cas d'échec. Je préfère l'approche "si la fonction n'a pas trouvé cette valeur dans la ligne alors c'est qu'elle est cachée"

Donc grosso modo, je suis d'accord avec ta proposition pour peu que le nom soit mieux choisi, que le deuxième return soit dans le else et qu'il y ait un membre appelé sur la structure grille[pif][paf] .ici == val


Pour l'autre post:
int reduitCandidatsRégion(Grille g, int region, int val)
{
    int i;
    int j;
    int pos_ligne = (region / 3) * 3;
    const int pos_colonne = (region % 3) * 3;
    const int nbCandidatsElimines = 0;

    for( i = pos_ligne ; i < pos_ligne + 3 ; i++ )
    {
        for( j = pos_colonne ; j < pos_colonne + 3 ; j++ )
        {
            // Comme pour la ligne ou la colonne, qu'en penses-tu ?
        }
    }

    return nbCandidatsElimines;
}


enfin merci beaucoup quand meme je t'adore
Je sais, les gens débordent d'amour quand ils ont besoin de quelque chose :D
(Mais nan... si on peut plus rien dire... ;-))

Juste une précision quand même... 0:-) C'est :

"enfin merci beaucoup quand meme... je t'adore."
ou
"enfin, merci beaucoup ! quand meme... je t'adore !"
Une phrase non ponctuée perd tellement de son sens...
(Ne mets pas ton adresse sur ce site ou tu vas avoir une jalouse à ta porte ! :D)

Et maintenant, tu as un compilo ?
Code::Blocks + Gcc (Win et Linux)
MS Visual Express edtition (Win)
MS Visual Studio 2008 (Win si ton université est inscrite au programme Microsoft (site officiel))

Pour la fonction qui affiche les candidats cachés il faut faire une boucle sur les valeur de 1 à 9 et demander à chaque fois si c'est un candidat caché de la ligne courante. (et les compter au passage) Les boucles ça te connaît maintenant, je te laisse faire. ^^
0
comme ca ? :)

int reduitCandidatsRégion(Grille g, int region, int val)
{
int i;
int j;
int pos_ligne = (region / 3) * 3;
const int pos_colonne = (region % 3) * 3;
const int nbCandidatsElimines = 0;

for( i = pos_ligne ; i < pos_ligne + 3 ; i++ )
{
for( j = pos_colonne ; j < pos_colonne + 3 ; j++ )
{
nbdecandidat = nbdecandidat + reduitCandidatsCase( g, j ,i , val );
}
}

return nbCandidatsElimines;
}


Je suis en train de télécharger dev - c++ pour le compilateur ^^

Comme ca se fait que tu sois aussi fort ?? ( même si c'est vrai que moi je fais ça uniquement car on me le demande , à chaque fois je suis larguée en info :p )

et je t'admires beaucoup car t'aides et en plus t'es gentil ( et t'essayes de faire de l'humour, lol ) contrairement a mon professeur d'informatique ...
0
Oki, c'est donc ça qu'on ne reconnaît pas la patte de l'auteur par rapport au premier post. ^^"

Ca te dérange si je continue à t'appeler Marie ?
Je vais t'avouer un truc mais faut que ça reste entre nous ok ? Mon vrai nom c'est pas Zigzag ! :D (désolé, Julie)

Pardon, je vais redevenir plus... enfin moins c** surtout ^^".
0
par contre je me demande si on s'est pas trompé dans les fonctions car dnas la consigne yavé écrit :

écrire la fonction int reduitCandidatsLigne(Grille g, int ligne, int val) qui parcourt les cases
vides de la ligne d'indice ligne et qui y élimine les candidats de valeur val. Cette fonction
retourne le nombre de candidats éliminés sur toute la ligne.

et dans nos fonction on élimine rien , non ? ( parce qu'avant il demandait d'écrire la focntion supprimer la valeur d'un tableau )
0
j'ai paniqué pour rien je crois car la fonction reduirecase élimine la valeur

ouf j'ai eu une petite frayeur ( c'est parce que je dois tout rendre demain ... oui je sais je m'y prend au dernier moment )
0
Je me doute que tu t'apelles pas zigzag ^^

tu peux m'appeler marie je comprendrais :D ( je suis pas aussi bête que tu peux le penser , au vue de tout ce que je demande )

bon j'y vais , bonne nuit et merci encore ++
0
Pour l'instant, la seule chose qui te largue en info c'est ton manque de confiance en toi. T'as l'algo, le code sors comme il faut aussi... y manque toujours un ; de-ci de-là mais je pense que grand-mère dans ton rocking-chair t'en oublieras encore, comme tout le monde... Le seul truc qui peut te manquer c'est de la pratique mais t'as le droit de pas aimer l'info et de ne plus vouloir en faire après la fac, personne t'en voudra

(Sauf moi ! Gnark gnark gnark !)
J'en ai marre d'être "gentil" :'(

Pour Dev-Cpp, la première chose est de créer un projet avec l'assistant, puis de rajouter tes fichiers. Eventuellement de virer le leur si tu as ton main. Dev-cpp utilise Gcc aussi comme compilateur.
0
Je t'appellerai Julie. C'est le pseudo que tu t'es choisi, un point c'est tout. C'est une raison bien suffisante.
On doit te dire souvent que tu es trop gentille...

je suis pas aussi bête que tu peux le penser
Ah là, pour une fois... Tu me déçois. :'(


A demain peut-être (si tu es là)
;-)
0