public static bool StateMachine(string expression) { // Time: O(n). One pass over the entire string from left to right. Evaluates the state of each character against the previous character's valid state transitions. // Memory: O(1). A constant amount of memory is used to keep track of valid states and bracket counts. // Treating null and empty string expressions as true if (string.IsNullOrEmpty(expression)) { return(true); } var bracketStack = new Stack <char>(); var validStateTransitions = ExpressionStateMachine.GetStateTransitions(); foreach (var currentChar in expression) { // Check brackets first for possible early return if (BracketsInvalid(bracketStack, currentChar)) { return(false); } // Get all possible states for the current character var currentStates = ExpressionStateMachine.GetStates(currentChar); // Get the next valid state, if it exists var nextState = GetNextValidState(validStateTransitions, currentStates); if (nextState == ExpressionStateMachine.ExpressionStateEnum.Invalid) { return(false); } // Set the collection of valid state transitions for the current state validStateTransitions = ExpressionStateMachine.GetStateTransitions(nextState); } // Check to see if all brackets have a matching pair before returning true if (bracketStack.Count != 0) { return(false); } // Check for the Exit state on return in case the expression ends with an invalid state return(validStateTransitions.Contains(ExpressionStateMachine.ExpressionStateEnum.Exit)); }
private static bool BracketsInvalid(Stack <char> bracketCount, char bracket) { if (ExpressionStateMachine.IsOpeningBracket(bracket)) { bracketCount.Push(bracket); } if (ExpressionStateMachine.IsClosingBracket(bracket)) { var lastBracket = bracketCount.Pop(); if (bracket == ')' && lastBracket != '(') { return(true); } if (bracket == '}' && lastBracket != '{') { return(true); } } return(false); }