Пример #1
0
        // calculate a probability for each un-revealed tile on the board
        public void Process()
        {
            this.mask = new bool[this.boxes.Count];

            // create an initial solution of no mines anywhere
            ProbabilityLine held = new ProbabilityLine(this.boxes.Count);

            held.SetSolutionCount(1);
            this.heldProbs.Add(held);

            // add an empty probability line to get us started
            this.workingProbs.Add(new ProbabilityLine(this.boxes.Count));

            NextWitness nextWitness = FindFirstWitness();

            while (nextWitness != null)
            {
                // mark the new boxes as processed - which they will be soon
                foreach (Box box in nextWitness.GetNewBoxes())
                {
                    this.mask[box.GetUID()] = true;
                }

                this.workingProbs = MergeProbabilities(nextWitness);

                nextWitness = FindNextWitness(nextWitness);
            }

            CalculateBoxProbabilities();
        }
Пример #2
0
        // this is used to recursively place the missing Mines into the available boxes for the probability line
        private List <ProbabilityLine> DistributeMissingMines(ProbabilityLine pl, NextWitness nw, int missingMines, int index)
        {
            //console.log("Distributing " + missingMines + " missing mines to box " + nw.newBoxes[index].uid);

            this.recursions++;
            if (this.recursions % 100000 == 0)
            {
                information.Write("Solution Counter recursision = " + recursions);
            }

            List <ProbabilityLine> result = new List <ProbabilityLine>();

            // if there is only one box left to put the missing mines we have reach the end of this branch of recursion
            if (nw.GetNewBoxes().Count - index == 1)
            {
                // if there are too many for this box then the probability can't be valid
                if (nw.GetNewBoxes()[index].GetMaxMines() < missingMines)
                {
                    //console.log("Abandon (1)");
                    return(result);
                }
                // if there are too few for this box then the probability can't be valid
                if (nw.GetNewBoxes()[index].GetMinMines() > missingMines)
                {
                    //console.log("Abandon (2)");
                    return(result);
                }
                // if there are too many for this game then the probability can't be valid
                if (pl.GetMineCount() + missingMines > this.maxTotalMines)
                {
                    //console.log("Abandon (3)");
                    return(result);
                }

                // otherwise place the mines in the probability line
                pl.SetMineBoxCount(nw.GetNewBoxes()[index].GetUID(), new BigInteger(missingMines));

                pl.SetMineCount(pl.GetMineCount() + missingMines);
                result.Add(pl);
                //console.log("Distribute missing mines line after " + pl.mineBoxCount);
                return(result);
            }


            // this is the recursion
            int maxToPlace = Math.Min(nw.GetNewBoxes()[index].GetMaxMines(), missingMines);

            for (int i = nw.GetNewBoxes()[index].GetMinMines(); i <= maxToPlace; i++)
            {
                ProbabilityLine npl = ExtendProbabilityLine(pl, nw.GetNewBoxes()[index], i);

                List <ProbabilityLine> r1 = DistributeMissingMines(npl, nw, missingMines - i, index + 1);
                result.AddRange(r1);
            }

            return(result);
        }
Пример #3
0
        // counts the number of mines already placed
        private BigInteger CountPlacedMines(ProbabilityLine pl, NextWitness nw)
        {
            BigInteger result = 0;

            foreach (Box b in nw.GetOldBoxes())
            {
                result = result + pl.GetMineBoxCount(b.GetUID());
            }

            return(result);
        }
Пример #4
0
        // take the next witness details and merge them into the currently held details
        private List <ProbabilityLine> MergeProbabilities(NextWitness nw)
        {
            List <ProbabilityLine> newProbs = new List <ProbabilityLine>();

            foreach (ProbabilityLine pl in this.workingProbs)
            {
                int missingMines = nw.GetBoxWitness().GetMinesToFind() - (int)CountPlacedMines(pl, nw);

                if (missingMines < 0)
                {
                    //console.log("Missing mines < 0 ==> ignoring line");
                    // too many mines placed around this witness previously, so this probability can't be valid
                }
                else if (missingMines == 0)
                {
                    //console.log("Missing mines = 0 ==> keeping line as is");
                    newProbs.Add(pl);   // witness already exactly satisfied, so nothing to do
                }
                else if (nw.GetNewBoxes().Count == 0)
                {
                    //console.log("new boxes = 0 ==> ignoring line since nowhere for mines to go");
                    // nowhere to put the new mines, so this probability can't be valid
                }
                else
                {
                    List <ProbabilityLine> result = DistributeMissingMines(pl, nw, missingMines, 0);
                    newProbs.AddRange(result);
                }
            }

            //if (newProbs.length == 0) {
            //     console.log("Returning no lines from merge probability !!");
            //}

            return(newProbs);
        }
Пример #5
0
        // look for the next witness to process
        private NextWitness FindNextWitness(NextWitness prevWitness)
        {
            // flag the last set of details as processed
            prevWitness.GetBoxWitness().SetProcessed(true);

            foreach (Box newBox in prevWitness.GetNewBoxes())
            {
                newBox.SetProcessed(true);
            }

            int        bestTodo    = 99999;
            BoxWitness bestWitness = null;

            // and find a witness which is on the boundary of what has already been processed
            foreach (Box b in this.boxes)
            {
                if (b.IsProcessed())
                {
                    foreach (BoxWitness w in b.GetBoxWitnesses())
                    {
                        if (!w.IsProcessed())
                        {
                            int todo = 0;
                            foreach (Box b1 in w.GetBoxes())
                            {
                                if (!b1.IsProcessed())
                                {
                                    todo++;
                                }
                            }
                            if (todo == 0)      // prioritise the witnesses which have the least boxes left to process
                            {
                                return(new NextWitness(w));
                            }
                            else if (todo < bestTodo)
                            {
                                bestTodo    = todo;
                                bestWitness = w;
                            }
                        }
                    }
                }
            }

            if (bestWitness != null)
            {
                return(new NextWitness(bestWitness));
            }
            else
            {
                information.Write("Ending independent edge");
            }

            //independentGroups++;

            // since we have calculated all the mines in an independent set of witnesses we can crunch them down and store them for later

            // store the details for this edge
            StoreProbabilities();


            // get an unprocessed witness
            NextWitness nw = FindFirstWitness();

            if (nw != null)
            {
                information.Write("Starting a new independent edge");
            }

            // If there is nothing else to process then either do the local clears or calculate the probabilities
            if (nw == null)
            {
                edgeStore.Sort(EdgeStore.SortByLineCount);

                AnalyseAllEdges();

                long start = DateTime.Now.Ticks;
                foreach (EdgeStore edgeDetails in edgeStore)
                {
                    workingProbs = edgeDetails.data;
                    CombineProbabilities();
                }
                information.Write("Combined all edges in " + (DateTime.Now.Ticks - start) + " ticks");
            }

            // return the next witness to process
            return(nw);
        }