Ejemplo n.º 1
0
        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);
            }
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
        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));
        }
Ejemplo n.º 5
0
Archivo: Day22.cs Proyecto: hagward/aoc
        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]);
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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());
        }
Ejemplo n.º 9
0
        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>());
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        //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
        }