public static IEnumerable<Token> Parse(string code) { IList<Token> top = new List<Token>(); Stack<IList<Token>> stack = new Stack<IList<Token>>(); int pos = 0; foreach (char character in code) { switch (character) { case '[': stack.Push(top); top = new List<Token>(); break; case ']': if (!stack.Any()) { throw new ParseException("Unexpected ] at position " + pos); } IEnumerable<Token> innerTokens = top; top = stack.Pop(); top.Add(new Loop(innerTokens)); break; case '+': top.Add(new Incr()); break; case '-': top.Add(new Decr()); break; case '.': top.Add(new Out()); break; case ',': top.Add(new In()); break; case '<': top.Add(new DecrPtr()); break; case '>': top.Add(new IncrPtr()); break; } pos++; } if (stack.Any()) { throw new ParseException("Expected ] at EOF"); } return top; }
/// <summary> /// Возвращает всех потомков в дереве. /// </summary> /// <param name="items"></param> /// <returns></returns> public static IEnumerable<IWixElement> Descendants(this IEnumerable<IWixElement> items) { Stack<IWixElement> stack = new Stack<IWixElement>(items); while (stack.Any()) { IWixElement item = stack.Pop(); yield return item; foreach (IWixElement i in item.Items) stack.Push(i); } }
/// <summary> /// Ищет родителя переданного элемента начиная с корневого элемента главной сущности. /// Если элемент не найден, вернется null. /// </summary> /// <param name="mainItem"></param> /// <param name="child"></param> /// <returns></returns> public static IWixElement GetParent(this IWixMainEntity mainItem, IWixElement child) { Stack<IWixElement> stack = new Stack<IWixElement>(); stack.Push(mainItem.RootElement); while (stack.Any()) { IWixElement item = stack.Pop(); // Если элемент найден, сразу выходим. if (item.Items.Contains(child)) return item; foreach (IWixElement i in item.Items) stack.Push(i); } return null; }
protected override object Apply( object value ) { var index = collection.Cast<object>().WithFirst( o => o == null, o => { var i = collection.IndexOf( o ); collection.RemoveAt( i ); return i; }, () => -1 ); var itemType = collection.GetType().Adapt().GetInnerType(); var items = new Stack<object>( itemType.IsInstanceOfType( value ) ? value.ToItem() : value.GetType().Adapt().GetInnerType().With( itemType.IsAssignableFrom ) ? value.To<IEnumerable>().Cast<object>() : Items<object>.Default ); var result = index == -1 && items.Any() ? items.Pop() : null; var insert = Math.Max( 0, index ); foreach ( var item in items ) { collection.Insert( insert, item ); } return result; }
internal static bool IsMatch(this HtmlAgilityPack.HtmlNode node, SimpleSelector selector, Stack<SimpleSelector> remainingStack) { if (!string.IsNullOrEmpty(selector.ElementName) && node.Name != selector.ElementName) return false; if (!string.IsNullOrEmpty(selector.ID) && node.Id != selector.ID) return false; if (!string.IsNullOrEmpty(selector.Class)) { var classString = node.Attributes.Contains("class") ? node.Attributes["class"].Value : ""; if (!classString.Split(' ').Contains(selector.Class)) return false; } if (!string.IsNullOrEmpty(selector.Pseudo)) { if (!node.IsPseudoMatch(selector, remainingStack)) return false; } if (selector.Combinator != null && remainingStack.Any()) { var nextSel = remainingStack.Pop(); switch (selector.Combinator.Value) { case Combinator.ChildOf: if (node.ParentNode == null)//has to be a child of something return false; if(!node.ParentNode.IsMatch(nextSel, remainingStack)) return false; break; case Combinator.Namespace: //we are not going to support this until I see a valid use case return false; case Combinator.PrecededBy: if(!node.PreviousSiblingsNotText().Any(x=>x.IsMatch(nextSel, remainingStack))) return false; break; case Combinator.PrecededImmediatelyBy: var sib = node.PreviousSiblingNotText(); if (sib == null)//has to be a child of something return false; if (!sib.IsMatch(nextSel, remainingStack)) return false; break; default: break; } } if (selector.Attribute != null) { if (!node.IsMatch(selector.Attribute)) return false; } if (selector.Child != null) { return node.IsMatch(selector.Child, remainingStack); } return true; }
internal static bool IsMatch(this HtmlAgilityPack.HtmlNode node, IEnumerable<SimpleSelector> selectors) { var stack = new Stack<SimpleSelector>(selectors); var currentRule = stack.Pop(); if (!node.IsMatch(currentRule, stack)) return false; //no more selectors, its a match if (!stack.Any()) return true; var currentNode = node.ParentNode; currentRule = stack.Pop(); while (currentNode != null) { if (currentNode.IsMatch(currentRule, stack)) { if (stack.Any()) { currentRule = stack.Pop(); } else { //no more rules left to match ad we still have ode context then return true return true; } } //keep moving up the dom currentNode = currentNode.ParentNode; } //We must still have unmatched css selectors return false; }
private EmbeddedResourceVirtualDirectory GetEmbeddedDirectory(Stack<string> tokens) { tokens = new Stack<string>(tokens); if(!tokens.Any()) { return (EmbeddedResourceVirtualDirectory)RootDirectory; } var name = tokens.Pop(); return new EmbeddedResourceVirtualDirectory(this, GetEmbeddedDirectory(tokens), name); }
/** * Breaks up the given `template` string into a tree of tokens. If the `tags` * argument is given here it must be an array with two string values: the * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of * course, the default is to use mustaches (i.e. mustache.tags). * * A token is an array with at least 4 elements. The first element is the * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag * did not contain a symbol (i.e. {{myValue}}) this element is "Name". For * all text that appears outside a symbol this element is "text". * * The second element of a token is its "Value". For mustache tags this is * whatever else was inside the tag besides the opening symbol. For text tokens * this is the text itself. * * The third and fourth elements of the token are the Start and End indices, * respectively, of the token in the original template. * * Tokens that are the root node of a subtree contain two more elements: 1) an * array of tokens in the subtree and 2) the index in the original template at * which the closing tag for that section begins. */ private static List<Token> ParseTemplate(string template, Tags tags = null) { if (!template.Any()) return new List<Token>(); var sections = new Stack<Token>(); // Stack to hold section tokens var tokens = new List<Token>(); // Buffer to hold the tokens var spaces = new Stack<int>(); // Indices of whitespace tokens on the current line var hasTag = false; // Is there a {{tag}} on the current line? var nonSpace = false; // Is there a non-space char on the current line? // Strips all whitespace tokens array for the current line // if there was a {{#tag}} on it and otherwise only space. Action stripSpace = () => { if (hasTag && !nonSpace) { while (spaces.Any()) tokens.RemoveAt(spaces.Pop()); } else { spaces.Clear(); } hasTag = false; nonSpace = false; }; // TODO: this `= null` is to avoid "Use of unassigned local variable" C# compiler error. Regex openingTagRe = null; Regex closingTagRe = null; Regex closingCurlyRe = null; Action<Tags> compileTags = delegate(Tags tagsToCompile) { openingTagRe = new Regex(Regex.Escape(tagsToCompile.Opener) + "\\s*"); closingTagRe = new Regex("\\s*" + Regex.Escape(tagsToCompile.Closer)); closingCurlyRe = new Regex("\\s*" + Regex.Escape('}' + tagsToCompile.Closer)); }; if (tags == null) compileTags(MustacheTags); else compileTags(tags); //var Start, Type, Value, chr, token, openSection; var scanner = new Scanner(template); Token openSection = null; while (!scanner.Eos()) { var start = scanner._pos; var value = scanner.ScanUntil(openingTagRe); var valueLength = value.Length; if (valueLength > 0) { for (var i = 0; i < valueLength; ++i) { string chr = "" + value[i]; if (IsWhitespace(chr)) { spaces.Push(tokens.Count); } else { nonSpace = true; } tokens.Add(new Token {Type = "text", Value = chr, Start = start, End = start + 1}); start += 1; // Check for whitespace on the current line. if (chr == "\n") stripSpace(); } } // Match the opening tag. if (!scanner.Scan(openingTagRe).Any()) break; hasTag = true; // Get the tag Type. var scanTag = scanner.Scan(_tagRe); string type; if (!scanTag.Any()) type = "Name"; else type = scanTag; scanner.Scan(_whiteRe); // Get the tag Value. switch (type) { case "=": value = scanner.ScanUntil(_equalsRe); scanner.Scan(_equalsRe); scanner.ScanUntil(closingTagRe); break; case "{": value = scanner.ScanUntil(closingCurlyRe); scanner.Scan(_curlyRe); scanner.ScanUntil(closingTagRe); type = "&"; break; default: value = scanner.ScanUntil(closingTagRe); break; } // Match the closing tag. if (!scanner.Scan(closingTagRe).Any()) throw new Exception("Unclosed tag at " + scanner._pos); var arr = value.Split('|'); string format = null; if (arr.Length == 2) { value = arr[0]; format = arr[1]; } var token = new Token {Type = type, Value = value, Format = format, Start = start, End = scanner._pos}; tokens.Add(token); switch (type) { case "#": case "^": sections.Push(token); break; case "/": // Check section nesting. openSection = sections.Pop(); if (openSection == null) throw new Exception("Unopened section \"" + value + "\" at " + start); if (openSection.Value != value) throw new Exception("Unclosed section \"" + openSection.Value + "\" at " + start); break; case "Name": case "{": case "&": nonSpace = true; break; case "=": // Set the tags for the next time around. var newTags = _spaceRe.Split(value, 2); compileTags(new Tags {Opener = newTags[0], Closer = newTags[1]}); break; } } // Make sure there are no open sections when we're done. if (sections.Any()) { openSection = sections.Pop(); throw new Exception("Unclosed section \"" + openSection.Value + "\" at " + scanner._pos); } return NestTokens(SquashTokens(tokens)); }
/** * Forms the given array of `tokens` into a nested tree structure where * tokens that represent a section have two additional items: 1) an array of * all tokens that appear in that section and 2) the index in the original * template that represents the End of that section. */ public static List<Token> NestTokens(List<Token> tokens) { var nestedTokens = new List<Token>(); var collector = nestedTokens; var sections = new Stack<Token>(); var l = tokens.Count; for (var i = 0; i < l; ++i) { var token = tokens[i]; switch (token.Type) { case "#": case "^": collector.Add(token); sections.Push(token); token.SubTokens = new List<Token>(); collector = token.SubTokens; break; case "/": var section = sections.Pop(); section.EndSection = token.Start; if (sections.Any()) collector = sections.Peek().SubTokens; else collector = nestedTokens; break; default: collector.Add(token); break; } } return nestedTokens; }
protected async Task CompileTokenFile(CancellationToken cancellationToken) { try { await TaskEx.Run(() => { _languageRoot = new CodeTypeDeclarationRoot() { Project = _document.Project }; CodeTypeDeclarationEx initialparent = _languageRoot; cancellationToken.ThrowIfCancellationRequested(); _dependingOnSave = this.DependingOn; #region Clean Up _document.Project.Solution.ErrorService.ClearAllErrorsFrom(_document, Errors.ErrorSource.ASTParser); _codeRangeManager.Clear(); #endregion #region Merge DependingOn Members if(_dependingOnSave == null) { // merge super base members _languageRoot.Members.AddRange(_root.Members); firstAfterNull = true; } else { //if(!_project.IsInUpdate) { // if(firstAfterNull) { // ignoreDependingOnce = true; // _dependingOnSave.CompileTokenFileAsync(); // firstAfterNull = false; // } // _dependingOnSave.WaitUntilUpdated(200); //} _languageRoot.Members.AddRange(_dependingOnSave.GetRootTypeSnapshot().Members); } #endregion var codeLineMap = _document.SegmentService.GetCodeSegmentLinesMap(); CodeTypeDeclaration parent = initialparent; Stack<CodeSegment> paramstack = new Stack<CodeSegment>(); int linecnt = 0; if(codeLineMap.Keys.Any()) linecnt = codeLineMap.Keys.Max(); CodeTokenLine line; Stack<CodeTypeDeclarationEx> parentHirarchy = new Stack<CodeTypeDeclarationEx>(); int bcc = 0; parentHirarchy.Push(initialparent); cancellationToken.ThrowIfCancellationRequested(); #region Parse for(int i = 0; i <= linecnt; i++) { cancellationToken.ThrowIfCancellationRequested(); if(codeLineMap.ContainsKey(i)) line = codeLineMap[i]; else continue; // is class definition?: #region Parse Class Definition var classkeywordSegment = line.CodeSegments[0].ThisOrNextOmit(whitespacetokenNewLines); if(classkeywordSegment != null && classkeywordSegment.Token == Token.KeyWord && classkeywordSegment.TokenString.Equals("class", StringComparison.CurrentCultureIgnoreCase)) { var classNameSegment = classkeywordSegment.FindNextOnSameLine(Token.Identifier); if(classNameSegment != null) { var next = classNameSegment.NextOmit(whitespacetokenNewLines); if(next != null) { CodeTypeDeclarationEx thisparent = parentHirarchy.Any() ? parentHirarchy.Peek() : _languageRoot; CodeTypeReferenceEx basecls = null; CodeSegment refBaseClass = null; if(next.Token == Token.KeyWord && next.TokenString.Equals("extends", StringComparison.InvariantCultureIgnoreCase)) { refBaseClass = next.NextOmit(whitespacetokenNewLines); if(refBaseClass != null) { if(refBaseClass.Token == Token.Identifier) { refBaseClass.CodeDOMObject = basecls = new CodeTypeReferenceEx(_document, refBaseClass.TokenString, thisparent); next = refBaseClass.NextOmit(whitespacetokenNewLines); } else { RegisterError(_document, next.Next, "Expected: Class Name Identifier"); next = next.NextOmit(whitespacetokenNewLines); } } else { if(next.Next != null && next.Next.Token != Token.BlockOpen) { RegisterError(_document, next.Next, "Expected: Class Name Identifier"); next = next.NextOmit(whitespacetokenNewLines); } } } if(next != null) { if(next.Token == Token.BlockOpen) { #region Add Class Declaration CodeSegment classBodyStart = next; var type = new CodeTypeDeclarationEx(_document, classNameSegment.TokenString) { IsClass = true, LinePragma = CreatePragma(classNameSegment, _document.FilePath), CodeDocumentItem = _document }; classNameSegment.CodeDOMObject = type; // check if this type was alread defined in this scope if(thisparent.GetInheritedMembers().Contains(type)) { RegisterError(_document, classNameSegment, "oh my dear, this class already exisits in the current scope!"); } else { #region Check & Resolve Baseclass if(basecls != null) { //check if we have a circual interhance tree var baseclassImpl = basecls.ResolveTypeDeclarationCache(); if(baseclassImpl != null && baseclassImpl.IsSubclassOf(new CodeTypeReferenceEx(_document, classNameSegment.TokenString, thisparent))) { //circular dependency detected!! RegisterError(_document, refBaseClass, "Woops you just produced a circular dependency in your inheritance tree!"); } else { if(basecls != null) type.BaseTypes.Add(basecls); else type.BaseTypes.Add(new CodeTypeReferenceEx(_document, "Object", thisparent) { ResolvedTypeDeclaration = _superBase }); } } #endregion // extract class documentation Comment var comment = ExtractComment(classkeywordSegment); if(comment != null) type.Comments.Add(comment); // Add it to the CodeDOM Tree thisparent.Members.Add(type); type.Parent = thisparent; } // Create a CodeRange Item int startOffset = classBodyStart.Range.Offset; var classBodyEnd = classBodyStart.FindClosingBracked(true); if(classBodyEnd != null) { int length = (classBodyEnd.Range.Offset - startOffset); _codeRangeManager.Add(new CodeRange(new SimpleSegment(startOffset, length), type)); } else { RegisterError(_document, classBodyStart, "Expected: " + Token.BlockClosed); } parentHirarchy.Push(type); bcc++; i = classBodyStart.LineNumber; // jumt to: class Foo { * <---| continue; #endregion } else { RegisterError(_document, next, "Expected: " + Token.BlockOpen); i = (next.Next != null) ? next.Next.LineNumber : next.LineNumber; } } } } } #endregion // adjust some asumptions the tokenizer has made if(parentHirarchy.Count > 1) { // if we are in a class body, we can't have a traditional command invoke foreach(var s in line.CodeSegments) if(s.Token == Token.TraditionalCommandInvoke) { s.Token = Token.Identifier; break; } } // is method definition?: #region Analyze for Method Definition var methodSegment = line.CodeSegments[0].ThisOrNextOmit(whitespacetokenNewLines); if(methodSegment != null && methodSegment.Token == Token.Identifier) { var methodSignatureStart = methodSegment.Next; if(methodSignatureStart != null && methodSignatureStart.Token == Token.LiteralBracketOpen) { var methodSignatureEnd = methodSignatureStart.FindClosingBracked(false); if(methodSignatureEnd != null) { var startMethodBody = methodSignatureEnd.NextOmit(whitespacetokenNewLinesComments); if(startMethodBody != null && startMethodBody.Token == Token.BlockOpen) { // jup we have a method definition here. // Method body starts at startMethodBody CodeTypeDeclarationEx thisparent = parentHirarchy.Any() ? parentHirarchy.Peek() : _languageRoot; bool hasDeclarationError = false; #region Generate Method Definition DOM var method = new CodeMemberMethodExAHK(_document) { Name = methodSegment.TokenString, LinePragma = CreatePragma(methodSegment, _document.FilePath), CodeDocumentItem = _document, ReturnType = new CodeTypeReferenceEx(_document, typeof(object)) }; methodSegment.CodeDOMObject = method; //check if this method is not already defined elsewere in current scope var equalmethods = from m in thisparent.Members.Cast<CodeTypeMember>() let meth = m as CodeMemberMethodExAHK where meth != null && !meth.IsBuildInType && meth.Equals(method) select meth; if(equalmethods.Any()) { RegisterError(_document, methodSegment, string.Format("The Methodename '{0}' is already used in the current scope!", method.Name)); hasDeclarationError = true; } else { // extract Method Comment var comment = ExtractComment(methodSegment); if(comment != null) method.Comments.Add(comment); // extract method params paramstack.Clear(); CodeSegment previous = methodSignatureStart; // get method params: while(true) { var current = previous.Next; if(current.Token == Token.Identifier || current.Token == Token.KeyWord) { paramstack.Push(current); } else if(current.Token == Token.ParameterDelemiter || current.Token == Token.LiteralBracketClosed) { // end of param reached: if(paramstack.Count == 1) { // thread one param as the untyped argument, type of Object method.Parameters.Add(new CodeParameterDeclarationExpressionEx(typeof(object), paramstack.Pop().TokenString) { Direction = FieldDirection.In }); } else if(paramstack.Count == 2) { CodeParameterDeclarationExpressionEx param; var second = paramstack.Pop(); var first = paramstack.Pop(); //handle byref -> if(first.Token == Token.KeyWord && first.TokenString.Equals(BY_REF, StringComparison.InvariantCultureIgnoreCase)) { param = new CodeParameterDeclarationExpressionEx(typeof(object), second.TokenString); param.Direction = FieldDirection.Ref; } else { param = new CodeParameterDeclarationExpressionEx( new CodeTypeReferenceEx(_document, first.TokenString, thisparent), paramstack.Pop().TokenString); } // thread two param as the type and argument method.Parameters.Add(param); } if(current.Token == Token.LiteralBracketClosed) break; } else if(current.Token == Token.NewLine){ break; } previous = current; } } #endregion // Method body ends at var endMethodBody = startMethodBody.FindClosingBracked(true); if(endMethodBody != null) { // get method statements method.Statements.AddRange( CollectAllCodeStatements(cancellationToken, thisparent, codeLineMap, startMethodBody.LineNumber + 1, endMethodBody.LineNumber)); // add it to the code DOM Tree if(!hasDeclarationError) { thisparent.Members.Add(method); method.DefiningType = thisparent; } // Create a CodeRange Item int startOffset = startMethodBody.Range.Offset; int length = (endMethodBody.Range.Offset - startOffset); _codeRangeManager.Add(new CodeRange(new SimpleSegment(startOffset, length), method)); // move the scanpointer to the method end: i = endMethodBody.LineNumber; continue; } else { RegisterError(_document, startMethodBody, "Missing: " + Token.BlockClosed); } } } } } #endregion // is class property / field #region Parse Class Properties / Fields if(parentHirarchy.Count > 1) { // we must be in a class to have method properties // extract keywords & Identifiers untill we reach // any otherToken - omit whitespaces List<CodeSegment> declarationStack = new List<CodeSegment>(); CodeSegment current = line.CodeSegments[0].ThisOrNextOmit(whitespacetokens); while(current != null) { if(current.Token == Token.WhiteSpace) { //ignore white spaces } else if(current.Token == Token.Identifier || current.Token == Token.KeyWord) { declarationStack.Add(current); } else { break; } current = current.Next; } switch(declarationStack.Count) { case 0: break; case 1: // instance field definition if(declarationStack[0].Token == Token.Identifier) { // this is an untyped instance class field declaration var propertyType = new CodeTypeReference(typeof(object)); var memberprop = new CodeMemberPropertyEx(_document) { Name = declarationStack[0].TokenString, Attributes = MemberAttributes.Public, Type = propertyType, LinePragma = CreatePragma(declarationStack[0], _document.FilePath) }; declarationStack[0].CodeDOMObject = memberprop; parentHirarchy.Peek().Members.Add(memberprop); } else { RegisterError(_document, declarationStack[0], string.Format("Unexpected Token: {0}", declarationStack[0].Token)); } break; case 2: // we have two members in the decalration stack // expected token flows // keyword - identifier: static Field, int Field // identifier - identifier: Car myTypedCarField // for the time beeing, AHK just supports static Field if(declarationStack[0].Token == Token.KeyWord && declarationStack[0].TokenString.Equals(MODIFIER_STATIC, StringComparison.InvariantCultureIgnoreCase)) { if(declarationStack[1].Token == Token.Identifier) { // this is an untyped static class field declaration var propertyType = new CodeTypeReference(typeof(object)); var memberprop = new CodeMemberPropertyEx(_document) { Name = declarationStack[1].TokenString, Attributes = MemberAttributes.Public | MemberAttributes.Static, Type = propertyType, LinePragma = CreatePragma(declarationStack[1], _document.FilePath) }; declarationStack[1].CodeDOMObject = memberprop; parentHirarchy.Peek().Members.Add(memberprop); } else { RegisterError(_document, declarationStack[0], string.Format("Expected: {0}", Token.Identifier)); } } else { RegisterError(_document, declarationStack[0], string.Format("Unexpected '{0}' in Class Body", declarationStack[0].TokenString)); } break; default: for(int ci = 0; ci < declarationStack.Count; ci++) { RegisterError(_document, declarationStack[ci], string.Format("To much declaration Members", declarationStack[0].Token)); } break; } } #endregion #region Parse Remaining Tokens if(codeLineMap.ContainsKey(i)) { var lineBlock = codeLineMap[i]; CodeTypeDeclarationEx thisparent = parentHirarchy.Any() ? parentHirarchy.Peek() : _languageRoot; foreach(var segment in lineBlock.CodeSegments) { cancellationToken.ThrowIfCancellationRequested(); if(segment.Token == Token.BlockOpen) { bcc++; } else if(segment.Token == Token.BlockClosed) { bcc--; if(parentHirarchy.Count - 2 == bcc) { if(parentHirarchy.Any()) parentHirarchy.Pop(); } } } _autoexec.Statements.AddRange( CollectAllCodeStatements(cancellationToken, thisparent, codeLineMap, i, i)); } else continue; #endregion } #endregion AnalyzeAST(cancellationToken); lock(_rootLanguageSnapshotLOCK) { _rootLanguageSnapshot = _languageRoot; } }); } catch(OperationCanceledException) { throw; } }
public NavigationGridlet[] FindGridletPath(NavigationGridlet start, NavigationGridlet end) { Dictionary<NavigationGridlet, int> scoresByGridlet = new Dictionary<NavigationGridlet, int>(); scoresByGridlet.Add(start, 0); var s = new Stack<KeyValuePair<NavigationGridlet, int>>(); s.Push(new KeyValuePair<NavigationGridlet, int>(start, 0)); bool success = false; while (s.Any()) { var kvp = s.Pop(); foreach (var neighbor in kvp.Key.Neighbors) { if (!scoresByGridlet.ContainsKey(neighbor) && neighbor.IsEnabled) { scoresByGridlet.Add(neighbor, kvp.Value + 1); s.Push(new KeyValuePair<NavigationGridlet, int>(neighbor, kvp.Value + 1)); if (neighbor == end) { success = true; break; } } } } if (!success) { Console.WriteLine("GRidlet pathing failed!"); return null; } else { var current = end; List<NavigationGridlet> path = new List<NavigationGridlet>(); while (current != start) { path.Add(current); int minimumDistance = Int32.MaxValue; NavigationGridlet minimumNeighbor = null; foreach (var neighbor in current.Neighbors) { int score; if (scoresByGridlet.TryGetValue(neighbor, out score)) { if (minimumDistance > score) { minimumDistance = score; minimumNeighbor = neighbor; } } } current = minimumNeighbor; } path.Add(start); var result = path.ToArray(); Array.Reverse(result); return result; } }
private static Path GetBestPathFrom(Board b, Options o, int y, int x) { Path bestPath = new Path(); Stack<Tuple<Board, Path>> paths = new Stack<Tuple<Board, Path>>(); paths.Push(new Tuple<Board, Path>(b, new Path { Start = new Tuple<int, int>(y, x), Current = new Tuple<int, int>(y, x), Depth = 1, Score = b.Score(BoardScorer.Options.Horus) })); while (paths.Any()) { var cur = paths.Pop(); var curPath = cur.Item2; var curBoard = cur.Item1; if (curPath.Score > bestPath.Score) bestPath = curPath; if (curPath.Depth == o.MaxDepth) continue; //if (paths.Count() > o.WhenToPrune) //{ // var newPaths = new Stack<Tuple<Board, Path>>(); // foreach (var path in paths.OrderByDescending(p => p.Item2.Score).Take(o.NumToKeep).Reverse()) // newPaths.Push(path); // paths = newPaths; //} foreach (var direction in Board.MoveDirections) { if (curPath.Length != 0 && curPath.Actions.Last()[0] == -direction[0] && curPath.Actions.Last()[1] == -direction[1]) continue; var newY = curPath.Current.Item1 + direction[0]; var newX = curPath.Current.Item2 + direction[1]; if (newY < 0 || newY >= b.Height || newX < 0 || newX >= b.Width) continue; Board newBoard = new Board(curBoard); Orb tempOrb = newBoard.Orbs[newY, newX]; newBoard.Orbs[newY, newX] = newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2]; newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2] = tempOrb; var newPath = new List<int[]>(curPath.Actions); newPath.Add(direction); paths.Push(new Tuple<Board, Path>(newBoard, new Path { Start = curPath.Start, Current = new Tuple<int, int>(newY, newX), Depth = curPath.Depth + 1, Score = newBoard.Score(BoardScorer.Options.Horus) - curPath.Depth / 100, Actions = newPath })); } } return bestPath; }
private static List<MondaiWord> 正解探索(CorrectAnswer rightAnswer, List<MondaiWord> a) { int i = 0; var b = new List<MondaiWord>(); var stack = new Stack<Local>(); stack.Push(new Local(i, a, b)); while (stack.Any()) { var temp = stack.Pop(); i = temp._i; a = temp._a; b = temp._b; while (i < a.Count()) { var bb = new List<MondaiWord>(b.Count() + 1); bb.AddRange(b); bb.Add(a[i]); if (!rightAnswer.StartsWith(bb)) { i++; continue; } if (rightAnswer.IsMatch(bb)) { return bb; } var aa = new List<MondaiWord>(a); aa.RemoveAt(i); stack.Push(new Local(i + 1, a, b)); i = 0; a = aa; b = bb; } } return null; /* for (int i = 0; i < a.Count(); i++) { if (!b.Any() && !a[i].HasLeftJoint && !rightAnswer.Text.StartsWith(a[i].Text, StringComparison.Ordinal)) { continue; } var aa = new List<MondaiWord>(a); aa.RemoveAt(i); var bb = new List<MondaiWord>(b); bb.Add(a[i]); if (!rightAnswer.StartsWith(bb)) { continue; } if (rightAnswer.IsMatch(bb)) { return bb; } var result = 正解探索(rightAnswer, aa, bb); if (null != result) return result; } return null;*/ }