mission2.adb

with Support ;
with SudoGrille ;
with Gada.Text_IO ;

procedure Mission2 is

   package G renames SudoGrille ;
   package Txt renames GAda.Text_IO ;

   type Un_Resultat is record
      Combien : Integer ;
      Valeur  : Integer ;
   end record ;

   type Un_Resultat_Double is record
      Combien : Integer ;
      Ligne   : Integer ;
      Colonne : Integer ;
   end record ;

   function Possibles_Lignes (Grille : G.Une_Grille ; Ligne : Integer ; Val : Integer) return Un_Resultat is
      NPossibles : Integer := 0 ;
      NoCol : Integer ;
   begin
      for Col in Grille'Range(2) loop
         if Grille(Ligne, Col)(Val) then
            NPossibles := NPossibles + 1 ;
            NoCol := Col ;
         end if ;
      end loop ;
      return (NPossibles, NoCol) ;
   end Possibles_Lignes ;


   procedure Tester_Possibles_Lignes is
      Res : Un_Resultat ;
   begin
      Res := Possibles_Lignes(G.Fabrique(G.Difficile), 1, 5) ;
      Txt.Put_Line("Possibles Ligne 1  Val 5 :  Combien = " & Integer'Image(Res.Combien) &
                   "  Valeur = " & Integer'Image(Res.Valeur)) ;
   end Tester_Possibles_Lignes ;

   function Possibles_Colonnes (Grille : G.Une_Grille ; Col : Integer ; Val : Integer) return Un_Resultat is
      NPossibles : Integer := 0 ;
      NoLigne : Integer ;
   begin
      for Ligne in Grille'Range(1) loop
         if Grille(Ligne, Col)(Val) then
            NPossibles := NPossibles + 1 ;
            NoLigne := Ligne ;
         end if ;
      end loop ;
      return (NPossibles, NoLigne) ;
   end Possibles_Colonnes ;

   function Possibles_Sous_Mat (Grille : G.Une_Grille ; Ligne, Col : Integer ; Val : Integer) return Un_Resultat_Double is
      NPossibles : Integer := 0 ;
      NoLigne, NoCol : Integer ;
      DepLigne : Integer := 3 * ((Ligne - 1) / 3) + 1 ;
      DepCol   : Integer := 3 * ((Col - 1) / 3) + 1 ;

   begin
      for NLigne in DepLigne..DepLigne+2 loop
         for NCol in DepCol..DepCol+2 loop
            if Grille(NLigne, NCol)(Val) then
               NPossibles := NPossibles + 1 ;
               NoLigne := NLigne ;
               NoCol   := NCol ;
            end if ;
         end loop ;
      end loop ;
      return (NPossibles, NoLigne, NoCol) ;
   end Possibles_Sous_Mat ;


   procedure Examiner_Ligne(Grille : in out G.Une_Grille ; Ligne : Integer) is
      Res : Un_Resultat ;
   begin
      for Val in 1..G.Taille loop
         Res := Possibles_Lignes(Grille, Ligne, Val) ;
         if Res.Combien = 1 then
            Grille(Ligne, Res.Valeur) := G.Fixe(Val) ;
         end if ;
      end loop ;
   end Examiner_Ligne ;

   procedure Examiner_Col(Grille : in out G.Une_Grille ; Col : Integer) is
      Res : Un_Resultat ;
   begin
      for Val in 1..G.Taille loop
         Res := Possibles_Colonnes(Grille, Col, Val) ;
         if Res.Combien = 1 then
            Grille(Res.Valeur, Col) := G.Fixe(Val) ;
         end if ;
      end loop ;
   end Examiner_Col ;

   procedure Examiner_Sous_Mat(Grille : in out G.Une_Grille ; Ligne, Col : Integer) is
      Res : Un_Resultat_Double ;
   begin
      for Val in 1..G.Taille loop
         Res := Possibles_Sous_Mat(Grille, Ligne, Col, Val) ;
         if Res.Combien = 1 then
            Grille(Res.Ligne, Res.Colonne) := G.Fixe(Val) ;
         end if ;
      end loop ;
   end Examiner_Sous_Mat ;


   -- Cette procedure est equivalente a celle demandee en partie 1,
   -- mais l'algorithme est different ici et ne correspond pas a ce qu'on vous demandait en partie 1.
   procedure Resous (LaGrille : in out SudoGrille.Une_Grille) is
      Continue : Boolean := True ;
   begin

      while Continue loop
         -- Ne modifiez pas la ligne suivante. Elle propage les contraintes comme dans la partie 1.
         Support.Propage_Tout(LaGrille, Continue) ;

         --G.Attend_Entree ;
         --G.Affiche(LaGrille) ;

         -- Lignes
         for Lig in LaGrille'Range(1) loop
            Examiner_Ligne(LaGrille, Lig) ;
         end loop ;

         -- Colonnes
         for Col in LaGrille'Range(2) loop
            Examiner_Col(LaGrille, Col) ;
         end loop ;

         -- Sous matrices
         for Lig in 1..G.SousTaille loop
            for Col in 1..G.SousTaille loop
               Examiner_Sous_Mat(LaGrille, Lig * G.SousTaille, Col * G.SousTaille) ;
            end loop ;
         end loop ;

      end loop ;

      SudoGrille.Affiche(LaGrille) ;

   end Resous ;





   -- Declarer ici la variable Sudok
   --Soduk : G.Une_Grille := G.Fabrique(G.Moyen) ;
   Soduk : G.Une_Grille := G.Fabrique(G.Difficile) ;
begin

   G.Affiche(Soduk) ;

   Resous(Soduk) ;


   --Tester_Possibles_Lignes ;

end Mission2 ;