Exemple #1
0
        static List <int>[] DomeinToevoeging(Knoop k, int getal, List <int> verwijderdKolom, List <int> verwijderdRij, List <int> verwijderdBlok)
        {
            // zelfde idee maar dan als toevoeging, als een vakje in lijn staat met p, voeg dan getal weer toe aan het domein
            for (int kCount = 0; kCount < verwijderdKolom.Count(); kCount++)       //kolom
            {
                int ko = verwijderdKolom[kCount];

                k.domein[ko].Add(getal);
            }

            for (int rCount = 0; rCount < verwijderdRij.Count(); rCount++)                   //rij
            {
                int r = verwijderdRij[rCount];

                k.domein[r].Add(getal);
            }
            for (int bCount = 0; bCount < verwijderdBlok.Count(); bCount++)                              //blok
            {
                int b = verwijderdBlok[bCount];

                k.domein[b].Add(getal);
            }

            return(k.domein);
        }
Exemple #2
0
        // ALGORITMES //

        static bool BackTracking(Knoop k, int p, int n, int worteln)           // Knoop k is beginknoop, p staat voor positie die we invullen
        {                                                                      // en n is voor grid grootte, worteln wortel van n
            if (p == n * n)                                                    // als we bij de laatste positie zijn aangekomen dan zijn er geen schendingen
            {
                return(true);                                                  // en hebben we een oplossing
            }
            k.i++;


            if (k.sudoku[p] == 0)
            {
                (int x, int y) = VraagCoOrdinaat(n, p);                         // het recursieve gedeelte
                int z = (x / worteln) + (y / worteln) * worteln;                // x: kolomnummer, y: rijnummer, z: bloknummer

                for (int toewijzing = 1; toewijzing <= n; toewijzing++)         // toewijzing van een invulling aan positie p
                {
                    if (!k.kolom[x].Contains(toewijzing) &&
                        !k.rij[y].Contains(toewijzing) &&
                        !k.blok[z].Contains(toewijzing))                        // er wordt gecheckt of op die plek dit cijfer kan
                    {
                        k.sudoku[p] = toewijzing; k.kolom[x].Add(toewijzing);   //pas knoop aan door aan alle delen de nieuwe toewijzing
                        k.rij[y].Add(toewijzing); k.blok[z].Add(toewijzing);    //toe te voegen


                        if (BackTracking(k, p + 1, n, worteln))
                        {
                            return(true);                         // als er niks wordt geschonden, backtrack dan verder
                        }
                        k.sudoku[p] = 0; k.kolom[x].Remove(toewijzing);
                        k.rij[y].Remove(toewijzing); k.blok[z].Remove(toewijzing);
                    }
                }
            }
            else
            {
                return(BackTracking(k, p + 1, n, worteln));
            }

            return(false);
        }
Exemple #3
0
        static bool StandardForwardChecking(Knoop k, int p, int n, int worteln)
        {
            if (p == n * n)                                                     // als we bij de laatste positie zijn aangekomen dan zijn er geen schendingen
            {
                return(true);                                                   // en hebben we een oplossing
            }
            k.i++;

            if (k.sudoku[p] == 0)
            {
                (int x, int y) = VraagCoOrdinaat(n, p);                         // het recursieve gedeelte
                int z = (x / worteln) + (y / worteln) * worteln;                // x: kolomnummer, y: rijnummer, z: bloknummer

                for (int getal = 1; getal <= n; getal++)
                {
                    if (k.domein[p].Contains(getal))
                    {
                        // er worden lijsten aangemaakt die bij zullen houden van welke
                        // vakjes er in het domein iets verwijderd wordt
                        List <int> verwijderdRij   = new List <int>();
                        List <int> verwijderdKolom = new List <int>();
                        List <int> verwijderdBlok  = new List <int>();

                        // het vakje wordt ingevuld met een getal
                        k.sudoku[p] = getal;

                        // de vakjes met dezelfde x worden gecheckt op domein,
                        // als getal in het domein zit, wordt deze eruit gehaald
                        bool kolomFout = false;
                        for (int ko = x; ko < ((n - 1) * n + x) + 1; ko += n)       //kolom
                        {
                            if (k.sudoku[ko] == 0 && k.domein[ko].Contains(getal))
                            {
                                k.domein[ko].Remove(getal);

                                // als er na verwijdering niks meer in het domein van een vakje
                                // zit, geeft het programma een foutmelding en is het huidige getal fout
                                if (!k.domein[ko].Any())
                                {
                                    k.domein[ko].Add(getal);

                                    List <int>[] kolomFoutArray = DomeinToevoeging(k, getal, verwijderdKolom, verwijderdRij, verwijderdBlok);

                                    for (int i = 0; i < kolomFoutArray.Length; i++)
                                    {
                                        k.domein[i] = kolomFoutArray[i];
                                    }

                                    k.sudoku[p] = 0;

                                    kolomFout = true;
                                    break;
                                }

                                // anders wordt het getal uit het domein gehaald
                                // en wordt de coordinaat van het vakje opgeslagen
                                verwijderdKolom.Add(ko);
                            }
                        }
                        if (kolomFout == true)
                        {
                            kolomFout = false;
                            continue;
                        }

                        // de vakjes met dezelfde y worden gecheckt op domein,
                        // als getal in het domein zit, wordt deze eruit gehaald
                        bool rijFout = false;
                        for (int r = y * n; r < (y * n + n); r++)                   //rij
                        {
                            if (k.sudoku[r] == 0 && k.domein[r].Contains(getal))
                            {
                                k.domein[r].Remove(getal);

                                // als er na verwijdering niks meer in het domein van een vakje
                                // zit, geeft het programma een foutmelding en is het huidige getal fout
                                if (!k.domein[r].Any())
                                {
                                    k.domein[r].Add(getal);

                                    List <int>[] rijFoutArray = DomeinToevoeging(k, getal, verwijderdKolom, verwijderdRij, verwijderdBlok);

                                    for (int i = 0; i < rijFoutArray.Length; i++)
                                    {
                                        k.domein[i] = rijFoutArray[i];
                                    }

                                    k.sudoku[p] = 0;

                                    rijFout = true;
                                    break;
                                }

                                // anders wordt het getal uit het domein gehaald
                                // en wordt de coordinaat van het vakje opgeslagen
                                verwijderdRij.Add(r);
                            }
                        }
                        if (rijFout == true)
                        {
                            rijFout = false;
                            continue;
                        }

                        // de vakjes met hetzelfde bloknummer worden gecheckt op domein,
                        // als getal in het domein zit, wordt deze eruit gehaald
                        bool blokFout = false;
                        for (int b = 0; b < n * n; b++)                              //blok
                        {
                            (int X, int Y) = VraagCoOrdinaat(n, b);
                            int Z = (X / worteln) + (Y / worteln) * worteln;

                            if (z == Z)
                            {
                                if (k.sudoku[b] == 0 && k.domein[b].Contains(getal))
                                {
                                    k.domein[b].Remove(getal);

                                    // als er na verwijdering niks meer in het domein van een vakje
                                    // zit, geeft het programma een foutmelding en is het huidige getal fout
                                    if (!k.domein[b].Any())
                                    {
                                        k.domein[b].Add(getal);

                                        List <int>[] blokFoutArray = DomeinToevoeging(k, getal, verwijderdKolom, verwijderdRij, verwijderdBlok);

                                        for (int i = 0; i < blokFoutArray.Length; i++)
                                        {
                                            k.domein[i] = blokFoutArray[i];
                                        }

                                        k.sudoku[p] = 0;

                                        blokFout = true;
                                        break;
                                    }

                                    // anders wordt het getal uit het domein gehaald
                                    // en wordt de coordinaat van het vakje opgeslagen
                                    verwijderdBlok.Add(b);
                                }
                            }
                        }
                        if (blokFout == true)
                        {
                            blokFout = false;
                            continue;
                        }

                        // als het algoritme met het huidige getal tot een oplossing
                        // komt, is het goed ingevuld
                        if (StandardForwardChecking(k, p + 1, n, worteln))
                        {
                            return(true);
                        }

                        // anders wordt het getal en alle domeinaanpassingen gereset
                        List <int>[] tempArray = DomeinToevoeging(k, getal, verwijderdKolom, verwijderdRij, verwijderdBlok);

                        for (int i = 0; i < tempArray.Length; i++)
                        {
                            k.domein[i] = tempArray[i];
                        }

                        k.sudoku[p] = 0;
                    }
                }
            }
            else
            {
                return(StandardForwardChecking(k, p + 1, n, worteln));
            }

            return(false);
        }
Exemple #4
0
        static void Main(string[] args)
        {
            // Check if command contains an algorithm name we should use
            // and the txt file we should read
            string algorithm = "CB";

            if (args.Contains("-CB"))
            {
                algorithm = "CB";
            }
            else if (args.Contains("-FC"))
            {
                algorithm = "FC";
            }

            string txtFile = "";

            if (args.Contains("-sud"))
            {
                int sudInd = Array.IndexOf(args, "-sud");
                txtFile = args[sudInd + 1];
            }
            else
            {
                Console.WriteLine("A .txt file should be given, after -sud");
            }

            // Get path of txt file
            string workingDirectory = Environment.CurrentDirectory;
            string txtPath          = workingDirectory + "/" + txtFile;

            // Read a text file line by line.
            string[]     lines     = File.ReadAllLines(txtPath);
            int          lineInd   = 0;
            int          numSudoku = 0;
            List <Knoop> sudokus   = new List <Knoop>();
            List <int>   ns        = new List <int>();

            while (lineInd < lines.Length)
            {
                // If the line starts with a letter,
                // that's an indication that the next N lines
                // will be a sudoku
                if (lines[lineInd].Any(x => char.IsLetter(x)))
                {
                    lineInd++;
                    numSudoku++;

                    char[]   chars    = lines[lineInd].ToCharArray();
                    string[] line     = Array.ConvertAll(chars, char.ToString);
                    int[]    intarray = Array.ConvertAll <string, int>(line, int.Parse);
                    int      N        = line.Length;
                    ns.Add(N);

                    //N x N 2D array is generated
                    //values in the first line are added to the array
                    //& checked whether fixed values.
                    int[] inputState = new int[N * N];

                    for (int j = 0; j < N; j++)
                    {
                        inputState[j] = intarray[j];
                    }

                    for (int nextLines = 1; nextLines < N; nextLines++)
                    {
                        chars    = lines[lineInd + nextLines].ToCharArray();
                        line     = Array.ConvertAll(chars, char.ToString);
                        intarray = Array.ConvertAll <string, int>(line, int.Parse);

                        for (int nextVal = nextLines * N; nextVal < (nextLines + 1) * N; nextVal++)
                        {
                            inputState[nextVal] = intarray[nextVal - nextLines * N];
                        }
                    }
                    lineInd += N;

                    int          wortelN  = (int)Math.Sqrt(N);
                    List <int>[] kolommen = MaakKolommen(N, inputState);
                    List <int>[] rijen    = MaakRijen(N, inputState);
                    List <int>[] blokken  = MaakBlokken(N, wortelN, inputState);            // blokken rijen en kolommen worden aangemaakt van de sudoku
                    List <int>[] domein   = MaakDomeinen(N, wortelN, inputState, kolommen, rijen, blokken);

                    Knoop input = new Knoop(inputState, kolommen, rijen, blokken, domein);
                    sudokus.Add(input);
                }
                else
                {
                    lineInd++;
                }
            }


            // Now that the sudoku has been read and the
            // algorithm determined, run the algorithm
            // on the sudoku
            List <int> evalScores = new List <int>();

            for (int tempNum = 0; tempNum < numSudoku; tempNum++)
            {
                bool  resultaat = false;
                Knoop input     = sudokus[tempNum];
                int   N         = ns[tempNum];
                int   worteln   = (int)Math.Sqrt(N);

                // If the algorithm is Chronological
                // Backtracking, use that on the sudokus
                // that are to be solved
                if (algorithm == "CB")
                {
                    time.Start();
                    resultaat = BackTracking(input, 0, N, worteln);
                    time.Stop();
                    if (resultaat)
                    {
                        // Some output that is printed when a result has been found
                        Console.WriteLine("Time elapsed for CB: {0}", time.Elapsed);
                        time.Reset();
                        Console.WriteLine("Amount of nodes expanded: " + input.i);
                        int[] output = input.sudoku;
                        for (int ib = 0; ib < N * N; ib++)
                        {
                            Console.Write(output[ib]);
                            if ((ib + 1) % 9 == 0)
                            {
                                Console.Write("\n");
                            }
                        }
                    }
                    else
                    {
                        // Because CB is complete, when it doesn't have an outcome,
                        // it means there isn't a solution to the sudoku
                        Console.WriteLine("There is no solution to this sudoku.");
                        time.Reset();
                    }
                }
                // If the algorithm is Forward
                // Checking, use that on the sudokus
                // that are to be solved
                else if (algorithm == "FC")
                {
                    time.Start();
                    resultaat = StandardForwardChecking(input, 0, N, worteln);
                    time.Stop();
                    if (resultaat)
                    {
                        // Some output that is printed when a result has been found
                        Console.WriteLine("Time elapsed for FC: {0}", time.Elapsed);
                        time.Reset();
                        Console.WriteLine("Amount of nodes expanded: " + input.i);
                        int[] output = input.sudoku;
                        for (int ib = 0; ib < N * N; ib++)
                        {
                            Console.Write(output[ib]);
                            if ((ib + 1) % 9 == 0)
                            {
                                Console.Write("\n");
                            }
                        }
                    }
                    else
                    {
                        // Because FC is complete, when it doesn't have an outcome,
                        // it means there isn't a solution to the sudoku
                        Console.WriteLine("There is no solution to this sudoku.");
                        time.Reset();
                    }
                }

                Console.ReadLine();
            }

            Console.ReadLine();
        }