Example #1
0
        public void Achievable()
        {
            var src = new Puzzle(new int[, ] {
                { 1, 2, 3 }, { 4, 5, 0 }
            });
            var dst = src.MoveSelf(Direction.Left).MoveSelf(Direction.Left).MoveSelf(Direction.Up);

            Assert.IsTrue(PuzzleUtility.Reachable(src, dst));
            Assert.IsFalse(PuzzleUtility.Reachable(src, new Puzzle(new int[, ] {
                { 1, 2, 3 }, { 5, 4, 0 }
            })));
        }
Example #2
0
        public static void Main()
        {
            //Read from console
            int    rowCount = ReadInteger("Row count: ");
            int    colCount = ReadInteger("Column count: ");
            Puzzle src      = ReadPuzzle(rowCount, colCount, "Source puzzle:\n");
            Puzzle dst      = ReadPuzzle(rowCount, colCount, "Destination puzzle:\n");

            //Check reachability before searching
            bool?reachable;

            try {
                reachable = PuzzleUtility.Reachable(src, dst);
            }
            catch (Exception ex) {
                Console.WriteLine(ex.Message);
                return;
            }
            if (reachable == false)
            {
                Console.WriteLine("Not reachable");
                return;
            }

            //Read the heuristic function to be used. Function name must be presented in Evaluator class
            string funcName;

            do
            {
                Console.Write("Heuristic function: ");
                funcName = Console.ReadLine();
            }while (typeof(Evaluator).GetField(funcName) == null);
            Search <Puzzle> .Evaluator estimate = (dynamic)(typeof(Evaluator).GetField(funcName).GetValue(null));

            //Start searching
            var search = new Search <Puzzle>(src, dst, PuzzleUtility.Transform);
            var cost   = search.AStar(estimate);

            if (!cost.HasValue)
            {
                Console.WriteLine("Not reachable");
                return;
            }
            Console.WriteLine($"Number of steps: {cost}");

            //Render the search tree to an image
            var graph        = search.SearchSource.BuildSearchTree(out var indexToNode);
            var stateToIndex = new Dictionary <Puzzle, int>();

            for (int i = 0; i < indexToNode.Length; ++i)
            {
                stateToIndex.Add(indexToNode[i].State, i);
            }
            graph.SetNodeAttribute(attr => {
                attr.Padding = 0.1;
                attr.Color   = Color.Black;
            });
            graph.FindNode(stateToIndex[search.Source].ToString()).Attr.Color      = Color.Red;
            graph.FindNode(stateToIndex[search.Destination].ToString()).Attr.Color = Color.Yellow;
            graph.PaintPath(search.Path.Select(puzzle => stateToIndex[puzzle].ToString()), Color.Cyan);
            string fileName = "search states.jpg";

            graph.RenderImage(fileName, height: search.SearchSource.Height * 40 * (rowCount + 2));
            Process.Start(new ProcessStartInfo()
            {
                FileName        = fileName,
                UseShellExecute = true
            });
        }
Example #3
0
 public void CountReversePairs()
 {
     Assert.AreEqual(0, PuzzleUtility.CountReversePairs(new int[] { 1, 2, 3, 4, 5 }));
     Assert.AreEqual(10, PuzzleUtility.CountReversePairs(new int[] { 5, 4, 3, 2, 1 }));
     Assert.AreEqual(13, PuzzleUtility.CountReversePairs(new int[] { 1, 9, 2, 6, 0, 8, 1, 7 }));
 }