How to parse the following string - c#

I am trying to generate a formula which could be anything like this, this is just a sample,
A + B + C > D - A
Now, A, B, C, D, etc are Column Names of a sheet (like excel sheet) i will be accessing in memory.
I need to generate a Rule, like the above A + B + C > D - A which will decide what kind of values user can add in a Cell.
Currently this is how i have begun:
string toValidate = "A + B + C > D + E - A";
string lhs = "", rhs = "";
string[] comparisonOperators = new string[] { "=", ">", "<", "<>", "!=" };
char[] arithmeticOperators = { '+', '-', '/', '*' };
toValidate = toValidate.Replace(#" ", "");
for (int i = 0; i < comparisonOperators.Length; i++)
{
if (toValidate.Contains(comparisonOperators[i]))
{
operatorIndex = toValidate.IndexOf(comparisonOperators[i]);
break;
}
}
lhs = toValidate.Substring(0, operatorIndex);
rhs = toValidate.Substring(operatorIndex + 1);
string[] columnLhsList = lhs.Split(arithmeticOperators);
string[] columnRhsList = rhs.Split(arithmeticOperators);
However even though i have the strings as lhs and rhs and even my operator which > in the above code, i am not able to understand how can i apply the formula on the sheet itself. I just need to know which Column has which operator associated.
Since i have the individual column names, but not the operator before them, for e.g,
+ before A - before A in another case.
How do i parse the above please help.

It is, however, a very fun question if you want to make simple formula parsers like this yourself.
I advice you to check out this article, since it is very clearly written and understandable because of it.
Shunting-yard Algorithm

Personally, I would never try/dare to create my own formula expression parser. Instead, I would (and did) use one of the may available ones, e.g. NCalc over at CodePlex.com.
Using these tools, it is as easy as writing
Expression e = new Expression("2 + 3 * 5");
Debug.Assert(17 == e.Evaluate());
to get your formula evaluated.
Usually such libraries are very solid, well tested and have a rich function set. It would take ages (if ever) to do such a high quality library on my own.
To further cite the NCalc website, you can even use variables like e.g.:
Expression e = new Expression("Round(Pow([Pi], 2) + Pow([Pi2], 2) + [X], 2)");
e.Parameters["Pi2"] = new Expression("Pi * [Pi]");
e.Parameters["X"] = 10;
e.EvaluateParameter +=
delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());

Related

c# how to convert char to VirtualKeyCode?

I've been looking over here, but usually question is other way roud "how to convert virtualkey to char".
So I need to ask how to convert char into virtualkeycode?
I can perfectly fine work with F1, Ctrl etc., but can't figure out how to convert A to VK_A etc. in some convenient way.
I'm trying to let external configuration file hold some variables which then have to be used as virtualkeycodes in actual application.
I can recognize pairs like
Alt+F2, Shift+Control+F1 ... etc.
As those are just Enum 0-12 and then VirtualKeyCode.F1 + index
But I can't figure out those
Alt+F, Shift+Control+A ... etc.
I'm probably missing something very straightforward but unfortunately i can't see it.
Thanks
Edit:
Thanks to help from here I'm now able to convert "Ctrl+X" or "Shift-A" into VirtualKeyCode with this bit of code (still more like testing code)
public static void ParseKeys(string text)
{
Key key = 0;
Key mod = 0;
int current = 0;
string[] result;
string[] separators = new string[] { "+", "-" };
result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
foreach (string entry in result)
{
if (entry.Trim() == Keys.Control.ToString() || entry.Trim() == "Ctrl")
mod = Key.LeftCtrl;
if (entry.Trim() == Keys.Alt.ToString())
mod = Key.LeftAlt;
if (entry.Trim() == Keys.Shift.ToString())
mod = Key.LeftShift;
if (entry.Trim() == Keys.LWin.ToString() && current != result.Length - 1)
mod = Key.LWin;
current++;
}
KeysConverter keyconverter = new KeysConverter();
key = (Key)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
var vmod = KeyInterop.VirtualKeyFromKey(mod);
System.Diagnostics.Trace.WriteLine((VirtualKeyCode)vmod + " = " + (VirtualKeyCode)key);
}
usage
ParseKeys("Alt+X");
I found out I would need to handle combinations like "Alt+Ctrl+X" or "Ctrl+X+Q" but indeed this code is for A+B combo. Can somebody please suggest some elegant solution to have at the end this:
VirtualKeyCode[] outsequence = { VirtualKeyCode.A , VirtualKeyCode.B, VirtualKeycode.C }
?
Thanks!

Converting string to function

I want to build in my application the possibility of drawing mathematical functions. In the plotting library that I'm using (OxyPlot) there is a great support for that. See this example:
y = ax³ + bx² + cx + d = 0
is being plotted this way:
new FunctionSeries( x => a*x*x*x + b*x*x + c*x + d, /* other stuff, spacing, number of points, etc */ )
Trigonometrical functions are done the same way:
y = sin(3x) + 5cos(x)
is
new FunctionSeries(x => Math.Sin(3*x) + 5*Math.Cos(x) , ....);
I would be very happy if someone could guide me in the conversion between a string (written in a textbox for example) and a call of a method that has inside the syntax shown.
EDIT: the first parameter in the FunctionSeries(a, ....) a is Func<double, double>
EDIT2: Is there a way to say to the compiler, hey, believe me "x => 5*x*x" is a Func, take it literally
something like :
Func<double, double> f = (Func<double, double>)myString;
Here I have a partial solution:
var expresionData = new List<DataPoint>();
Regex pattern = new Regex("[x]");
for (int i = 0; i < 100; i++)
{
string a = pattern.Replace(ExpresionString, i.ToString());
NCalc.Expression exp = new NCalc.Expression(a);
expresionData.Add(new DataPoint(i,Double.Parse(exp.Evaluate().ToString())));
}
I'm doing a little trick here: I transform each 'x' in the typed string to i, then I evaluate the expression and add the point. It's pretty slow. I'm still very interested in the original question:
How to transform a string to Func<double, double> (or just make the compiler take it literally).

Most efficient method to create all the letters in the alphabet into a string [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Generating an array of letters in the alphabet in C#
(Theoretical question only, was just pondering it as a writing a filtering system (not using an alphabet, but got me thinking)).
So lets say I want to create a filter list of all the capital letters (A-Z) in the English alphabet plus the word "All"
All A B C D E ... X Y Z
And convert it to a List<string> what is the most efficient way to do this in C# Without using the hard coded {"A","B"} method.
Not a duplicate of This question
The question listed above deals with conversion to a plain and simple character array, which wouldn't allow for the ALL portion. And to take that and convert I believe would involve at least a copy + cast.
For 'most efficient' you would try to avoid List<> and LINQ.
var sb = new StringBuilder("All", 26+3 +spare);
for (char c = 'A'; c <= 'Z'; c++) sb.Append(c);
string result = sb.ToString();
but to be honest you would have to benchmark the various answers here.
You can also do it with actual characters:
List<string> characters = new List<string>();
for (char c = 'A'; c <= 'Z'; c++)
characters.Add("" + c);
Each string character is a char value that has a number an ascii. Capital A starts at 65 and Captial Z is 90. Thus using a loop you can generate the values.
List<string> alpha = new List<string>();
for(int i=65; i <=90; i++) {
alpha.add(""+(char)i);
}
EDIT:
You could also use the character literals for the for loop as
for(int i = (int)'A'; i <= (int)'Z'; i++)
For example:
var alphabet = new List<String>(27);
var capitalRange = Enumerable.Range(0, 26)
.Select(i => new String(Convert.ToChar(i + 65), 1));
alphabet.AddRange( capitalRange );
alphabet.Add("All");
Note that the initialization of the list with the correct capacity ensures that it doesn't need to be resized and won't be oversized. Apart from that this is similar to a for-loop.
The string constuctor is slightly faster than a Char.ToString().
Here is a fairly compact way to do it:
var list = new[] { "All" }.Concat(
Enumerable.Range('A', 'Z' - 'A' + 1)
.Select(c => ((char)c).ToString())
).ToList();
But something like this is cleaner (IMO) and more efficient since there is no resizing:
const char start_ch = 'A';
const char end_ch = 'Z';
var list = new List<string>(end_ch - start_ch + 1) { "All" };
for (char ch = start_ch; ch <= end_ch; ++ch)
list.Add(ch.ToString());
What exactly do you intend to do with this List? For example, searching can be more efficiently done using an associative data structure instead, such as HashSet or Dictionary.

String Fraction to Double

I need a function to parse a user inputs of numbers to doubles. I cannot do anything client side or change how the input comes in.
Input | Desired Output
"9" | 9
"9 3/4" | 9.75
" 9 1/ 2 " | 9.5
"9 .25" | 9.25
"9,000 1/3" | 9000.33
"1/4" | .25
I saw this post, but it uses Python, I was just wondering if anybody knew any fancy C# ways of handling this before I spend time to write my own.
I would use regular expressions for this one:
Regex re = new Regex(#"^\s*(\d+)(\s*\.(\d*)|\s+(\d+)\s*/\s*(\d+))?\s*$");
string str = " 9 1/ 2 ";
Match m = re.Match(str);
double val = m.Groups[1].Success ? double.Parse(m.Groups[1].Value) : 0.0;
if(m.Groups[3].Success) {
val += double.Parse("0." + m.Groups[3].Value);
} else {
val += double.Parse(m.Groups[4].Value) / double.Parse(m.Groups[5].Value);
}
Untested, as of yet, but I think it should work.
Here's a demo, and here's another demo.
There is nothing built in the BCL that will do this, but there are plenty of existing mathematical expression parsers that will (though this may be over the top for this specific situation).
Writing one yourself, for the limited use cases you have posted shouldn't be difficult.
I see two sections. Everything before the first space is the integral section. Everything after the first space is the fractional section. After you separate the two sections, you can just strip spaces from the fractional section, split that section on the / character, and divide the first part by the 2nd part (if there is a 2nd part). Then add the result to the integral section to find your answer.
This algorithm should give a correct result for each of your samples. It might also give an incorrect result for samples like these: "9 .25/4" or "9 3/0", so those are things to watch for. Other things include leading whitespace, whether you want to allow other whitespace, currency symbols, whether "9.25" (no spaces) is a valid input, and what to do with irrational fractions like "1/3", "1/10" (irrational in binary), etc.
I'm not normally a huge believer in test driven design (that you should write the tests first and go for 100% coverage) for static-typed languages, but I do think unit tests have value in certain specific situations, and this is one of those situations. I would put together a few tests for both some common and edge cases, such that you can be sure whatever you end up with handles the inputs correctly to pass the tests.
Here's what I ended up using:
private double ParseDoubleFromString(string num)
{
//removes multiple spces between characters, cammas, and leading/trailing whitespace
num = Regex.Replace(num.Replace(",", ""), #"\s+", " ").Trim();
double d = 0;
int whole = 0;
double numerator;
double denominator;
//is there a fraction?
if (num.Contains("/"))
{
//is there a space?
if (num.Contains(" "))
{
//seperate the integer and fraction
int firstspace = num.IndexOf(" ");
string fraction = num.Substring(firstspace, num.Length - firstspace);
//set the integer
whole = int.Parse(num.Substring(0, firstspace));
//set the numerator and denominator
numerator = double.Parse(fraction.Split("/".ToCharArray())[0]);
denominator = double.Parse(fraction.Split("/".ToCharArray())[1]);
}
else
{
//set the numerator and denominator
numerator = double.Parse(num.Split("/".ToCharArray())[0]);
denominator = double.Parse(num.Split("/".ToCharArray())[1]);
}
//is it a valid fraction?
if (denominator != 0)
{
d = whole + (numerator / denominator);
}
}
else
{
//parse the whole thing
d = double.Parse(num.Replace(" ", ""));
}
return d;
}
It doesn't look very difficult to write some code that would do this. First try removing all spaces and see if it's a legal number. If it's not, find the legal numbers (such as 9, 3, 4 in "9 3/4" and do a simple arithmetic operation: 9 + 3 / 4 = 9.75
I wrote this method for this work:
private double DoWork(string data)
{
double final = 0;
foreach (string s in data.Split(' '))
{
if (s.Contains('/'))
{
final += double.Parse(s.Split('/')[0]) / double.Parse(s.Split('/')[1]);
}
else
{
double tryparse = 0;
double.TryParse(s, out tryparse);
final += tryparse;
}
}
return final;
}
Is it useful to you ?
I think you can also use the dynamically compiling code
static void Main(string[] args)
{
var value = "9 3/4";
value = value.Split(' ')[0] + "d + " + value.Split(' ')[1] + "d";
var exp = " public class DynamicComputer { public static double Eval() { return " + value + "; }}";
CodeDomProvider cp = new Microsoft.CSharp.CSharpCodeProvider();
ICodeCompiler icc = cp.CreateCompiler();
CompilerParameters cps = new CompilerParameters();
CompilerResults cres;
cps.GenerateInMemory = true;
cres = icc.CompileAssemblyFromSource(cps, exp);
Assembly asm = cres.CompiledAssembly;
Type t = asm.GetType("DynamicComputer");
double d = (double)t.InvokeMember("Eval",
BindingFlags.InvokeMethod,
null,
null,
null);
Console.WriteLine(d);
Console.Read();
}
Solution below won't work for negative fractions. Can be improved by changing
//is it a valid fraction?
if (denominator != 0)
{
d = whole + (numerator / denominator);
}
to
//is it a valid fraction?
if (denominator != .0)
{
var sign = Math.Sign(whole);
d = whole + sign*(numerator/denominator);
}

c# longest common words sample

i am looking for a longest common words c# implementation. Most of the samples i have came across are comparing character by character.
in otherwords,
string1 = access
string2 = advised
should return null output from the function
any sample codes?
I think this problem is usually referred to as the Longest common substring problem. The Wikipedia article contains pseudocode, and C# implementations can be found on the Web.
If by word you mean these letter things, seperated from the others by punktuation, try this:
private String longestCommonWord(String s1, String s2)
{
String[] seperators = new String[] { " ", ",", ".", "!", "?", ";" };
var result = from w1 in s1.Split(seperators, StringSplitOptions.RemoveEmptyEntries)
where (from w2 in s2.Split(seperators, StringSplitOptions.RemoveEmptyEntries)
where w2 == w1
select w2).Count() > 0
orderby w1.Length descending
select w1;
if (result.Count() > 0)
{
return result.First();
}
else
{
return null;
}
}
This probably is not the most elegant way to do it, but it works for me. =)
Turning the algorithm which computes LCS of arrays of characters into one that does it to arrays of anything else -- like, say, an array of words -- is usually pretty straightforward. Have you tried that?
If you need some hints, here's an article I wrote a couple years ago on how to implement Longest Common Subsequence on an array of words in JScript. You should be able to adapt it to C# without too much difficulty.
http://blogs.msdn.com/ericlippert/archive/2004/07/21/189974.aspx
Finding differences in strings is called the Longest Common Subsequence problem. The following is a generic solution to the LCS problem, written in C#:
static int[,] GetLCSDifferenceMatrix<T>(
Collection<T> baseline,
Collection<T> revision)
{
int[,] matrix = new int[baseline.Count + 1, revision.Count + 1];
for (int baselineIndex = 0; baselineIndex < baseline.Count; baselineIndex++)
{
for (int revisionIndex = 0; revisionIndex < revision.Count; revisionIndex++)
{
if (baseline[baselineIndex].Equals(revision[revisionIndex]))
{
matrix[baselineIndex + 1, revisionIndex + 1] =
matrix[baselineIndex, revisionIndex] + 1;
}
else
{
int possibilityOne = matrix[baselineIndex + 1, revisionIndex];
int possibilityTwo = matrix[baselineIndex, revisionIndex + 1];
matrix[baselineIndex + 1, revisionIndex + 1] =
Math.Max(possibilityOne, possibilityTwo);
}
}
}
return matrix;
}
This code gives you a "difference" matrix, which can then be used to construct the difference from the two inputs. For unit tests and example usage, see http://sethflowers.com/2012/01/18/basic-diff-with-a-generic-solution-to-the-longest-common-subsequence-problem.html.

Categories