static void TestCase4() { var random = new Random(); var myHeap = new FibonacciHeap<double>(int.MinValue, Comparer<double>.Default); var thirdPartyHeap = new FastPriorityQueue<FastPriorityQueueNode>(1000); for (var i = 0; i < 1000; i++) { if (random.Next(3) == 0 && thirdPartyHeap.Any()) { var myResult = myHeap.ExtractMin(); var otherResult = thirdPartyHeap.Dequeue(); Assert(myResult.Item1); Assert(Math.Abs(myResult.Item2 - otherResult.Priority) < double.Epsilon); } else { var value = random.NextDouble()*10; myHeap.Insert(value); thirdPartyHeap.Enqueue(new FastPriorityQueueNode(), value); } } while (thirdPartyHeap.Any()) { var myResult = myHeap.ExtractMin(); var otherResult = thirdPartyHeap.Dequeue(); Assert(myResult.Item1); Assert(Math.Abs(myResult.Item2 - otherResult.Priority) < double.Epsilon); } }
public Path GetShortestPath(string from, string to) { if (!_nodes.TryGetValue(from, out var fromNode)) { throw new Exception("from node not exist"); } if (!_nodes.TryGetValue(to, out var toNode)) { throw new Exception("to node not exist"); } var distances = new Dictionary <Node, int>(); foreach (var node in _nodes.Values) { distances.Add(node, int.MaxValue); } distances.Remove(fromNode); distances.Add(fromNode, 0); var visited = new HashSet <Node>(); var privouseNode = new Dictionary <Node, Node>(); var queue = new FastPriorityQueue <NodeEntry>(10); queue.Enqueue(node: new NodeEntry(fromNode, 0), priority: 0); while (queue.Any()) { var current = queue.Dequeue().GetNode(); visited.Add(current); foreach (var edge in current.GetEdges()) { var edgeTo = Get(edge.To()); if (visited.Contains(edgeTo)) { continue; } var newDistance = distances[current] + edge.GetWeight(); if (newDistance >= distances[edgeTo]) { continue; } distances.Remove(edgeTo); distances.Add(edgeTo, newDistance); if (privouseNode.TryGetValue(edgeTo, out var currentNode)) { privouseNode.Remove(edgeTo); } privouseNode.Add(edgeTo, current); queue.Enqueue(new NodeEntry(edgeTo, newDistance), newDistance); } } return(BuildPath(privouseNode, toNode)); }
private int GetShortestPathToTarget() { var visitedPoints = new Dictionary <Point, HashSet <EquipmentType> >(); var consideredPoints = new FastPriorityQueue <PointNode>((this._furthestPoint.X + 1) * (this._furthestPoint.Y + 1) * 3); consideredPoints.Enqueue(new PointNode { P = new Point(0, 0), Time = 0, Equipment = EquipmentType.Torch }, 0); while (consideredPoints.Any()) { var consideredPoint = consideredPoints.Dequeue(); if (!visitedPoints.ContainsKey(consideredPoint.P)) { visitedPoints.Add(consideredPoint.P, new HashSet <EquipmentType> { consideredPoint.Equipment }); } else { if (visitedPoints[consideredPoint.P].Contains(consideredPoint.Equipment)) { continue; } visitedPoints[consideredPoint.P].Add(consideredPoint.Equipment); } if (consideredPoint.P == this._targetPosition) { if (consideredPoint.Equipment == EquipmentType.Torch) { return(consideredPoint.Time); } var nextPoint = new PointNode { P = consideredPoint.P, Equipment = EquipmentType.Torch, Time = consideredPoint.Time + 7 }; consideredPoints.Enqueue(nextPoint, nextPoint.Time); } var neighbours = this.GetNextPoints(consideredPoint, visitedPoints); foreach (var neighbour in neighbours) { consideredPoints.Enqueue(neighbour, neighbour.Time); } } return(int.MaxValue); }
/// <summary> /// Finds a shortest path from the <paramref name="start"/> to the <paramref name="end"/>. /// It uses a Dijkstra's algorithm with a priority queue. /// </summary> string Solve(Map map, Cell start, Cell end) { var vertices = new FastPriorityQueue <Cell>(map.TotalMapSize); var distances = new Dictionary <Cell, float>(); var previous = new Dictionary <Cell, Cell>(); foreach (var cell in map.AllCells()) { if (!cell.Equals(start)) { distances[cell] = float.PositiveInfinity; previous[cell] = null; vertices.Enqueue(cell, float.PositiveInfinity); } } vertices.Enqueue(start, 0); distances[start] = 0; int oneTenth = map.TotalMapSize > 10 ? map.TotalMapSize / 10 : 1; while (vertices.Any()) { var u = vertices.Dequeue(); if (reportProgress && vertices.Count % oneTenth == 0) { Console.WriteLine($"Remaining nodes {vertices.Count}/{map.TotalMapSize}"); } foreach (var v in map.GetNeighbors(u)) { if (!vertices.Contains(v)) { continue; } var currentDistance = distances[v]; var newDistance = distances[u] + v.Difficulty; if (newDistance < currentDistance) { vertices.UpdatePriority(v, newDistance); distances[v] = newDistance; previous[v] = u; if (v.Equals(end)) { vertices.Clear(); break; } } } } return(GeneratePath(end, previous, map)); }
static int Dijkstra2(int[,] map) { var height = map.GetLength(0); var width = map.GetLength(1); var dist = new int[3, height, width]; for (var i = 0; i < 3; i++) { for (var j = 0; j < height; j++) { for (var k = 0; k < width; k++) { dist[i, j, k] = int.MaxValue; } } } var q = new FastPriorityQueue <Vertex>(10000); q.Enqueue(new Vertex(0, 0, 1), 0); while (q.Any()) { var u = q.Dequeue(); var y = u.Y; var x = u.X; var t = u.Type; var d = (int)u.Priority; if (x < 0 || x >= width || y < 0 || y >= height || t == map[y, x] || d >= dist[t, y, x]) { continue; } Console.WriteLine($"Visiting {y},{x},{t},{d}"); var oth = (t + 1) % 3; if (oth == map[y, x]) { oth = (oth + 1) % 3; } dist[t, y, x] = d; q.Enqueue(new Vertex(x, y, oth), d + 7); q.Enqueue(new Vertex(x + 1, y, t), d + 1); q.Enqueue(new Vertex(x - 1, y, t), d + 1); q.Enqueue(new Vertex(x, y + 1, t), d + 1); q.Enqueue(new Vertex(x, y - 1, t), d + 1); } return(dist[1, height - 1, width - 1]); }
static void TestCase2() { var random = new Random(); var myHeap = new BinomialHeap<double>(double.MinValue, Comparer<double>.Default); var otherQueue = new FastPriorityQueue<FastPriorityQueueNode>(10000); for (var i = 0; i < 10000; i++) { if (otherQueue.Any() && random.Next(3) == 0) { Assert(Math.Abs(myHeap.ExtractMin().Item2 - otherQueue.Dequeue().Priority) < double.Epsilon); } else { var newValue = random.NextDouble()*10; myHeap.Insert(newValue); otherQueue.Enqueue(new FastPriorityQueueNode(), newValue); } } while(otherQueue.Any()) Assert(Math.Abs(myHeap.ExtractMin().Item2 - otherQueue.Dequeue().Priority) < double.Epsilon); }
private Coordinate PrioritySearch(Bot[] bots, Coordinate start, int resolution, int searchSpace) { var avgX = (int)bots.Average(b => b.Coord.X); var avgY = (int)bots.Average(b => b.Coord.Y); var avgZ = (int)bots.Average(b => b.Coord.Z); var zero = new Coordinate(0, 0, 0); var queue = new FastPriorityQueue <Coordinate>(100000000); queue.Enqueue(start, 0); var seen = new HashSet <string>(); seen.Add(start.Hash); var searched = 0; var best = 0; var bestManhatten = 0; var bestCoordinate = zero; while (queue.Any() && ++searched <= searchSpace) { var current = queue.Dequeue(); var inRange = BotsInRangeOf(current, bots); if (inRange > best) { best = inRange; bestManhatten = ManhattenDistance3D(current, zero); bestCoordinate = current; Console.WriteLine($"Best in range: {best} at {bestCoordinate}. Distance to Zero: {bestManhatten}"); } else if (inRange == best) { var md = ManhattenDistance3D(current, zero); if (md < bestManhatten) { bestManhatten = md; bestCoordinate = current; Console.WriteLine($"Best in range: {best} at {bestCoordinate}. Distance to Zero: {bestManhatten}"); } } CheckSeenToQueue(queue, seen, bots, current.X - resolution, current.Y, current.Z); CheckSeenToQueue(queue, seen, bots, current.X + resolution, current.Y, current.Z); CheckSeenToQueue(queue, seen, bots, current.X, current.Y - resolution, current.Z); CheckSeenToQueue(queue, seen, bots, current.X, current.Y + resolution, current.Z); CheckSeenToQueue(queue, seen, bots, current.X, current.Y, current.Z - resolution); CheckSeenToQueue(queue, seen, bots, current.X, current.Y, current.Z + resolution); } return(bestCoordinate); }
private int Search(ref Dictionary <string, Point> map, int targetX, int targetY) { var startState = new State(map[$"0,0"], Equipment.Torch, 0); var searchQueue = new FastPriorityQueue <State>(targetX * 3 * targetY * 3); var foundTimes = new List <int>(); searchQueue.Enqueue(startState, 0); var seenStates = new Dictionary <string, State>() { [startState.Hash] = startState }; while (searchQueue.Any()) { var currentState = searchQueue.Dequeue(); if (IsTargetState(currentState, targetX, targetY)) { //Console.WriteLine($"Found in {currentState.TotalMinutes} minutes"); foundTimes.Add(currentState.TotalMinutes); continue; } //Print(map, currentState.Location.X, currentState.Location.Y, currentState.Wielding); if (currentState.Location.Y - 1 >= 0) { var north = new State(currentState.Location.N, currentState.Wielding, currentState.TotalMinutes + 1); if (ToolIsOk(currentState.Wielding, north.Location.Type)) { if (!seenStates.ContainsKey(north.Hash) || seenStates[north.Hash].TotalMinutes > north.TotalMinutes) { searchQueue.Enqueue(north, north.TotalMinutes); seenStates[north.Hash] = north; } } } if (currentState.Location.X - 1 >= 0) { var west = new State(currentState.Location.W, currentState.Wielding, currentState.TotalMinutes + 1); if (ToolIsOk(currentState.Wielding, west.Location.Type)) { if (!seenStates.ContainsKey(west.Hash) || seenStates[west.Hash].TotalMinutes > west.TotalMinutes) { searchQueue.Enqueue(west, west.TotalMinutes); seenStates[west.Hash] = west; } } } if (currentState.Location.Y <= targetY * 3) { var south = new State(currentState.Location.S, currentState.Wielding, currentState.TotalMinutes + 1); if (ToolIsOk(currentState.Wielding, south.Location.Type)) { if (!seenStates.ContainsKey(south.Hash) || seenStates[south.Hash].TotalMinutes > south.TotalMinutes) { searchQueue.Enqueue(south, south.TotalMinutes); seenStates[south.Hash] = south; } } } if (currentState.Location.X <= targetX * 3) { var east = new State(currentState.Location.E, currentState.Wielding, currentState.TotalMinutes + 1); if (ToolIsOk(currentState.Wielding, east.Location.Type)) { if (!seenStates.ContainsKey(east.Hash) || seenStates[east.Hash].TotalMinutes > east.TotalMinutes) { searchQueue.Enqueue(east, east.TotalMinutes); seenStates[east.Hash] = east; } } } if (ToolIsOk(Equipment.Gear, currentState.Location.Type)) { var wieldGear = new State(currentState.Location, Equipment.Gear, currentState.TotalMinutes + 7); if (!seenStates.ContainsKey(wieldGear.Hash) || seenStates[wieldGear.Hash].TotalMinutes > wieldGear.TotalMinutes) { searchQueue.Enqueue(wieldGear, wieldGear.TotalMinutes); seenStates[wieldGear.Hash] = wieldGear; } } if (ToolIsOk(Equipment.Neither, currentState.Location.Type)) { var wieldNeither = new State(currentState.Location, Equipment.Neither, currentState.TotalMinutes + 7); if (!seenStates.ContainsKey(wieldNeither.Hash) || seenStates[wieldNeither.Hash].TotalMinutes > wieldNeither.TotalMinutes) { searchQueue.Enqueue(wieldNeither, wieldNeither.TotalMinutes); seenStates[wieldNeither.Hash] = wieldNeither; } } if (ToolIsOk(Equipment.Torch, currentState.Location.Type)) { var wieldTorch = new State(currentState.Location, Equipment.Torch, currentState.TotalMinutes + 7); if (!seenStates.ContainsKey(wieldTorch.Hash) || seenStates[wieldTorch.Hash].TotalMinutes > wieldTorch.TotalMinutes) { searchQueue.Enqueue(wieldTorch, wieldTorch.TotalMinutes); seenStates[wieldTorch.Hash] = wieldTorch; } } } return(foundTimes.Min()); }
public static IEnumerable <TNode> FindPath( TNode start, TNode end, Func <TNode, IEnumerable <TNode> > getNeighbors, Func <TNode, TNode, float> getCost, Func <TNode, TNode, float> getHeuristicCost, IEqualityComparer <TNode> equalityComparer, int maxNodes = 1024) { var openList = new FastPriorityQueue <PriorityNode>(maxNodes); var closedList = new HashSet <PriorityNode>(new PriorityNodeEqualityComparer(equalityComparer)); var startNode = new PriorityNode(start, getHeuristicCost(start, end)); openList.Enqueue(startNode, startNode.Priority); while (openList.Any()) { var currentNode = openList.Dequeue(); if (equalityComparer.Equals(currentNode.Node, end)) { var path = new List <TNode>(); while (currentNode.Parent != null) { path.Add(currentNode.Node); currentNode = currentNode.Parent; } return(((IEnumerable <TNode>)path).Reverse()); } closedList.Add(currentNode); foreach (var neighbor in getNeighbors(currentNode.Node)) { var cost = currentNode.RealCost + getCost(currentNode.Node, neighbor); if (float.IsInfinity(cost)) { continue; } var openListNeighbor = openList.FirstOrDefault(x => equalityComparer.Equals(x.Node, neighbor)); if (openListNeighbor != null && cost < openListNeighbor.RealCost) { openList.Remove(openListNeighbor); openListNeighbor = null; } var closedListNeighbor = closedList.FirstOrDefault(x => equalityComparer.Equals(x.Node, neighbor)); if (closedListNeighbor != null && cost < closedListNeighbor.RealCost) { closedList.Remove(closedListNeighbor); closedListNeighbor = null; } if (openListNeighbor == null && closedListNeighbor == null) { if (openList.Count == openList.MaxSize) { continue; } var realCost = currentNode.RealCost + cost; var heuristicCost = getHeuristicCost(neighbor, end); var newNode = new PriorityNode(currentNode, neighbor, realCost, heuristicCost); openList.Enqueue(newNode, newNode.Priority); } } } return(new List <TNode>()); }
public int[] Work(bool print = true, int startIndex = 0) { int NumberOfNodes = Graph.ListOfNodes.Count; var queue = new FastPriorityQueue <Node>(100 * 1000); Node u; int du; int dv; int wuv; int[] d = new int[NumberOfNodes]; for (int i = 0; i < NumberOfNodes; i++) { d[i] = Int32.MaxValue / 10; } if (startIndex + 1 > NumberOfNodes) { startIndex = 0; } d[startIndex] = 0; for (int i = 0; i < NumberOfNodes; i++) { queue.Enqueue(Graph.GetNode(i), 0); } while (queue.Any()) // while queue is not empty { u = queue.Dequeue(); foreach (var v in u.ListOfEdges) { du = d[u.Id]; dv = d[v.Target.Id]; wuv = v.Weight; if (du + wuv < dv) { d[v.Target.Id] = du + wuv; if (queue.Contains(v.Target)) { queue.UpdatePriority(v.Target, d[v.Target.Id]); } else { queue.Enqueue(v.Target, d[v.Target.Id]); } } } } if (print) { for (int i = 0; i < NumberOfNodes; i++) { Console.WriteLine("Id: {0}, distance: {1}", i, d[i]); } } return(d); }
public List <T> Around(IKDBush <T> index, double lng, double lat, int?maxResults = null, double?maxDistance = null, Predicate <T> predicate = null) { var result = new List <T>(); if (maxResults == null) { maxResults = int.MaxValue; } if (maxDistance == null) { maxDistance = double.MaxValue; } // maxDistance = double.PositiveInfinity; var cosLat = Math.Cos(lat * rad); var sinLat = Math.Sin(lat * rad); // a distance-sorted priority queue that will contain both points and kd-tree nodes var pointsLength = index.ids.Length; FastPriorityQueue <Node <T> > q = new FastPriorityQueue <Node <T> >(pointsLength); // an object that represents the top kd-tree node (the whole Earth) var node = new Node <T> { left = 0, // left index in the kd-tree array right = index.ids.Length - 1, // right index axis = 0, // 0 for longitude axis and 1 for latitude axis dist = 0, // will hold the lower bound of children's distances to the query point minLng = -180, // bounding box of the node minLat = -90, maxLng = 180, maxLat = 90 }; while (node != null) { var right = node.right; var left = node.left; T item; if (right - left <= index.nodeSize) { // leaf node // add all points of the leaf node to the queue for (var i = left; i <= right; i++) { item = index.points[index.ids[i]]; if (predicate == null || predicate(item)) { var dist = GreatCircleDist(lng, lat, index.coords[2 * i], index.coords[2 * i + 1], cosLat, sinLat); q.Enqueue(new Node <T> { item = item, dist = dist }, (float)dist); } } } else { // not a leaf node (has child nodes) var m = (left + right) >> 1; // middle index var midLng = index.coords[2 * m]; var midLat = index.coords[2 * m + 1]; // add middle point to the queue item = index.points[index.ids[m]]; if (predicate == null || predicate(item)) { var dist = GreatCircleDist(lng, lat, midLng, midLat, cosLat, sinLat); q.Enqueue(new Node <T> { item = item, dist = dist }, (float)dist); } var nextAxis = (node.axis + 1) % 2; // first half of the node var leftNode = new Node <T> { left = left, right = m - 1, axis = nextAxis, minLng = node.minLng, minLat = node.minLat, maxLng = node.axis == 0 ? midLng : node.maxLng, maxLat = node.axis == 1 ? midLat : node.maxLat, dist = 0 }; // second half of the node var rightNode = new Node <T> { left = m + 1, right = right, axis = nextAxis, minLng = node.axis == 0 ? midLng : node.minLng, minLat = node.axis == 1 ? midLat : node.minLat, maxLng = node.maxLng, maxLat = node.maxLat, dist = 0 }; leftNode.dist = BoxDist(lng, lat, leftNode, cosLat, sinLat); rightNode.dist = BoxDist(lng, lat, rightNode, cosLat, sinLat); // add child nodes to the queue q.Enqueue(leftNode, (float)leftNode.dist); q.Enqueue(rightNode, (float)rightNode.dist); } // fetch closest points from the queue; they're guaranteed to be closer // than all remaining points (both individual and those in kd-tree nodes), // since each node's distance is a lower bound of distances to its children while (q.Any() && q.First.item != null) { var candidate = q.Dequeue(); if (candidate.dist > maxDistance) { return(result); } result.Add(candidate.item); if (result.Count == maxResults) { return(result); } } // the next closest kd-tree node node = q.Count > 0 ? q.Dequeue() : null; } return(result); }
private Point Move(Person person, Point pos) { // Start by adding p to visited var visited = new HashSet <Point> { pos }; var nodes = new FastPriorityQueue <VisitedNode>(64); var adjacentNodes = GetAdjacentNodes(pos); foreach (var node in adjacentNodes) { node.InitialVel = new Point(node.Pos.X - pos.X, node.Pos.Y - pos.Y); nodes.Enqueue(node, node.GetPriority()); visited.Add(node.Pos); } while (nodes.Any()) { var nextNodes = new FastPriorityQueue <VisitedNode>(64); while (nodes.Any()) { var node = nodes.Dequeue(); visited.Add(node.Pos); if (this._people.TryGetValue(node.Pos, out var enemy) && enemy.GetType() != person.GetType()) { // Enemy in this pos - stop searching var newPos = new Point(pos.X, pos.Y); newPos.Offset(node.InitialVel); return(newPos); } // Non-empty square - cannot move here, do nothing if (this._people.ContainsKey(node.Pos) || !this._emptySquares.Contains(node.Pos)) { continue; } // This square is empty - add all adjacent non-visited nodes adjacentNodes = GetAdjacentNodes(node.Pos); foreach (var adjNode in adjacentNodes) { if (!visited.Contains(adjNode.Pos)) { adjNode.InitialVel = node.InitialVel; visited.Add(adjNode.Pos); nextNodes.Enqueue(adjNode, adjNode.GetPriority()); } else if (nextNodes.Contains(adjNode)) { var queueNode = nextNodes.Single(nds => nds.Equals(adjNode)); if (adjNode.InitialVel.Y < queueNode.InitialVel.Y) { queueNode.InitialVel = adjNode.InitialVel; } else if (adjNode.InitialVel.Y == queueNode.InitialVel.Y && adjNode.InitialVel.X < queueNode.InitialVel.X) { queueNode.InitialVel = adjNode.InitialVel; } } } } nodes = nextNodes; } return(pos); }
//used to check if user input would create a final board that is consistent. Uses a priority queue to implement minimal remaining value algorithm //on the list of squares that make up the board. Guesses when it comes to a square that cant be reduced to only one possible value. If a square has no possible //values and the guessStack is empty then the state is consistent and an error that corresponds to the type of consistency error is returned. Otherwise if the board //can be completed in a valid state then null is returned. public Error checkConsistency(Square temp) { FastPriorityQueue <Square> testQueue = new FastPriorityQueue <Square>(81); //used for mrv algorithm Stack <unCert> guessStack = new Stack <unCert>(); //stack that keeps track of guessed states foreach (Square sq in this.Board) //populate priority queue with squares from the board { sq.genPossibles(this.Board); testQueue.Enqueue(sq, sq.Heur); } while (testQueue.Any()) //loop until the queue is empty { if (testQueue.First.Given || temp == testQueue.First || testQueue.First.Solved) //if the square has been solved, is a given, or is user entered remove the sqaure from the queue { testQueue.Dequeue(); } else if (testQueue.First.Heur == 1)//if the square only has one possible value set it to that value and declare it as solved, remove it from the queue and update the board, and the domain of the squares that that square constrains { testQueue.First.Number = testQueue.First.PossibleVals[0]; testQueue.First.Solved = true; updateBoard(testQueue.First); testQueue.Dequeue(); for (int i = 0; i < testQueue.Count; i++)//update the priority of the square in the queue based on the new number in the board { testQueue.UpdatePriority(testQueue.ElementAt(i), testQueue.ElementAt(i).Heur); } } else if (testQueue.First.Heur == 0) //a square has no possible values so the current state is inconsistent( as proposed by ac3 algorithm) { if (guessStack.Count == 0) //no guesses have been made so the board is incosistent due to the user input so display an error { Error err = new Error(Error.errType.single, temp); return(err); } else//otherwise a guess caused an inconsistency so a correction needs to be made { foreach (int x in guessStack.First().Guessed)//restrict the domain based on the guesses that have already been made, since those are wrong as they caused an inconsistency { guessStack.First().Gsquare.PossibleVals.Remove(x); } if (guessStack.First().Gsquare.PossibleVals.Count == 0)//if there are no more values left in the guessed squares domain that means the bad guess occured on a previous square, pop this state and check the lower guess in the stack { guessStack.Pop(); guessStack.First().Prev.board[guessStack.First().Gsquare.Y * 9 + guessStack.First().Gsquare.X].Solved = false; guessStack.First().Prev.board[guessStack.First().Gsquare.Y * 9 + guessStack.First().Gsquare.X].Heur = -1; continue; } if (guessStack.Count != 0)//as long as the stack isnt empty update the guessed square to be false again and set its heur value at -1 so it will be at the front of the queue, then reset the board to the backed up version { guessStack.First().Prev.board[guessStack.First().Gsquare.Y * 9 + guessStack.First().Gsquare.X].Solved = false; guessStack.First().Prev.board[guessStack.First().Gsquare.Y * 9 + guessStack.First().Gsquare.X].Heur = -1; foreach (Square sq in guessStack.First().Prev.board) { this.modBoard(sq); } this.Placed = guessStack.First().Prev.Placed; testQueue.Clear(); foreach (Square sq in this.board) { testQueue.Enqueue(sq, sq.Heur); } } } } else if (testQueue.First.Heur > 1 || testQueue.First.Heur == -1) //a guess needs to be made as it has multiple possible values { if (guessStack.Count == 0 || guessStack.First().Gsquare != testQueue.First()) //if the guess stack is empty or the guess at the top of the stack doesnt correspond to the current square make a new guess object { unCert tempCert = new unCert(); int guessing = 0; tempCert.Gsquare = testQueue.First.deepCopy(); tempCert.Prev = this.deepCopy(); guessing = testQueue.First.PossibleVals[0]; testQueue.First.PossibleVals.Remove(0); testQueue.First.Solved = true; testQueue.First.Number = guessing; tempCert.Guessed.Add(guessing); guessStack.Push(tempCert); updateBoard(testQueue.First); testQueue.Dequeue(); for (int i = 0; i < testQueue.Count; i++) { testQueue.UpdatePriority(testQueue.ElementAt(i), testQueue.ElementAt(i).Heur); } } else//otherwise modify the guess object at the top of the guess stack and make a new guess, and update the board based on the new guess. { guessStack.First().Gsquare = testQueue.First().deepCopy(); guessStack.First().Prev = this.deepCopy(); foreach (int x in guessStack.First().Guessed) { testQueue.First.PossibleVals.Remove(x); } if (testQueue.First.PossibleVals.Count == 0) { continue; } testQueue.First.Solved = true; int guessing = testQueue.First.PossibleVals[0]; testQueue.First.Number = guessing; guessStack.First().Guessed.Add(guessing); updateBoard(testQueue.First); testQueue.Dequeue(); for (int i = 0; i < testQueue.Count; i++) { testQueue.UpdatePriority(testQueue.ElementAt(i), testQueue.ElementAt(i).Heur); } } } } return(null);//no errors encountered, state is consistent }