Logical error while creating Palindrome Program - c#

I tried to make Palindrome program as small as possible. However, this program is giving logical error. When I enter palindrome string it gives "False" as result which is opposite of what is expected.
char[] phrase;
Console.WriteLine((phrase = Console.ReadLine().ToArray())==phrase.Reverse().ToArray());
Console.ReadLine();
I do not want to increase number of statements of this program.

In .NET, arrays do not have an overloaded equality operator. Use Enumerable.SequenceEquals.
Reading your code more thoroughly, you are making things more complicated than necessary.
string phrase = Console.ReadLine();
var reversedPhrase = phrase.Reverse(); //Type is IEnumerable<char>
Console.WriteLine(phrase.SequenceEquals(reversedPhrase));
I recommend that you don't burry side-effects inside of expressions in the way you did. That code could well have been a test question to see if a student can work it out.

If you want to do it by array then you can try this
char[] phrase;
Console.WriteLine(phrase = Console.ReadLine().ToArray().SequenceEqual(phrase.Reverse().ToArray()));
Console.ReadLine();
just like usr said use sequenceequal

Since you created 2 different array and arrays are reference type, == checks for reference equality, not value.
You can use Enumerable.SequenceEqual instead which returns;
true if the two source sequences are of equal length and their
corresponding elements are equal according to the default equality
comparer for their type;
Console.WriteLine(myString.SequenceEqual(myString.Reverse()));
Easiest way to compare arrays in C#

Related

SequenceEqual always returning false

I making a lottery simulation and i have 2 different arrays with 6 numbers to hold firstly the numbers the user wishes to play and secondly the numbers that get generated each run.
The user enters their numbers into a textbox and its saved as a string and placed into respective spots in the aray, the randomly generated nums are also saved as a string into the string array.
After this i have a SequenceEqual for comparison
bool equal = lotteryNums.SequenceEqual(playerNums);
This always returns false, i have set all the generated array elements manually to 1-6 and then the players nums accordingly through the textboxes yet it will always return a false.
The generated array is currently filled like this for testing
lotteryNums[0] = "1";
lotteryNums[1] = "2";
lotteryNums[2] = "3";
lotteryNums[3] = "4";
lotteryNums[4] = "5";
lotteryNums[5] = "6";
The player array is filled like this using the next array position for the next number
string inputNum = inputBox_txt.Text;
playerNums[0] = inputNum;
Why is this always returning false?
Since people are asking the arrays are both in the exact same order and do not appear to contain anything more or anything less than the numbers in the arrays
SequenceEqual returns true if the two source sequences are of equal length and their corresponding elements are equal according to the default equality comparer for their type; otherwise, false.
Since the two arrays you provide are not identical then you are getting false.
In addition to what Athanasios Emmanouilidis said: it seems that the collections need to have the same order. So you should order them:
bool equal = playerNums.OrderBy(n => n).SequenceEqual(lotteryNums.OrderBy(n => n));
Another thing to consider: SequenceEquals requires that the numbers be in the exact same order in both arrays. Even if the arrays contain the same numbers, but they are in a different order, you will get false. You can solve this by sorting each list prior to comparing (just make sure you sort both in the same way).
If that doesn't work, verify that the strings from the textbox are actually just the numbers, and do not include any white space or special characters.
SeqqnceEqual will also take the order of the elemnts into account, which you probably donĀ“t want in a lottery. What you want instead is to check if all the expected values are in the inout as well:
var sixCorrects = lotteryNums.All(x => playerNums.Contains(x));
All will stop iterating as soon as an element of lotteryNums was not found within playerNums.

Visual Studio 2013: Testing / Assert Strings

I have a question. I am testing a lib from me, which is generation some text in xml-style. Up to now, I am testing with the function
Assert.AreEqual(string1, string2);
But the strings, which are in xml-style, are more than 300 characters long. And when I make a little mistake in one character, the test is failing and the output is, that the strings are not equal. But the test does not say, at which position they are not equal.
So my question is: Is there already an implemented function, which compares two strings and tell me also, at which position they differ + output of the strings ... ?
try this way
var indexBroke = 0;
var maxLength = Math.Min(string1.Length, string2.Length);
while (indexBroke < maxLength && string1[indexBroke] == string2[indexBroke]) {
indexBroke++;
}
return ++indexBroke;
the logic is that you compare each character step by step and when you get the first difference the function exit returninng the last index with equal characters
For that reason (and many others more), I can recommend using FluentAssertions.
With FluentAssertions you would formulate your assertion like this:
string1.Should().Be(string2);
In the case the strings do not match, you get a nice informative message helping you to tackle down the problem:
Expected string to be
"<p>Line one<br/>Line two</p>" with a length of 28, but
"<p>Line one<br>Line two</p>" has a length of 27.
Additionally, you can give a reason to make the error message even more clear:
string1.Should().Be(string2, "a multiline-input should have been successfully parsed");
That would give you the following message:
Expected string to be
"<p>Line one<br/>Line two</p>" with a length of 28 because a multiline-input should have been successfully parsed, but
"<p>Line one<br>Line two</p>" has a length of 27.
These reason arguments are especially valuable when comparing values that provide no meaning by themselves, such as booleans and numbers.
BTW, FluentAssertions also helps greatly in comparing object graphs.

solving a math expression

I want to evaluate a math expression which the user enters in a textbox. I have done this so far
string equation, finalString;
equation = textBox1.Text;
StringBuilder stringEvaluate = new StringBuilder(equation);
stringEvaluate.Replace("sin", "math.sin");
stringEvaluate.Replace("cos", "math.cos");
stringEvaluate.Replace("tan", "math.tan");
stringEvaluate.Replace("log", "math.log10");
stringEvaluate.Replace("e^", "math.exp");
finalString = stringEvaluate.ToString();
StringBuilder replaceI = new StringBuilder(finalString);
replaceI.Replace("x", "i");
double a;
for (int i = 0; i<5 ; i++)
{
a = double.Parse(finalStringI);
if(a<0)
break;
}
when I run this program it gives an error "Input string was not in a correct format." and highlights a=double.Parse(finalStringI);
I used a pre defined expression a=i*math.log10(i)-1.2 and it works, but when I enter the same thing in the textbox it doesn't.
I did some search and it came up with something to do with compiling the code at runtime.
any ideas how to do this?
i'm an absolute beginner.
thanks :)
The issue is within your stringEvaluate StringBuilder. When you're replacing "sin" with "math.sin", the content within stringEvaluate is still a string. You've got the right idea, but the error you're getting is because of that fact.
Math.sin is a method inside the Math class, thus it cannot be operated on as you are in your a = double.Parse(finalStringI); call.
It would be a pretty big undertaking to accomplish your goal, but I would go about it this way:
Create a class (perhaps call it Expression).
Members of the Expression class could include Lists of operators and operands, and perhaps a double called solution.
Pass this class the string at instantiation, and tear it apart using the StringBuilder class. For example, if you encounter a "sin", add Math.sin to the operator collection (of which I'd use type object).
Each operator and operand within said string should be placed within the two collections.
Create a method that evaluates the elements within the operator and operand collection accordingly. This could get sticky for complex calculations with more than 2 operators, as you would have to implement a PEMDAS-esque algorithm to re-order the collections to obey the order of operations (and thus achieve correct solutions).
Hope this helps :)
The .Parse methods (Int.Parse, double.Parse, etc) will only take a string such as "25" or "3.141" and convert it to the matching value type (int 25, or double 3.141). They will not evaluate math expressions!
You'll pretty much have to write your own text-parser and parse-tree evaluator, or explore run-time code-generation, or MSIL code-emission.
Neither topic can really be covered in the Q&A format of StackOverflow answers.
Take a look at this blog post:
http://www.c-sharpcorner.com/UploadFile/mgold/CodeDomCalculator08082005003253AM/CodeDomCalculator.aspx
It sounds like it does pretty much what you're trying to do. Evaluating math expressions is not as simple as just parsing a double (which is really only going to work for strings like "1.234", not "1 + 2.34"), but apparently it is possible.
You can use the eval function that the framework includes for JScript.NET code.
More details: http://odetocode.com/code/80.aspx
Or, if you're not scared to use classes marked "deprecated", it's really easy:
static string EvalExpression(string s)
{
return Microsoft.JScript.Eval.JScriptEvaluate(s, null, Microsoft.JScript.Vsa.VsaEngine.CreateEngine()).ToString();
}
For example, input "Math.cos(Math.PI / 3)" and the result is "0.5" (which is the correct cosine of 60 degrees)

Is there a way to use less than on Strings?

Using a string.CompareTo(string) i can get around this slightly but is not easy to read and i have read on that locallity settings might influence the result.
Is there a way to just simply use < or > on 2 Strings in a more straightforward way?
You can overload operators but you seldom should. To me "stringA" > "stringB" wouldn't mean a damn thing, it's not helping readability IMO. That's why operator overloading guidelines advise not to overload operators if the meaning is not obvious.
EDIT: Operator Overloading Usage Guidelines
Also, in case of String I'm afraid you can't do it seeing as you can put operator-overloading methods only in the class in which the methods are defined.
If the syntax of CompareTo bothers you, maybe wrapping it in extension method will solve your problem?
Like that:
public static bool IsLessThan(this string str, string str2) {
return str.Compare(str2) < 0;
}
I still find it confusing for reader though.
The bottom line is, you can't overload operators for String. Usually you can do something like declaring a partial and stuffing your overloads there, but String is a sealed class, so not this time. I think that the extension method with reasonable name is your best bet. You can put CompareTo or some custom logic inside it.
CompareTo is the proper way in my opinion, you can use the overloads to specify culture specific parameters...
You mention in a comment that you're comparing two strings with values of the form "A100" and "B001". This works in your legacy VB 6 code with the < and > operators because of the way that VB 6 implements string comparison.
The algorithm is quite simple. It walks through the string, one character at a time, and compares the ASCII values of each character. As soon as a character from one string is found to have a lower ASCII code than the corresponding character in the other string, the comparison stops and the first string is declared to be "less than" the second. (VB 6 can be forced to perform a case-insensitive comparison based on the system's current locale by placing the Option Compare Text statement at the top of
the relevant code module, but this is not the default setting.)
Simple, of course, but not entirely logical. Comparing ASCII values skips over all sorts of interesting things you might find in strings nowadays; namely non-ASCII characters. Since you appear to be dealing with strings whose contents have pre-defined limits, this may not be a problem in your particular case. But more generally, writing code like strA < strB is going to look like complete nonsense to anyone else who has to maintain your code (it seems like you're already having this experience), and I encourage you to do the "right thing" even when you're dealing with a fixed set of possible inputs.
There is nothing "straightforward" about using < or > on string values. If you need to implement this functionality, you're going to have to do it yourself. Following the algorithm that I described VB 6 as using above, you could write your own comparison function and call that in your code, instead. Walk through each character in the string, determine if it is a character or a number, and convert it to the appropriate data type. From there, you can compare the two parsed values, and either move on to the next index in the string or return an "equality" value.
There is another problem with that, I think:
Assert.IsFalse(10 < 2);
Assert.IsTrue("10" < "2");
(The second Assert assumes you did an overload for the < operator on the string class.)
But the operator suggests otherwise!!
I agree with Dyppl: you shouldn't do it!

C# highest string

This seems so trivial but I'm not finding an answer with Google.
I'm after a high value for a string for a semaphore at the end of a sorted list of strings.
It seems to me that char.highest.ToString() should do it--but this compares low, not high.
Obviously it's not truly possible to create a highest possible string because it would always be lower than the same thing + more data but the strings I'm sorting are all valid pathnames and thus the symbols used are constrained.
In response to the comments:
In the pre-unicode days in Delphi I would simply have used #255. I simply want a string that will compare higher than any possible pathname. This should be trivial--why isn't it??
Response #2:
It's not the sorting that requires the sentinel, it's the processing afterwards. I have multiple lists that I am sort-of merging (a simplistic merge won't do the job.) and either I duplicate code or I have dummy values that always compare high.
A string representation of the highest character will only be one character long.
Why don't you just append it as a semaphore after sorting, rather than trying to make it something that will sort afterwards?
Alternatively, you could specify your own comparator that sorts your token after any other string, and calls the default comparator otherwise.
I had the same problem when trying to put null values at the bottom of a list in a LINQ OrderBy() statement. I ended up using...
Char.ConvertFromUtf32(0x10ffff)
...which worked a treat.
Something like this?
public static String Highest(this String value)
{
Char highest = '\0';
foreach (Char c in value)
{
highest = Math.Max(c, highest);
}
return new String(new Char[] { highest });
}

Categories