// return any witness which hasn't been processed private NextWitness FindFirstWitness() { BoxWitness excluded = null; foreach (BoxWitness boxWit in this.boxWitnesses) { if (!boxWit.IsProcessed()) { return(new NextWitness(boxWit)); } else if (!boxWit.IsProcessed()) { excluded = boxWit; } } if (excluded != null) { return(new NextWitness(excluded)); } return(null); }
// 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); }
public SolutionCounter(SolverInfo information, List <SolverTile> allWitnesses, List <SolverTile> allWitnessed, int squaresLeft, int minesLeft) { this.information = information; this.witnessed = allWitnessed; // constraints in the game this.minesLeft = minesLeft; this.tilesLeft = squaresLeft; this.tilesOffEdge = squaresLeft - allWitnessed.Count; // squares left off the edge and unrevealed this.minTotalMines = minesLeft - this.tilesOffEdge; //we can't use so few mines that we can't fit the remainder elsewhere on the board this.maxTotalMines = minesLeft; this.mineCountUpperCutoff = minesLeft; this.mineCountLowerCutoff = minTotalMines; information.Write("Tiles off edge " + tilesOffEdge); //this.boxProb = []; // the probabilities end up here // generate a BoxWitness for each witness tile and also create a list of pruned witnesses for the brute force search int pruned = 0; foreach (SolverTile wit in allWitnesses) { BoxWitness boxWit = new BoxWitness(information, wit); // if the witness is a duplicate then don't store it bool duplicate = false; foreach (BoxWitness w in this.boxWitnesses) { if (w.Equivalent(boxWit)) { //if (boardState.getWitnessValue(w) - boardState.countAdjacentConfirmedFlags(w) != boardState.getWitnessValue(wit) - boardState.countAdjacentConfirmedFlags(wit)) { // boardState.display(w.display() + " and " + wit.display() + " share unrevealed squares but have different mine totals!"); // validWeb = false; //} duplicate = true; break; } } if (!duplicate) { this.prunedWitnesses.Add(boxWit); } else { pruned++; } this.boxWitnesses.Add(boxWit); // all witnesses are needed for the probability engine } information.Write("Pruned " + pruned + " witnesses as duplicates"); information.Write("There are " + this.boxWitnesses.Count + " Box witnesses"); // allocate each of the witnessed squares to a box int uid = 0; foreach (SolverTile tile in this.witnessed) { // for each adjacent tile see if it is a witness int count = 0; //foreach (SolverTile adjTile in information.GetAdjacentTiles(tile)) { // if (information.GetWitnesses().Contains(adjTile)) { // count++; // } //} // count how many adjacent witnesses the tile has foreach (SolverTile tile1 in allWitnesses) { if (tile.IsAdjacent(tile1)) { count++; } } // see if the witnessed tile fits any existing boxes bool found = false; foreach (Box box in this.boxes) { if (box.Fits(tile, count)) { box.Add(tile); boxLookup.Add(tile, box); // add this to the lookup found = true; break; } } // if not found create a new box and store it if (!found) { Box box = new Box(this.boxWitnesses, tile, uid++); this.boxes.Add(box); boxLookup.Add(tile, box); // add this to the lookup } } // calculate the min and max mines for each box foreach (Box box in this.boxes) { box.Calculate(this.minesLeft); //console.log("Box " + box.tiles[0].asText() + " has min mines = " + box.minMines + " and max mines = " + box.maxMines); } // Report how many boxes each witness is adjacent to foreach (BoxWitness boxWit in this.boxWitnesses) { information.Write("Witness " + boxWit.GetTile().AsText() + " is adjacent to " + boxWit.GetBoxes().Count + " boxes and has " + boxWit.GetMinesToFind() + " mines to find"); } }