Beispiel #1
0
        /// <summary>
        /// Recherche si ligne Vertical dupliqué
        /// </summary>
        /// <param name="sudoku"></param>
        /// <returns></returns>
        public static bool NoDuplicateRowVerti(Sudoku sudoku)
        {
            HashSet <int[]> hashSet = new HashSet <int[]>();

            // premier élément
            hashSet.Add(sudoku.GetRowVertical(0));

            for (int i = 1; i < Sudoku.SIZE - 1; i++)
            {
                var r = sudoku.GetRowVertical(i);

                foreach (var hash in hashSet)
                {
                    // regarde si cette ligne existe déjà
                    if (RowUtil.RowEqual(r, hash))
                    {
                        // existe
                        return(false);
                    }
                }
            }

            hashSet = null;
            return(true);
        }
Beispiel #2
0
        public static bool IsRowVerticalIsPermutation(Sudoku sudoku)
        {
            for (int i = 0; i < Sudoku.SIZE; i++)
            {
                if (RowUtil.IsPermutation(sudoku.GetRowVertical(i)) == false)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #3
0
        public static bool IsRowMatrixIsPermutation(Sudoku sudoku)
        {
            for (int i = 0; i < Sudoku.SIZE; i++)
            {
                if (RowUtil.IsPermutation(RowUtil.GetRowsbMatrixFlate(i, sudoku.Matrix)) == false)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #4
0
        public ExpertSudoku(List <Fact> facts)
        {
            //-------------------------------------
            // apply chaining forward
            //-------------------------------------
            Console.WriteLine("-----------------");
            Console.WriteLine("Chainage avant");
            Console.WriteLine("-----------------");
            List <Exclure> exclures = null;

            // recherche les cases exclues.
            var flagValeurTrouve = true;

            while (flagValeurTrouve)
            {
                flagValeurTrouve = false;

                //---------------------
                // exclusions
                //---------------------
                exclures = new List <Exclure>();
                // exclu a cause de la permetutaion
                facts.ForEach(f => f.Exclure(exclures));
                // exclu les existantes differentes
                facts.ForEach(f =>
                {
                    for (int i = 0; i < f.Row.Count(); i++)
                    {
                        if (f.Row[i].HasValue)
                        {
                            foreach (var ee in exclures.Where(ex => ex.Valeur != f.Row[i].Value))
                            {
                                ee.AExclure[f.Id, i] = 1;
                            }
                        }
                    }
                });

                //---------------------
                // regle 1
                // si une valeur est autorisée que sur une case alors on a une solution
                //---------------------
                foreach (var exclure in exclures)
                {
                    var valeurTrouvee = exclure.SearchValues();
                    // retirer

                    if (valeurTrouvee.Count() > 0)
                    {
                        foreach (var vt in valeurTrouvee)
                        {
                            if (!facts[vt.Item1].Row[vt.Item2].HasValue)
                            {
                                flagValeurTrouve = true;
                                // met à jour la matrice
                                facts[vt.Item1].Row[vt.Item2] = exclure.Valeur;
                                Console.WriteLine($"Ligne : {vt.Item1 + 1}, colonne {vt.Item2 + 1}, valeur : {exclure.Valeur}");
                            }
                        }
                    }
                }

                //---------------------
                // regle 2
                // test les exclusions si interdit a tous les chiffres sauf un chiffre alors
                // on a trouvé une solution ( cellule ne convient pas 1,3,4,5,6,7,8,9 => reponse =2)
                // en meme temps prepare la liste des permutations possbiles.
                //---------------------
                foreach (var f in facts)
                {
                    f.Tirage = new List <List <int> >();

                    for (int i = 0; i < Sudoku.SIZE; i++)
                    {
                        if (!f.Row[i].HasValue)
                        {
                            List <int> choixInterdit = new List <int>();   //= Fact.POSSIBLE;
                            foreach (var ex in exclures)
                            {
                                if (ex.AExclure[f.Id, i] > 0)
                                {
                                    // exclure
                                    choixInterdit.Add(ex.Valeur);
                                }
                            }

                            var possible = Fact.POSSIBLE.Except(choixInterdit);

                            if (possible.Count() == 1)
                            {
                                // on a trouvé une solution
                                f.Row[i]         = possible.First();
                                flagValeurTrouve = true;
                                f.Tirage.Add(new List <int>()
                                {
                                    possible.First()
                                });
                                Console.WriteLine($"Ligne : {f.Id + 1}, colonne {i + 1}, valeur : {possible.First()}");
                            }
                            else
                            {
                                //pas trouvé on mets les choix possible
                                f.Tirage.Add(possible.ToList());
                            }
                        }
                        else
                        {
                            f.Tirage.Add(new List <int>()
                            {
                                f.Row[i].Value
                            });
                        }
                    }
                }
            }


            if (facts.All(f => f.Resolu))
            {
                // Si chainage avant gagné
                List <int[]> tmp = new List <int[]>();
                GetRowNonNullable(facts, tmp);

                RowUtil.PrintConsole(tmp);
                Solution = new Sudoku(tmp);
                return;
            }

            //-------------------------------------
            // apply chaining backward
            //-------------------------------------
            Console.WriteLine("-----------------");
            Console.WriteLine("Chainage arriere");
            Console.WriteLine("-----------------");


            facts.ForEach(f => f.PermuteRow2());


            // si apres permutation il y a une permutations ==1 une ligne a été résolu . on peut recommencer
            // les calculs avec les nouveaux fait inférés


            // iteration

            foreach (var t0 in facts[0].Permutaions)
            {
                foreach (var t1 in facts[1].Permutaions)
                {
                    foreach (var t2 in facts[2].Permutaions)
                    {
                        foreach (var t3 in facts[3].Permutaions)
                        {
                            foreach (var t4 in facts[4].Permutaions)
                            {
                                foreach (var t5 in facts[5].Permutaions)
                                {
                                    foreach (var t6 in facts[6].Permutaions)
                                    {
                                        foreach (var t7 in facts[7].Permutaions)
                                        {
                                            foreach (var t8 in facts[8].Permutaions)
                                            {
                                                List <int[]> rows = new List <int[]>();
                                                rows.Add(t0);
                                                rows.Add(t1);
                                                rows.Add(t2);
                                                rows.Add(t3);
                                                rows.Add(t4);
                                                rows.Add(t5);
                                                rows.Add(t6);
                                                rows.Add(t7);
                                                rows.Add(t8);


                                                var sudoku = new Sudoku(rows);

                                                if (ApplyRule(sudoku))
                                                {
                                                    Solution = sudoku;
                                                    RowUtil.PrintConsole(rows);

                                                    return;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            Console.WriteLine("Aucunesolution !");
        }
Beispiel #5
0
        /// <summary>
        /// il ne reste q'une seule case possible
        /// </summary>
        /// <returns></returns>
        internal List <Tuple <int, int> > SearchValues()
        {
            var findCells = new List <Tuple <int, int> >();

            // tester si c'est la seule possible sur une ligne
            for (int i = 0; i < Sudoku.SIZE; i++)
            {
                int nbPossible = 0, line = -1, column = -1;

                for (int c = 0; c < Sudoku.SIZE; c++)
                {
                    if (AExclure[i, c] == 0)
                    {
                        line   = i;
                        column = c;
                        nbPossible++;
                    }
                }

                if (nbPossible == 1)
                {
                    findCells.Add(new Tuple <int, int>(line, column));
                }
            }


            // tester si c'est la seule possible sur une Colonne
            for (int c = 0; c < Sudoku.SIZE; c++)
            {
                int nbPossible = 0, line = -1, column = -1;

                for (int i = 0; i < Sudoku.SIZE; i++)
                {
                    if (AExclure[i, c] == 0)
                    {
                        line   = i;
                        column = c;
                        nbPossible++;
                    }
                }

                if (nbPossible == 1)
                {
                    findCells.Add(new Tuple <int, int>(line, column));
                }
            }

            // seule valeur possible dans une sous matrice
            for (int i = 0; i < Sudoku.SIZE; i++)
            {
                var underMatrix = RowUtil.GetRowsbMatrixFlate(i, AExclure);

                // parcours cette sous matrice 3 X 3
                int nbPossible = 0, line = -1;

                for (int l = 0; l < underMatrix.Length; l++)
                {
                    if (underMatrix[l] == 0)
                    {
                        line = l;
                        nbPossible++;
                    }
                }

                if (nbPossible == 1)
                {
                    // recherche des coordonnées dans la matrice principale
                    int mainL = -1;
                    int MainC = -1;
                    RowUtil.getCoordMainMatrix(i, line, out mainL, out MainC);
                    findCells.Add(new Tuple <int, int>(mainL, MainC));
                }
            }

            return(findCells);
        }