Code Smell in Dynamic Expression - c#

This code solves an interesting puzzle outlined in http://www.programgood.net/2011/01/13/DynamicOperatorsGuernseyChallenge.aspx
Problem: There seems to be lots of repeating here.. DRY (Don't Repeat Yourself) principle springs to mind here. Anyone see a refactor?
string opZ = "";
string opA = "";
string opB = "";
string opC = "";
string opD = "";
for (int h = 1; h <= 2; h++) // making the first number positive or negative
{
if (h == 1) opZ = "";
if (h == 2) opZ = "-";
for (int i = 1; i <= 4; i++)
{
if (i == 1) opA = "*";
if (i == 2) opA = "/";
if (i == 3) opA = "+";
if (i == 4) opA = "-";
for (int j = 1; j <= 4; j++)
{
if (j == 1) opB = "*";
if (j == 2) opB = "/";
if (j == 3) opB = "+";
if (j == 4) opB = "-";
for (int k = 1; k <= 4; k++)
{
if (k == 1) opC = "*";
if (k == 2) opC = "/";
if (k == 3) opC = "+";
if (k == 4) opC = "-";
for (int l = 1; l <= 4; l++)
{
if (l == 1) opD = "*";
if (l == 2) opD = "/";
if (l == 3) opD = "+";
if (l == 4) opD = "-";
string expression = opZ + 1 + opA + 3 + opB + 5 + opC + 7 + opD + 9;
DataTable dummy = new DataTable();
double result = Convert.ToDouble(dummy.Compute(expression, string.Empty));
if (result == 3)
Debug.WriteLine(expression + " = 3");
if (result == 47)
Debug.WriteLine(expression + " = 47");
if (result == 18)
Debug.WriteLine(expression + " = 18");
}
}
}
}
}

Well, the first obvious refactoring would be to have an array of operators:
String[] operators = { null, "*", "/", "+", "-" };
Then use:
opC = operators[j]; // etc
(Personally I'd use loops going from 0 to 3 instead of 1 to 4 - that's more idiomatic IMO, but that's a different matter.)
Then there's the way of building the permutations. I'd actually use LINQ for this:
string[] prefixes = { "", "-" };
string[] operators = { "*", "/", "+", "-" };
var expressions = from prefix in prefixes
from opA in operators
from opB in operators
from opC in operators
from opD in operators
select prefix + 1 + opA + 3 + opB + 5 + opC + 7 + opD + 9;
foreach (string expression in expressions)
{
...
}

char[] ops = new [] {'*','/','+','-'};
foreach(string opA in ops)
foreach(string opB in ops)
foreach(string opC in ops)
foreach(string opD in ops)
foreach(string opZ in new []{'-',' '}) {
string expression = opZ + 1 + opA + 3 + opB + 5 + opC + 7 + opD + 9;
DataTable dummy = new DataTable();
double result = Convert.ToDouble(dummy.Compute(expression, string.Empty));
if (result == 3)
Debug.WriteLine(expression + " = 3");
if (result == 47)
Debug.WriteLine(expression + " = 47");
if (result == 18)
Debug.WriteLine(expression + " = 18");
}

I suppose there's no real point doing this while using DataTable.Compute, but
var calculator = new DataTable () ;
var operators = "*/+-" ;
for (int i = 0 ; i < 0x200 ; ++i)
{
var value = calculator.Compute (String.Format ("{0}1{1}3{2}5{3}7{4}9",
(i & 0x100) != 0 ? "-" : "",
operators[(i >> 0) & 3],
operators[(i >> 2) & 3],
operators[(i >> 4) & 3],
operators[(i >> 6) & 3]), String.Empty) ;
...
}
Otherwise, this will definitely be faster if somewhat more abstruse:
var opstrings = "+-*/" ;
var operators = new Func<int, int, int>[] {
(a, b) => a + b,
(a, b) => a - b,
(a, b) => a * b,
(a, b) => a / b, } ;
for (int i = 0 ; i < 0x200 ; ++i)
{
var stack = 0 ; // seed value
var last = 0 ; // imitate + for lowest precedence
var value =(i & 0x100) != 0 ? -1 : 1 ;
for (int j = 0 ; j < 5 ; ++j) // extra item to force last reduction
{
var oper = (i >> j * 2) & 3 ; // "input" operator
var input = 3 + j * 2 ; // "input" number
if (oper / 2 <= last / 2) // reduce below top?
{
stack = operators[last] (stack, value) ;
last = oper ; // shift operator
value = input ; // shift number
}
else // reduce top
value = operators[oper] (value, input) ;
}
var result = stack ;
if (result == 3 || result == 47 || result == 18)
Debug.WriteLine ("{0}1{1}3{2}5{3}7{4}9 = {5}",
(i & 0x100) != 0 ? "-" : "",
opstrings[(i >> 0) & 3],
opstrings[(i >> 2) & 3],
opstrings[(i >> 4) & 3],
opstrings[(i >> 6) & 3],
result) ;
}

Related

How to improve for loop performance for xml coloring

I am doing xml coloring for attributes, element, value, comment through code.
For this, I am using nested for loops which degrading the performance for large xml files because with this changes, it is checking character by character and due to this it is taking much time to recognize the target area to add coloring.
Here is the code snippet which I written for recognizing xml attributes, values, e.t.c for coloring.
protected override void OnPropertyChanged(string propertyName)
{
#region MyRegion
var pageTextLines = PageText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
for (int i = 0; i < pageTextLines.Length; i++)
{
int startIndex = -1;
int endIndex = -1;
var thisLine = pageTextLines[i];
for (int j = 0; j < thisLine.Length; j++)
{
bool isComment = false;
bool isValue = false;
if (thisLine[j] == '<')
startIndex = j;
if (thisLine[j] == '>')
endIndex = j;
// Check if we have something like <!-- to flag that we have a comment
if (thisLine[j] == '-')
{
if (j - 2 >= 0 && j + 1 < pageTextLines.Length)
{
if (thisLine[j - 2] == '<' && thisLine[j - 1] == '!' && thisLine[j + 1] == '-')
{
j = j + 1;
startIndex = j - 2;
isComment = true;
}
}
// Check if we have something like --> to see if we're closing a comment
// or if we're at the end
if (j + 2 < thisLine.Length)
{
if (thisLine[j] == '-')
{
if (thisLine[j + 1] == '-' && thisLine[j + 2] == '>')
{
isComment = true;
j += 2;
endIndex = j;
}
}
}
}
if (startIndex != -1 && endIndex != -1)
{
if (isComment)
{
// Coloring the xml comment.
ProcessDataSelection(SelectionLayer.CommentColor,
new DataSelection(new Point(startIndex + 1, i + 1), new Point(endIndex + 1, i + 1), PositionFormat.Characters, true));
startIndex = endIndex = -1;
}
else
{
// Coloring the xml node.
ProcessDataSelection(SelectionLayer.NodeColor,
new DataSelection(new Point(startIndex + 1, i + 1), new Point(endIndex + 1, i + 1), PositionFormat.Characters, true));
startIndex = endIndex = -1;
for (int k = 0; k < thisLine.Length; k++)
{
if (thisLine[k] == ' ')
startIndex = k;
if (thisLine[k] == '=')
endIndex = k;
if (startIndex != -1 && endIndex != -1)
{
// Coloring the xml attribute.
ProcessDataSelection(SelectionLayer.AttributeColor,
new DataSelection(new Point(startIndex + 1, i + 1), new Point(endIndex + 1, i + 1), PositionFormat.Characters, true));
startIndex = endIndex = -1;
}
}
for (int l = 0; l < thisLine.Length; l++)
{
if (thisLine[l] == '>' && l < thisLine.Length - 1)
{
startIndex = l + 1;
isValue = true;
}
if (thisLine[l] == '<' && thisLine[l + 1] == '/')
{
endIndex = l - 1;
isValue = true;
}
if (startIndex != -1 && endIndex != -1)
{
if (isValue)
// Coloring the xml value.
ProcessDataSelection(SelectionLayer.ValueColor,
new DataSelection(new Point(startIndex + 1, i + 1), new Point(endIndex + 1, i + 1), PositionFormat.Characters, true));
startIndex = endIndex = -1;
}
}
}
startIndex = endIndex = -1;
}
}
#endregion
}
Can anyone please suggest me a better way to do this or better way to improve these loops ?

How can i reudce the number if if statments to 2 [duplicate]

This question already has answers here:
Writing FizzBuzz
(47 answers)
Closed 5 years ago.
how do I reduce the number of if statements in this code
for (int i = 1; i < number;i++)
{
if ( i % 3 == 0 && i % 5 != 0)
{
Console.WriteLine(i + " Fizz");
}
else if (i % 5 == 0 && i % 3 != 0)
{
Console.WriteLine(i + " Buzz");
}
else if(i % 3 == 0 && i % 5 == 0)
{
Console.WriteLine(i + " FizzBuzz");
}
else
{
Console.WriteLine(i);
}
}
You could do the following:
for (int i = 1; i < number;i++)
{
Console.WriteLine(string.Format("{0} {1}{2}", i, i % 3 == 0 ? "Fizz":"", i % 5 == 0 ? "Buzz":"");
}
And use no if ;-)
for (int i = 1; i < number;i++)
{
string result = i + " ";
if ( i % 3 == 0)
{
result += "Fizz";
}
if (i % 5 == 0)
{
result += "Buzz";
}
Console.WriteLine(result);
}
This would display for example 1_, 3 Fizz, 5 Buzz, 15 FizzBuzz.
See the javascript equivalent code snippet below :
var number = 20;
for (var i = 1; i < number;i++)
{
var result = i + " ";
if (i % 3 == 0)
{
result += "Fizz";
}
if (i % 5 == 0)
{
result += "Buzz";
}
document.write(result+"<br>");
}
Variables and the conditional operator can help to make code more readable:
for (int i = 1; i < number;i++)
{
bool isMod3 = i % 3 == 0;
bool isMod5 = i % 5 == 0;
string fizz = isMod3 ? "Fizz" : "";
string buzz = isMod5 ? "Buzz" : "";
string result = $"{i} {fizz}{buzz}";
Console.WriteLine(result);
}
Here's another approach that works with even more values(theoretically umlimited):
var modDict = new Dictionary<int, string> { { 3, "Fizz" }, { 5, "Buzz" } };
for (int i = 1; i < number; i++)
{
string text = string.Join("", modDict.Select(kv => i % kv.Key == 0 ? kv.Value : ""));
Console.WriteLine(i + " " + text);
}
you can try conditional operators.
(i % 3 == 0)
? (i % 5 == 0)
? Console.WriteLine(i + " FizzBuzz")
: Console.WriteLine(i + " Fizz");
: (i % 5 == 0)
? Console.WriteLine(i + " Buzz");
: Console.WriteLine(i);
Try:
string str;
for (int i = 1; i < number; i++)
{
str = i + " ";
if (i % 3 == 0)
str += "Fizz";
if (i % 5 == 0)
str += "Buzz";
Console.WriteLine(str.Trim());
}
We can do like below, but it is not good for readability
for (int i = 1; i < number; i++)
{
var x = i % 3 == 0;
var y = i % 5 == 0;
string istr = i.ToString();
string a = x ? (y ? istr + " FizzBuzz"
: istr + " Fizz")
: (y ? istr + " Buzz"
: istr);
Console.WriteLine(a);
}
string output = i % 3 == 0
? ( i % 5 != 0 ? $"{i} Fizz" : $"{i} FizzBuzz" )
: i % 5 == 0 && i % 3 != 0
? $"{i} Buzz"
: i.ToString();
Console.WriteLine( output );

find common substrings in 2 string in c#

I have strings like:
1) Cookie:ystat_tw_ss376223=9_16940400_234398;
2) Cookie:zynga_toolbar_fb_uid=1018132522
3) GET /2009/visuels/Metaboli_120x600_UK.gif HTTP/1.1
4) GET /2010/07/15/ipad-3hk-smv-price-hk/ HTTP/1.1
1 ad 2 have common substtring{cookie:}
3 and 4 have common substtring{GET /20, HTTP/1.1}
I want to find all common substrings that have the length more than three characters(contain space character) between 2 strings.(like 1 and 2)
i want to code in c#. i have a program but it has some problems.
Could anyone help me?
public static string[] MyMCS2(string a, string b)
{
string[] st = new string[100];
// List<string> st = new List<string>();
List<char> f = new List<char>();
int ctr = 0;
char[] str1 = a.ToCharArray();
char[] str2 = b.ToCharArray();
int m = 0;
int n = 0;
while (m < str1.Length)
{
for (n = 0; n < str2.Length; n++)
{
if (m < str1.Length)
{
if (str1[m] == str2[n])
{
if ((m > 1) && (n > 1) &&(str1[m - 1] == str2[n - 1]) && (str1[m - 2] == str2[n - 2]))
{
//f[m]= str1[m];
f.Add(str1[m]);
char[] ff = f.ToArray();
string aaa = new string(ff);
if (aaa.Length >= 3)
{
st[ctr] = aaa + "()";
//st.Add(aaa);
ctr++;
}
kk = m;
m++;
}
else if ((n == 0) ||(n == 1))
{
f.Add(str1[m]);
kk = m;
m++;
}
else
f.Clear();
}
//else if ((str1[m] == str2[n]) && (m == str1.Length - 1) && (n == str2.Length - 1))
//{
// f.Add(str1[m]);
// char[] ff = f.ToArray();
// string aaa = new string(ff);
// if (aaa.Length >= 3)
// {
// st[ctr] = aaa;
// ctr++;
// }
// // m++;
//}
else if ((str1[m] != str2[n]) && (n == (str2.Length - 1)))
{
m++;
}
else if ((m > 1) && (n > 1) && (str1[m] != str2[n]) && (str1[m - 1] == str2[n - 1]) && (str1[m - 2] == str2[n - 2]) && (str1[m - 3] == str2[n - 3]))
{
//
char[] ff = f.ToArray();
string aaa = new string(ff);
if (aaa.Length >= 3)
{
st[ctr] = aaa + "()" ;
//st.Add(aaa);
ctr++;
f.Clear();
}
//f.Clear();
//for (int h = 0; h < ff.Length; h++)
//{
// f[h] = '\0';
//}
}
else if (str1[m] != str2[n])
continue;
}
}
}
//int gb = st.Length;
return st;
}
This is an exact matching problem not a substring. You can solve it with aho-corasick algorithm. Use the first string and compute a finite state machine. Then process the search string. You can extend the aho-corasick algorithm to use a wildcard and search also for substrings. You can try this animated example: http://blog.ivank.net/aho-corasick-algorithm-in-as3.html

ITF Barcode Algorithm

I have this C# ITF/Interleaved 2 of 5 algorithm (from a VB Azalea Software algorithm):
public static string Interleaved25(string input)
{
if (input.Length <= 0) return "";
if (input.Length % 2 != 0)
{
input = "0" + input;
}
string result = "";
//Takes pairs of numbers and convert them to chars
for (int i = 0; i <= input.Length - 1; i += 2)
{
int pair = Int32.Parse(input.Substring(i, 2));
if (pair < 90)
pair = pair + 33;
else if (pair == 90)
pair = pair + 182;
else if (pair == 91)
pair = pair + 183;
else if (pair > 91)
pair = pair + 104;
result = result + Convert.ToChar(pair);
}
//Leading and trailing chars.
return (char)171 + result + (char)172;
}
The problem is that somehow chars with value > 89 all have empty boxes as result (using the ITF font).
I know this is an old question. But here is a solution with checksum:
using System;
public class Program
{
public static void Main()
{
var bcTxt = "0000420876801";//"29902110013"; //"0000420876801";
int prod1 = 0;
int prod2 = 0;
string Txt1 = "";
string Txt2 = "";
Txt1 = bcTxt;
// Berechnen der Prüfziffer, wenn ungerade Anzahl von Zeichen
if (Txt1.Length % 2 == 1)
{
for (int i = 0; i < Txt1.Length; i++)
{
prod1 += int.Parse(Txt1.Substring(i, 1)) * 3;
if (i < Txt1.Length -1)
{
prod1 += int.Parse(Txt1.Substring(i + 1, 1));
i += 1;
}
Console.WriteLine(prod1);
}
Console.WriteLine(prod1);
prod2 = prod1 % 10;
Console.WriteLine(prod2);
if (prod2 == 0)
{
prod2 = 10;
}
prod2 = 10 - prod2;
Txt1 += (char)(prod2 + 48);
Console.WriteLine(Txt1);
}
//Ascii Zeichen zuordnen
//beim Code 2/5 werden die Zeichen paarweise zugeordnet
Txt2 = ((char)34).ToString();
string Tmp = "";
for (int i = 0; i < Txt1.Length; i++)
{
Tmp += Txt1.Substring(i, 2);
i += 1;
if (int.Parse(Tmp) > 91)
{
Txt2 += ((char)(int.Parse(Tmp) + 70)).ToString();
}
else
{
Txt2 += ((char)(int.Parse(Tmp) + 36)).ToString();
}
Tmp = "";
}
Txt2 += ((char)35).ToString();
Console.WriteLine(Txt2);
}
}
While typing this question, I got the answer all by myself.
Here is the new code:
if (pair < 90)
pair = pair + 33;
else
{
pair = pair + 71;
}
Basically, all chars between 90 and 99 needs a + 71.
same code in vb6
Public Function DevolverI2of5(ByVal cString As String) as String
Dim i As Integer
If Len(cString) Mod 2 <> 0 Then
cString = "0" & cString
End If
Dim result As String
'Takes pairs of numbers and convert them to chars
For i = 1 To Len(cString) Step 2
Dim pair As Integer
pair = Val(Mid(cString, i, 2))
If pair < 90 Then
pair = pair + 33
Else
pair = pair + 71
End If
result = result & Chr(pair)
Next i
DevolverI2of5 = Chr(171) & result & Chr(172)

how to convert a string to a mathematical expression programmatically

I am a beginner at C#. I am facing a problem while converting a string to a mathematical expression. I have a UI where user can create formula using random formula field. And in another UI user will give input of those formula field.
like for example at first time the formula may be (a+b)^n and another the formula may be ((a+b+c)^n+b).
In my calculation UI for the first time user will give input for a,b,n and for 2nd formula user will give input for a,b,c,n. Can anyone please help me about how to get the result for both of the formula programmatic-ally? Thanks in advance
This is how it should be done:
public class StringToFormula
{
private string[] _operators = { "-", "+", "/", "*","^"};
private Func<double, double, double>[] _operations = {
(a1, a2) => a1 - a2,
(a1, a2) => a1 + a2,
(a1, a2) => a1 / a2,
(a1, a2) => a1 * a2,
(a1, a2) => Math.Pow(a1, a2)
};
public double Eval(string expression)
{
List<string> tokens = getTokens(expression);
Stack<double> operandStack = new Stack<double>();
Stack<string> operatorStack = new Stack<string>();
int tokenIndex = 0;
while (tokenIndex < tokens.Count) {
string token = tokens[tokenIndex];
if (token == "(") {
string subExpr = getSubExpression(tokens, ref tokenIndex);
operandStack.Push(Eval(subExpr));
continue;
}
if (token == ")") {
throw new ArgumentException("Mis-matched parentheses in expression");
}
//If this is an operator
if (Array.IndexOf(_operators, token) >= 0) {
while (operatorStack.Count > 0 && Array.IndexOf(_operators, token) < Array.IndexOf(_operators, operatorStack.Peek())) {
string op = operatorStack.Pop();
double arg2 = operandStack.Pop();
double arg1 = operandStack.Pop();
operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
}
operatorStack.Push(token);
} else {
operandStack.Push(double.Parse(token));
}
tokenIndex += 1;
}
while (operatorStack.Count > 0) {
string op = operatorStack.Pop();
double arg2 = operandStack.Pop();
double arg1 = operandStack.Pop();
operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
}
return operandStack.Pop();
}
private string getSubExpression(List<string> tokens, ref int index)
{
StringBuilder subExpr = new StringBuilder();
int parenlevels = 1;
index += 1;
while (index < tokens.Count && parenlevels > 0) {
string token = tokens[index];
if (tokens[index] == "(") {
parenlevels += 1;
}
if (tokens[index] == ")") {
parenlevels -= 1;
}
if (parenlevels > 0) {
subExpr.Append(token);
}
index += 1;
}
if ((parenlevels > 0)) {
throw new ArgumentException("Mis-matched parentheses in expression");
}
return subExpr.ToString();
}
private List<string> getTokens(string expression)
{
string operators = "()^*/+-";
List<string> tokens = new List<string>();
StringBuilder sb = new StringBuilder();
foreach (char c in expression.Replace(" ", string.Empty)) {
if (operators.IndexOf(c) >= 0) {
if ((sb.Length > 0)) {
tokens.Add(sb.ToString());
sb.Length = 0;
}
tokens.Add(c);
} else {
sb.Append(c);
}
}
if ((sb.Length > 0)) {
tokens.Add(sb.ToString());
}
return tokens;
}
}
Call the class and method like this:
string formula = "type your formula here"; //or get it from DB
StringToFormula stf = new StringToFormula();
double result = stf.Eval(formula);
There are plenty methods for formula evaluation,
take a look. Just take your input, replace a, b, n chars in your string to values provided by user and resolve equation with one of methods mentioned.
i think this is the solution
Expression e = new Expression("((a+b+c)^n+b)");
e.Evaluate();
string input= "(12 + 4 * 6) * ((2 + 3 * ( 4 + 2 ) ) ( 5 + 12 ))";
string str4 = "(" + input`enter code here`.Replace(" ", "") + ")";
str4 = str4.Replace(")(", ")*(");
while (str4.Contains('('))
{
string sub1 = str4.Substring(str4.LastIndexOf("(") + 1);
string sub = sub1.Substring(0, sub1.IndexOf(")"));
string sub2 = sub;
string str21 = sub2.Replace("^", "~^~").Replace("/", "~/~").Replace("*", "~*~").Replace("+", "~+~").Replace("-", "~-~");
List<string> str31 = str21.Split('~').ToList();
while (str31.Count > 1)
{
while (str31.Contains("*"))
{
for (int i = 0; i < str31.Count; i++)
{
if (str31[i] == "*")
{
val = Convert.ToDouble(str31[i - 1]) * Convert.ToDouble(str31[i + 1]);
str31.RemoveRange(i - 1, 3);
str31.Insert(i - 1, val.ToString());
}
}
}
while (str31.Contains("/"))
{
for (int i = 0; i < str31.Count; i++)
{
if (str31[i] == "/")
{
val = Convert.ToDouble(str31[i - 1]) / Convert.ToDouble(str31[i + 1]);
str31.RemoveRange(i - 1, 3);
str31.Insert(i - 1, val.ToString());
}
}
}
while (str31.Contains("+"))
{
for (int i = 0; i < str31.Count; i++)
{
if (str31[i] == "+")
{
val = Convert.ToDouble(str31[i - 1]) + Convert.ToDouble(str31[i + 1]);
str31.RemoveRange(i - 1, 3);
str31.Insert(i - 1, val.ToString());
}
}
}
while (str31.Contains("-"))
{
for (int i = 0; i < str31.Count; i++)
{
if (str31[i] == "-")
{
val = Convert.ToDouble(str31[i - 1]) - Convert.ToDouble(str31[i + 1]);
str31.RemoveRange(i - 1, 3);
str31.Insert(i - 1, val.ToString());
}
}
}
}
str4 = str4.Replace("(" + sub + ")", str31[0].ToString());
}
string sum = str4;
The most structural approach which comes to my mind would be to define a grammar consisting out of operator symbols (which are apparently +,-,*,/ and ^ in your case) and operands; then, if a derivation of the input in the defined grammar exists, the derivation basically is the expression tree which can then be traversed recursively while the operators are directry translated to the actual operations. I admit that the description is a bit vague, but good parsing can be a bit difficult. Perhaps a look at LL parser can help a bit.
convert String To Mathematical Expression
var s3 = "3 - 4 + 5 * 9"
var s4 = NSExpression(format: s3).expressionValue(with: nil, context: nil) as! Double // 44.0
Answer : 44

Categories

Resources