/// <summary> /// Add all cases of the tests /// </summary> /// <returns></returns> private List <List <CandidateNode> > GetAllCasesTest() { CandidateNode root = SetCandidateNode(null, 0, BuildingTree()); root.AddPath(root, new List <CandidateNode>()); return(root.paths); }
private static void Start() { while (openList.Count > 0) { // algorithm's logic goes here // get the square with the lowest F score var lowest = openList.Min(l => l.F_Score); current = openList.First(l => Math.Abs(l.F_Score - lowest) < 0.05); // add the current square to the closed list closedList.Add(current); // remove it from the open list openList.Remove(current); //if (closedList.FirstOrDefault(l => l.Position.x == targetLoc.x && l.Position.y == targetLoc.y) != null) //Original if (closedList.FirstOrDefault(l => Math.Abs(l.Position.x - targetLoc.x) < 0.05 && Math.Abs(l.Position.y - targetLoc.y) < 0.05) != null) { break; } var adjacentNodes = GetWalkableAdjacentNodes(current.Position, GlobalGameManager.Instance.validMapNodes); g++; foreach (var adjacentSquare in adjacentNodes) { // if this adjacent square is already in the closed list, ignore it if (closedList.FirstOrDefault(l => l.Position == adjacentSquare.Position) != null) { continue; } // if it's not in the open list... if (openList.FirstOrDefault(l => l.Position == adjacentSquare.Position) == null) { // compute its score, set the parent adjacentSquare.G_Score = g; adjacentSquare.H_Score = ComputeHScore(adjacentSquare.Position, targetLoc); adjacentSquare.F_Score = adjacentSquare.G_Score + adjacentSquare.H_Score; adjacentSquare.Parent = current; // and add it to the open list openList.Insert(0, adjacentSquare); } else { // test if using the current G score makes the adjacent square's F score // lower, if yes update the parent because it means it's a better path if (g + adjacentSquare.H_Score < adjacentSquare.F_Score) { adjacentSquare.G_Score = g; adjacentSquare.F_Score = adjacentSquare.G_Score + adjacentSquare.H_Score; adjacentSquare.Parent = current; } } } }
private static void Init(Vector2 start, Vector2 destination) { current = null; startLoc = current; targetLoc = destination; openList = new List <CandidateNode>(); closedList = new List <CandidateNode>(); g = 0; openList.Add(startLoc); }
public List <CandidateNode> getNextCandidates() { List <int> skipFigurates = new List <int>(); foreach (int x in nums) { Pair p; figurateDict.TryGetValue(x, out p); skipFigurates.Add(p.whichFigurate); } List <CandidateNode> newNodes = new List <CandidateNode>(); foreach (int a in nums) { for (int x = 0; x < 6; ++x) { // skip figurates we already have if (!skipFigurates.Contains(x)) { for (int i = 0; i < figurates[x].Length; ++i) { if (isCyclicPair(a, figurates[x][i]) && a != figurates[x][i] && !figurateDict.ContainsKey(figurates[x][i])) { // create new node List <int> t = new List <int>(); foreach (int b in nums) { t.Add(b); } t.Add(figurates[x][i]); Dictionary <int, Pair> d = new Dictionary <int, Pair>(); Pair p; foreach (int key in figurateDict.Keys) { figurateDict.TryGetValue(key, out p); d.Add(key, p); } p = new Pair(); p.whichFigurate = x; p.index = i; d.Add(figurates[x][i], p); CandidateNode node = new CandidateNode(t, d); newNodes.Add(node); } } } } } return(newNodes); }
/// <summary> /// Set relation of all Nodes in the Tree /// </summary> /// <param name="value"></param> /// <param name="pos"></param> /// <param name="quizs"></param> /// <returns></returns> public CandidateNode SetCandidateNode(Candidate value, int pos, int[] quizs) { var child = new CandidateNode { Candi = value }; if (pos < quizs.Length) { foreach (var candi in QuestionSet.QuestionList.ElementAt(pos).Candidates) { child.Children.Add(SetCandidateNode(candi, pos + 1, quizs)); } } else { child.Children = null; } return(child); }
private void backTrack(CandidateNode node) { // the decision tree is going to be built using recursion if (node.isSolution()) { // we've found the answer and must print it! node.print(); return; } // if we haven't found the solution, then // we run our backtracking algorithm // Note that we don't prune any nodes early, // this algorithm is decidedly faster than the // original brute force algorithm that I'd been using // since this algorithm will eliminate certain choices // by virtue of the 'next candidate' function List <CandidateNode> nextCandidates = node.getNextCandidates(); foreach (CandidateNode next in nextCandidates) { backTrack(next); } }
public void getSolution() { for (int x = 0; x < 6; ++x) { for (int i = 0; i < figurates[x].Length; ++i) { List <int> start = new List <int>(); Dictionary <int, CandidateNode.Pair> figurateDict = new Dictionary <int, CandidateNode.Pair>(); CandidateNode.Pair p = new CandidateNode.Pair(); p.whichFigurate = x; p.index = i; start.Add(figurates[x][i]); figurateDict.Add(figurates[x][i], p); CandidateNode root = new CandidateNode(start, figurateDict); backTrack(root); } } // we need to traverse a decision tree.... we need a backtracking algorithm! // we use each possible starting point as a root node since it would seem // a bit arduous to code the recursive calls to handle both the regular // recursive parts as well as the initial special case that starts the process off // if(pieces.Count == 0) // { // pieces.Add(figurates[initialFigurate][initialFiguratePos]); // hasPiece[initialFigurate] = true; // thrownAway.Clear(); // throwAwayLevel = 0; // return true; // } // // if we have all pieces, then we must check to see // // if the entire set is cyclic // if (pieces.Count == 6) // { // List<int> t = new List<int>(); // foreach(int x in pieces) // { // t.Add(x); // } // // debug print // string s = ""; // foreach (int x in pieces) // s += x + " "; // Console.WriteLine("Answer: " + s); // if(oneArrangementIsCyclic(t)) // { // // we've found the answer and must print it! // string s2 = ""; // foreach (int x in pieces) // s2 += x + " "; // Console.WriteLine("Answer: " + s2); // return false; // } // else // { // // we haven't found the answer and must continue // // our search // goto NewSearch; // } // } // // if another piece cannot be found then we must // // reset this object, except we must be sure that // // we do not re-use the same starting piece, thus // // we begin the entire process again using the next // // figurate piece //NewSearch: // // we have something of a problem... // // when we cannot find another piece, it's quite // // possible that we need only backtrack one level // // and we will find the answer so that is what we must do // // remove the last element // // and add it to the list of items that // // are to be excluded from future piece // // searches // if(throwAwayLevel == 0) // { // // if the throwAwayLevel is zero then // // we can safely assume the value hasn't been // // set yet (since you must have something to throw away!) // throwAwayLevel = pieces.Count; // thrownAway.Clear(); // } // else // { // if(throwAwayLevel != pieces.Count) // { // // here we know that we've backtracked // // to a different number of pieces, and // // can free the thrown away numbers // throwAwayLevel = pieces.Count; // thrownAway.Clear(); // } // } // thrownAway.Add(pieces[pieces.Count - 1]); // pieces.Remove(pieces[pieces.Count - 1]); // // reset flags for which pieces this object holds // for (int i = 0; i < 6; ++i ) // { // hasPiece[i] = false; // } // foreach (int x in pieces) // { // for (int i = 0; i < 6; ++i) // { // for (int j = 0; j < figurates[i].Length; ++j) // { // if (figurates[i][j] == x) // { // hasPiece[i] = true; // break; // } // } // } // } // // we have a small problem since calling this function // // again will retrieve the piece that we threw away..... // // ... here it becomes a bit more clear that we need something // // of a backtracking algorithm.... // // I suppose we only need to track one level, that is if we // // start throwing away pieces when we have 6 of them, then // // we need only keep track of those thrown away as long as // // we are picking up a 6th piece..... I'm not sure if this // // reasoning makes sense but it's worth a shot! // // as it turns out.. NOPE ... the line of reasoning that // // I just attempted doesn't work! It's possible to re-enter // // a previous decision that was found to be fruitless causing // // a loop. You need a genuine backtracking algorithm to // // handle this problem appropriately // return findAnotherCyclicPiece(); }