check integrity of brackets in special formula - c#

my program should print a message on the screen if the formula that the user entered is good for the terms(you can only use digits and letters, u can't start with '(' and like mathematical formula, for each open bracket, has to be a suitable(and in the right place) close bracket.
here some formulas that the program should accepts and prints:
True-
a(aa(a)aaa(aa(a)aa)aa)aaaaa
a(((())))
here some formulas that the program should not accepts and prints:
False-
()()()
)()()(
but the program always prints False
thanks for helping
Heres the code:EDIT
bool IsNumeric(char character)
{
return "0123456789".Contains(character);
// or return Char.IsNumber(character);
}
bool IsLetter(char character)
{
return "ABCDEFGHIJKLMNOPQRSTUVWXWZabcdefghigjklmnopqrstuvwxyz".Contains(character);
}
bool IsRecognized(char character)
{
return IsBracket(character) | IsNumeric(character) | IsLetter(character);
}
public bool IsValidInput(string input)
{
if (String.IsNullOrEmpty(input) || IsBracket(input[0]))
{
return false;
}
var bracketsCounter = 0;
for (var i = 0; i < input.Length; i++)
{
var character = input[i];
if (!IsRecognized(character))
{
return false;
}
if (IsBracket(character))
{
if (character == '(')
bracketsCounter++;
if (character == ')')
bracketsCounter--;
}
}
if (bracketsCounter > 0)
{
return false;
}
return bracketsCounter==0;
}
}
}

Your algorithm is unnecessarily complex - all you need is a loop and a counter.
Check the initial character for ( (you already do that)
Set the counter to zero, and go through each character one by one
If the character is not a letter or a parentheses, return false
If the character is an opening (, increment the counter
If the character is a closing ), decrement the counter; if the counter is less than zero, return false
Return true if the count is zero after the loop has ended; otherwise return false

Is debugging this hard really? This condition:
((!IsNumeric(st[i])) && (st[i] != '(') && (st[i] != ')')&&((st[i]<'a')||(st[i]>'z')||(st[i]<'A')||(st[i]>'Z')))
return false;
is obviously wrong. It returns false for a every time. You don't take into consideration that a is greater than Z.
EDIT:
so how can i make it easier to read? that the only way i figured. do u
have other solution for this problem?
As for that condition block - use smaller methods / functions, for example.
bool IsBracket(char character)
{
return (character == '(' | character == ')');
}
bool IsNumeric(char character)
{
return "0123456789".Contains(character);
// or return Char.IsNumber(character);
}
bool IsLetter(char character)
{
// see why this is NOT prone to fail just because 'a' is greater than 'Z' in C#?
return (character >= 'a' & character <= 'z') |
(character >= 'A' & character <= 'Z');
// or return Regex.IsMatch(character.ToString(), "[a-zA-Z]", RegexOptions.None);
// or return Char.IsLetter(character);
}
// now you can implement:
bool IsRecognized(char character)
{
return IsBracket(character) | IsNumeric(character) | IsLetter(character);
}
and then in your big method you could just safely use:
if (!IsRecognized(st[i]))
return false;
It may look like an overkill for such a trivial example, but it's a better approach in principle, and certainly more readable.
And after that, you could reduce your code to something along the lines of:
bool IsInputValid(string input)
{
if (String.IsNullOrEmpty(input) || IsBracket(input[0]))
{
return false;
}
var bracketsCounter = 0;
for (var i = 0; i < input.Length; i++)
{
var character = input[i];
if (!IsRecognized(character))
{
return false;
}
if (IsBracket(character)) // redundant?
{
if (character == '(') // then what?
if (character == ')') // then what?
}
if (bracketsCounter < what?)
{
what?
}
}
return bracketsCounter == what?;
}
(dasblinkenlight's algorithm)
EDIT 10th April
You got it wrong.
bool IsNumeric(char character)
{
return "0123456789".Contains(character);
// or return Char.IsNumber(character);
}
bool IsLetter(char character)
{
return "ABCDEFGHIJKLMNOPQRSTUVWXWZabcdefghigjklmnopqrstuvwxyz".Contains(character);
}
bool IsRecognized(char character)
{
return IsBracket(character) | IsNumeric(character) | IsLetter(character);
}
public bool IsValidInput(string input)
{
if (String.IsNullOrEmpty(input) || IsBracket(input[0]))
{
return false;
}
var bracketsCounter = 0;
for (var i = 0; i < input.Length; i++)
{
var character = input[i];
if (!IsRecognized(character))
{
return false;
}
if (IsBracket(character))
{
if (character == '(')
bracketsCounter++;
if (character == ')')
bracketsCounter--;
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (bracketsCounter < 0) // NOT "> 0", and HERE - INSIDE the for loop
{
return false;
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
return bracketsCounter==0;
}
}
}
By the way, you also made a mistake in your IsLetter method:
...UVWXWZ? Should be UVWXYZ

Related

C#, Finding equal amount of brackets

I've made my own way to check if the amount of () and "" are equal. So for example "H(ell)o") is correct. However, the problem I face is that what if the first bracket is ) and the other is ( example "H)ell(o" this would mean it's incorrect. So my question is how would I check whether the first bracket in any word is opening?
EDIT:
public static Boolean ArTinkaSintakse(char[] simboliai)
{
int openingBracketsAmount = 0;
int closingBracketsAmount = 0;
int quotationMarkAmount = 0;
for (int i = 0; i < simboliai.Length; i++)
{
if (openingBracketsAmount == 0 && simboliai[i] == ')')
break;
else if (simboliai[i] == '\"')
quotationMarkAmount++;
else if (simboliai[i] == '(')
openingBracketsAmount++;
else if (simboliai[i] == ')')
closingBracketsAmount++;
}
int bracketAmount = openingBracketsAmount + closingBracketsAmount;
if (quotationMarkAmount % 2 == 0 && bracketAmount % 2 == 0)
return true;
else
return false;
}
Add a check for if (openingBracketsAmount < closingBracketsAmount). If that's ever true, you know that the brackets are unbalanced.
Add an if statement that breaks out of the loop if the first bracket encountered is a closing bracket, like so:
for (int i = 0; i < word.Length; i++)
{
if ((openingBracketsAmount == 0) && (word[i] == ')'))
{
<Log error...>
break;
}
<Rest of your loop...>
}
This way, as soon as openingBracketsAmount is updated, this if statement will be unreachable.
I would approach the problem recursively.
Create a Dictionary<char, char> to keep track of which opening character goes with which closing one.
Then I would implement:
boolean findMatches(string input, out int lastIndex) {}
The method will scan until a member of the Dictionary keys is found. Then it will recursively call itself with the remainder of the string. If the recursive call comes back false, return that. If true, check if the lastIndex character (or the one after; I always need to write the code to check fenceposts) is the matching bracket you want. If it is, and you're not at the end of the string, return the value of a recursive call with the rest of the string after that matching bracket. If you are at the end, return true with that character's index. If that character isn't the matching bracket/quote, pass the remainder of the string (including that last character) to another recursive call.
Continue until you reach the end of the string (returning true if you aren't matching a bracket or quote, false otherwise). Either way with a lastIndex of the last character.
Probably you need a stack-based approach to validate such expressions.
Please try the following code:
public static bool IsValid(string s)
{
var pairs = new List<Tuple<char, char>>
{
new Tuple<char, char>('(', ')'),
new Tuple<char, char>('{', '}'),
new Tuple<char, char>('[', ']'),
};
var openTags = new HashSet<char>();
var closeTags = new Dictionary<char, char>(pairs.Count);
foreach (var p in pairs)
{
openTags.Add(p.Item1);
closeTags.Add(p.Item2, p.Item1);
}
// Remove quoted parts
Regex r = new Regex("\".*?\"", RegexOptions.Compiled | RegexOptions.Multiline);
s = r.Replace(s, string.Empty);
var opened = new Stack<char>();
foreach (var ch in s)
{
if (ch == '"')
{
// Unpaired quote char
return false;
}
if (openTags.Contains(ch))
{
// This is a legal open tag
opened.Push(ch);
}
else if (closeTags.TryGetValue(ch, out var openTag) && openTag != opened.Pop())
{
// This is an illegal close tag or an unbalanced legal close tag
return false;
}
}
return true;
}

How to know if a string length contains a specified amount of capped letters

I'm trying to know if a string contains a length between 5 and 10 and at the same time, 7-10 letters are in upper case. The idea is to detect if a message sent by a user is 70%-100% capped.
This is what I have tried so far:
bool IsMessageUpper(string input)
{
if (input.Length.Equals(5 <= 10) && (input.Take(7).All(c => char.IsLetter(c) && char.IsUpper(c))))
{
return true;
}
else
{
return false;
}
}
You can rewrite your method in this way
bool IsMessageUpper(string input)
{
int x = input.Length;
return x>=7 && x<= 10 && input.Count(char.IsUpper) >= 7;
}
You can also add some safety checks to handle undesidered inputs
bool IsMessageUpper(string input)
{
int x = (input ?? "").Length;
return x>=7 && x<= 10 && input.Count(char.IsUpper) >= 7;
}

C# Controlling balanced parenthesis to recursive

I am trying to write a function to control if the parenthesis included in a stringare balanced or not.
I have written the following function:
public bool IsBalanced(string input)
{
//last condition, gets out
if (string.IsNullOrEmpty(input)) return true;
int numOpen = 0;
bool opened = false;
foreach (char c in input)
{
if (char.ToUpperInvariant(c) =='(')
{
opened = true;
numOpen+=1;
}
if (char.ToUpperInvariant(c) == ')')
{
if (opened)
{
numOpen-=1;
opened = numOpen > 0;
}
else
return false; //incorrect position parentheses, closes but not opened
}
}
return numOpen == 0;
}
I wanted to change it to a recursive function, but have not been able to do so. Could anyone give a hint how to do it?
Well, your algorithm is not pretty. Here is a better one
int check = 0;
foreach (var c in input)
{
if (c == '(') {
check++;
} else if (c == ')') {
check--;
}
if (check < 0) {
return false; // error, closing bracket without opening brackets first
}
}
return check == 0; // > 0 error, missing some closing brackets
To make it (algorithm of checking for balanced brackets) recursive you can go with following
bool IsBalanced(string input)
{
var first = input.IndexOf('('); // first opening bracket position
var last = input.LastIndexOf(')'); // last closing bracket position
if (first == -1 && last == -1)
return true; // no more brackets - balanced
if (first == -1 && last != -1 || first != -1 && last == -1)
return false; // error - one of brackets is missing
if (first > last)
return false; // error - closing bracket is BEFORE opening
return IsBalanced(input.Substring(first, last - first)); // not sure, might need to tweak it, parameter should be without first and last bracket (what is inside)
}
This simply remove first opening brackets and last closing bracket and pass what is left as parameter (recursively) until one of the end conditions is met.
The basic idea is to take a variant (numOpen in this case) as an argument.
Here is my code:
public bool IsBalancedRec(string input, int numOpen = 0)
{
if (numOpen < 0)
return false;
if (string.IsNullOrEmpty(input))
return numOpen == 0;
char c = input[0];
string rest = input.Substring(1);
if (c == '(')
return IsBalancedRec(rest, numOpen + 1);
else if (c == ')')
return IsBalancedRec(rest, numOpen - 1);
else
return IsBalancedRec(rest, numOpen);
}
And call this like IsBalancedRec("so(m(eth)ing)").
Implement with stack:
Stack myStak = new Stack();
public bool IsBalanced(string input)
{
if (input.ToArray().Count() != 0)
{
if(input.ToArray()[0] == '(')
{
myStak.Push('(');
}
else if(input.ToArray()[0] == ')')
{
if (myStak.Count != 0)
myStak.Pop();
else
{
//not balanced
return false;
}
}
return IsBalanced(input.Substring(1));
}
else
{
if (myStak.Count == 0)
{
//balanced
return true;
}
else
{
//not balanced
return false;
}
}
}
public static bool IsBalanced(string input)
{
int numOpen = 0;
while(input != "")
{
char c = input[0];
input = input.Substring(1);
numOpen = c == '(' ? (numOpen + 1) : (c == ')' ? (numOpen - 1) : numOpen);
}
return numOpen == 0;
}
// count no of left and right bracket or parenthesis and check counts
var InputStr= str.ToCharArray();
int left = 0;
int right = 0;
foreach (char item in InputStr)
{
if(item == '(')
{
left ++;
} else if(item == ')')
{
right ++;
}
}
if(right == l)
{
return "1";
}
return "0";
}

Writing a recursive function in C#

I need to write a function which verifies parentheses are balanced in a string. Each open parentheses should have a corresponding close parentheses and they should correspond correctly.
For example, the function should return true for the following strings:
(if (any? x) sum (/1 x))
I said (it's not (yet) complete). (she didn't listen)
The function should return false for the following strings:
:-)
())(
OPTIONAL BONUS
Implement the solution as a recursive function with no mutation / side-effects.
Can you please help me out in writing using C# because I'm new to .NET technologies.
Thanks.
Here's what I've tried so far. It works for sending parameters as open and close brackets, but I'm confused with just passing a string... and also I should not use stack.
private static bool Balanced(string input, string openParenthesis, string closedParenthesis)
{
try
{
if (input.Length > 0)
{
//Obtain first character
string firstString = input.Substring(0, 1);
//Check if it is open parenthesis
//If it is open parenthesis push it to stack
//If it is closed parenthesis pop it
if (firstString == openParenthesis)
stack.Push(firstString);
else if (firstString == closedParenthesis)
stack.Pop();
//In next iteration, chop off first string so that it can iterate recursively through rest of the string
input = input.Substring(1, input.Length - 1);
Balanced(input, openParenthesis, closedParenthesis); //this call makes the function recursive
}
if (stack.Count == 0 && !exception)
isBalanced = true;
}
catch (Exception ex)
{
exception = true;
}
return isBalanced;
}
You don't need to use any recursion method for such a simple requirement, just try this simple method and it works like a charm:
public bool AreParenthesesBalanced(string input) {
int k = 0;
for (int i = 0; i < input.Length; i++) {
if (input[i] == '(') k++;
else if (input[i] == ')'){
if(k > 0) k--;
else return false;
}
}
return k == 0;
}
I have used the startIndex and increment with each recursive call
List<string> likeStack = new List<string>();
private static bool Balanced(string input, string openParenthesis, string closedParenthesis , int startIndex)
{
try
{
if (startIndex < input.Length)
{
//Obtain first character
string firstString = input.Substring(startIndex, 1);
//Check if it is open parenthesis
//If it is open parenthesis push it to stack
//If it is closed parenthesis pop it
if (firstString == openParenthesis)
likeStack.Add(firstString);
else if (firstString == closedParenthesis)
likeStack.RemoveAt(likeStack.Count -1);
//In next iteration, chop off first string so that it can iterate recursively through rest of the string
Balanced(input, openParenthesis, closedParenthesis , startIndex + 1); //this call makes the function recursive
}
if (likeStack.Count == 0 && !exception)
isBalanced = true;
}
catch (Exception ex)
{
exception = true;
}
return isBalanced;
}
How's this recursive version?
public static bool Balanced(string s)
{
var ix = -1;
return Balanced(s, false, ref ix);
}
private static bool Balanced(string s, bool inParens, ref int ix)
{
ix++;
while (ix < s.Length)
{
switch (s[ix++])
{
case '(':
if (!Balanced(s, true, ref ix))
return false;
break;
case ')':
return inParens;
}
}
return !inParens;
}

how to check if string has more than two repeating characters

I'm trying to check if a string contains more than two repeating characters.
for example
'aabcd123' = ok
'aaabcd123' = not ok
'aabbab11!#' = ok
'aabbbac123!' = not ok
I've tried something like this but with no luck
if (string.Distinct().Count() > 2){
//do something
}
any help would be appreciated.
This one worked for me:
public bool IsOK(string s)
{
if(s.Length < 3) return true;
return !s.Where((c,i)=> i >= 2 && s[i-1] == c && s[i-2] == c).Any();
}
'aabcd123' : OK
'aaabcd123' : not OK
'aabbab11!#' : OK
'aabbbac123!' : not OK
Just for classic loops sake:
public bool HasRepeatingChars(string str)
{
for(int i = 0; i < str.Length - 2; i++)
if(str[i] == str[i+1] && str[i] == str[i+2])
return true;
return false;
}
You can use Regex for this one:
return Regex.IsMatch(inputString, #"(.)\1{2,}", RegexOptions.IgnoreCase)
This checks for any character, then for at least 2 times that same character. Works even with strings like "AaA" and can be modified to find out exactly what those characters are, where they are occurring in the string, and much more (also allows you to replace those substrings with something else)
More information:
http://msdn.microsoft.com/en-us/library/6f7hht7k.aspx
http://msdn.microsoft.com/en-us/library/az24scfc.aspx
Since you want to find runs of three characters and not just three characters in a string, you need to loop through and look at three consecutive characters to see if they are the same. A loop like this will work.
string myString = "aaabbcd";
bool hasMoreThanTwoRepeatingCharsInARow = false;
for(int index = 2; index < myString.Length; index++)
{
if(myString[index] == myString[index - 1] && myString[index] == myString[index - 2])
{
hasMoreThanTwoRepeatingCharsInARow = true;
}
}
I would stick this in a method and make the variables better and you're good to go!
[TestMethod]
public void Test()
{
const string sample1 = "aabcd123";
const string sample2 = "aaabcd123";
const string sample3 = "aabbab11!#";
const string sample4 = "aabbbac123!";
Assert.IsTrue(IsOk(sample1));
Assert.IsFalse(IsOk(sample2));
Assert.IsTrue(IsOk(sample3));
Assert.IsFalse(IsOk(sample4));
}
private bool IsOk(string str)
{
char? last = null;
var i = 1;
foreach (var c in str)
{
if (last == c)
{
i++;
if (i > 2) return false;
}
else
{
i = 1;
}
last = c;
}
return true;
}
Use the regex
(?:.*<letter>.*){2}
For letter b for example you'd use
(?:.*b.*){2}
For all vowels
(?:.*[aeiou].*){2}
For regex usage on c# refer to https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=net-5.0

Categories