I am trying for the last few hours on how to parse a string with algebric notation.
For example if I have the input:
X+8X-21X+21X+16
The output should be:
9X+16
so far if I tried to see if there exists a number behind X and tried many cases, however I keep on getting an index out of bounds error, and rightufully so. Any suggestions on how to fix it?
int getXPosition= LHSString.IndexOf("X");
int noOfXs = LHSString.Split('X').Length - 1;
int XCount = 0;
if (getXPosition > -1)
{
while (XCount <= noOfXs)
{
int posX = getPositionX(s);
Regex noBeforeX = new Regex(#"\d+");
if ((posX - 1) > -1 && noBeforeX.IsMatch(LHSString.Substring(posX-1,1)))
{
string getNumber = LHSString.Substring(posX-1, 1);
sum += Convert.ToInt32(getNumber);
}
if ((posX - 2) > -1 && noBeforeX.IsMatch(LHSString.Substring(posX - 2, 1)))
{
string gotNumber = LHSString.Substring(posX - 1, 1);
int Number=Convert.ToInt32(gotNumber);
sum += Number;
}
XCount++;
s = s.Substring(posX + 1);
}
}
I would use a more maintainable approach. separate different code parts and use collection of class that will represent the "part" in the algebraic equation.
here is my suggestion:
class Program
{
static void Main(string[] args)
{
string[] operators = { "+", "-", "/", "*" };
string test = "X+8X-21X+21X+16";
int locationcounter = 0;
string part = string.Empty;
List<Part> partsList = new List<Part>();
for (int i = 0; i < test.Length; i++)
{
if (operators.Contains(test[i].ToString()))
{
var operatorbeofore = (partsList.Count <= 0 ? "" : partsList[partsList.Count - 1].OperatorAfter);
partsList.Add(new Part(part, operatorbeofore, test[i].ToString(), locationcounter));
locationcounter++;
part = string.Empty;
}
else
{
part += test[i].ToString();
}
}
// last part that remain
if (part != string.Empty)
{
partsList.Add(new Part(part, partsList[partsList.Count() - 1].OperatorAfter, "", locationcounter++));
}
// output
Console.WriteLine(GetResultOutput(partsList));
Console.ReadLine();
}
private static string GetResultOutput(List<Part> algebraicexpression)
{
// reduce all vars
var vars = algebraicexpression.Where(x => x.IsVar).OrderBy(x => x.locationInEqution).ToList();
int lastVarResult = 0;
int varResult = 0;
if (vars.Count() > 1)
{
lastVarResult = GetCalculation(vars[0].Value, vars[1].Value, vars[1].OperatorBefore);
for (int i = 2; i < vars.Count(); i++)
{
varResult = GetCalculation(lastVarResult, vars[i].Value, vars[i].OperatorBefore);
lastVarResult = varResult;
}
}
else if (vars.Count() == 1)
{
lastVarResult = vars[0].Value;
}
// calculate all "free" numbers
var numbers = algebraicexpression.Where(x => x.IsVar == false).OrderBy(x => x.locationInEqution).ToList();
int lastResult = 0;
int Result = 0;
if (numbers.Count() > 1)
{
lastResult = GetCalculation(vars[0].Value, vars[1].Value, vars[1].OperatorBefore);
for (int i = 2; i < vars.Count(); i++)
{
Result = GetCalculation(lastResult, vars[i].Value, vars[i].OperatorBefore);
lastResult = varResult;
}
}
else if (numbers.Count() == 1)
{
Result = numbers[0].Value;
}
string stringresult = string.Empty;
if (varResult != 0)
{
stringresult = varResult.ToString() + vars[0].Notation;
}
if (Result > 0)
{
stringresult = stringresult + "+" + Result.ToString();
}
else if (Result < 0)
{
stringresult = stringresult + "-" + Result.ToString();
}
return stringresult;
}
private static int GetCalculation(int x, int y, string eqoperator)
{
if (eqoperator == "+")
{
return x + y;
}
else if (eqoperator == "-")
{
return x - y;
}
else if (eqoperator == "*")
{
return x * y;
}
else if (eqoperator == "/")
{
return x / y;
}
else
{
return 0;
}
}
}
class Part
{
public string MyAlgebricPart;
public string OperatorBefore;
public string OperatorAfter;
public int locationInEqution;
public Part(string part, string operatorbefore, string operatorafter, int location)
{
this.MyAlgebricPart = part;
this.OperatorAfter = operatorafter;
this.OperatorBefore = operatorbefore;
this.locationInEqution = location;
}
public int Value
{
get
{
if (MyAlgebricPart.Count() == 1 && Notation != string.Empty)
{
return 1;
}
else
{
string result = new String(MyAlgebricPart.Where(Char.IsDigit).ToArray());
return Convert.ToInt32(result);
}
}
}
public string Notation
{
get
{
var onlyLetters = new String(MyAlgebricPart.Where(Char.IsLetter).ToArray());
if (onlyLetters != "")
{
return onlyLetters[0].ToString();
}
else
{
return string.Empty;
}
}
}
public bool IsVar
{
get
{
if (Notation == string.Empty)
return false;
else
return true;
}
}
}
Related
Currently, I am doing a log analyzer for my personal project.
My issue here is that I am new to c# and I have an performance issue with my tool.
Everytime the device(iOS) is interacted, I get an output syslog from a library and it comes in to the output handler.
public void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine, iosSyslogger form, string uuid)
{
string currentPath = System.Environment.CurrentDirectory;
bool exit = false;
if (exit == true) return;
try
{
form.BeginInvoke(new Action(() =>
{
form.insertLogText = outLine.Data;
}));
using (System.IO.StreamWriter file = new System.IO.StreamWriter(currentPath + #"\syslog" + uuid + ".txt", true))
{
file.WriteLine(outLine.Data);
}
}
catch
{
return ;
}
//*Most of the logic for outputing the log should be dealt from this output Handler
}
Then, I write the outline.Data to Data grid view. My concern is that I need to be able to search and filter through data gridview.
Curently I am using visibility = false for search filtering ( if the row does not match the given filter specification I set the row to visibility =false)
This requires the program to traverse the entire datagridview to check whether the condition is met.
Will there be any better way to filter and search within ?
(When I have thousands of lines of row, it takes at least 20 seconds to process it)
Below is the code for filtering, and searching through the results function.
private void searchResult(string term)
{
if (term != null)
{
int i = 0;
while (i < dataGridView1.Rows.Count - 1)
{
if (dataGridView1.Rows[i].Cells[3] == null)
{
i++;
continue;
}
if (dataGridView1.Rows[i].Visible == false)
{
i++;
continue;
}
else if (dataGridView1.Rows[i].Cells[2].Value.ToString().Contains(term) || dataGridView1.Rows[i].Cells[3].Value.ToString().Contains(term) || dataGridView1.Rows[i].Cells[4].Value.ToString().Contains(term))
{
string multirow = dataGridView1.Rows[i].Cells[5].Value.ToString();
int count = Convert.ToInt32(multirow);
if (count > 0)
{
int z = 0;
for (z = 0; z <= count; z++)
{
dataGridView1.Rows[i + z].Visible = true;
}
i = i + z;
}
else
{
dataGridView1.Rows[i].Visible = true;
i++;
}
}
else
{
dataGridView1.Rows[i].Visible = false;
i++;
}
}
}
}
public filteringThelist(){
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
dataGridView1.Rows[i].Visible = false;
int count1,count2,count3=0;
count1 = 1;
count2 = 1;
count3 = 1;
int z = 0;
foreach (KeyValuePair<string, string> entry in totalSelected)
{
if (entry.Value == "devicename" && dataGridView1.Rows[i].Cells[1].Value != null)
{
if (dataGridView1.Rows[i].Cells[1].Value.ToString().Trim().Equals(entry.Key.Trim()))
{
string multirow1 = dataGridView1.Rows[i].Cells[5].Value.ToString();
int counts = Convert.ToInt32(multirow1);
if (counts > 0)
{
for (z = 0; z < counts; z++)
{
dataGridView1.Rows[i + z].Visible = true;
}
}
else
{
dataGridView1.Rows[i].Visible = true;
}
}
else if (devicename.CheckedItems.Count > 1&&count1!= devicename.CheckedItems.Count)
{
count1++;
continue;
}
else
{
dataGridView1.Rows[i].Visible = false;
break;
}
}
else if (entry.Value == "process" && dataGridView1.Rows[i].Cells[2].Value != null)
{
if (dataGridView1.Rows[i].Cells[2].Value.ToString().Trim().Equals(entry.Key.Trim()))
{
string multirow1 = dataGridView1.Rows[i].Cells[5].Value.ToString();
int counts = Convert.ToInt32(multirow1);
if (counts > 0)
{
for (z = 0; z < counts; z++)
{
dataGridView1.Rows[i + z].Visible = true;
}
}
else
{
dataGridView1.Rows[i].Visible = true;
}
}
else if (processlistname.CheckedItems.Count > 1 && count2 != processlistname.CheckedItems.Count)
{
count2++;
continue;
}
else
{
dataGridView1.Rows[i].Visible = false;
break;
}
}
else if (entry.Value == "loglevel" && dataGridView1.Rows[i].Cells[3].Value != null)
{
if (dataGridView1.Rows[i].Cells[3].Value.ToString().Trim().Contains(entry.Key.Trim()))
{
string multirow1 = dataGridView1.Rows[i].Cells[5].Value.ToString();
int counts = Convert.ToInt32(multirow1);
if (counts > 0)
{
for (z = 0; z < counts; z++)
{
dataGridView1.Rows[i + z].Visible = true;
}
}
else
{
dataGridView1.Rows[i].Visible = true;
}
continue;
}
else if (loglevelCheckBox.CheckedItems.Count > 1 && count3 != loglevelCheckBox.CheckedItems.Count)
{
count3++;
continue;
}
else
{
dataGridView1.Rows[i].Visible = false;
break;
}
}
// do something with entry.Value or entry.Key
}
string multirow = dataGridView1.Rows[i].Cells[5].Value.ToString();
int count = Convert.ToInt32(multirow);
if (count > 0&& dataGridView1.Rows[i].Visible==false)
{
for (int k = 0; k <= count; k++)
{
dataGridView1.Rows[i + k].Visible = false;
}
}
i = i + z;
}
The performance problem is because your DataGridView is redrawing at each modification.
Don't fill the DataGridView directly from your Data. Rather create a DataTable and bind it to DataGridView with a BindingSource.
Then use the "Filter" property of the binding source to view extracts of dataTable in the DataGridView. The "Filter" property is a string whose content is similar to that of a WHERE SQL clause.
hi I am calling a static web method from client side
[WebMethod(EnableSession = true)]
public static CrmClientReturn check_CrmClient_Exists_With_CrmClient(string Email, string Password)
{
int result = 0;
try
{
result = CommonFunctions.CheckNumberOfEnters();
then I am trying to establish how many times the user call this method but all the times I get the Session value for counter as null( even after a few attempts ) what am I doing wrong ??
public static int CheckNumberOfEnters()
{
int result = 0;
int counter = 0;
DateTime TimeCounter;
try
{
if (HttpContext.Current.Session["counter"] != null)
{
counter = int.Parse(HttpContext.Current.Session["counter"].ToString());
counter++;
}
else
{
HttpContext.Current.Session.Add("counter", counter);
}
if (counter < int.Parse(ConfigurationManager.AppSettings["LoginTry"].ToString()) + 1)
{
result = 1;
HttpContext.Current.Session["counter"] = counter;
}
else
{
if (counter < int.Parse(ConfigurationManager.AppSettings["LoginTry"].ToString()) + 4)
{
result = -1;
HttpContext.Current.Session["counter"] = counter;
}
else
{
HttpContext.Current.Session["counter"] = counter;
if (HttpContext.Current.Session["TimeCounter"] != null)
{
TimeCounter = DateTime.Parse(HttpContext.Current.Session["TimeCounter"].ToString());
}
else
{
HttpContext.Current.Session.Add("TimeCounter", DateTime.Now);
TimeCounter = DateTime.Now;
}
TimeSpan ts = DateTime.Now - TimeCounter;
if (ts.TotalMinutes >= int.Parse(ConfigurationManager.AppSettings["LogINTryMinuts"].ToString()))
{
HttpContext.Current.Session["TimeCounter"] = null;
result = 1;
counter = 0;
HttpContext.Current.Session["counter"] = counter;
}
else
{
result = 0;
}
}
}
}
catch (Exception ex)
{
ErrorLoging.InsertLogError("BasePage.aspx", "CheckNumberOfEnters fail", ex.ToString(), "", 0);
}
return result;
}
after I upload the code to test site it is working perfectly
but in local host I have the wrong behave
can some one explain it ??
I see the problem, after you increment the counter in the first if block, you need to update the session variable.
Change this:
if (HttpContext.Current.Session["counter"] != null)
{
counter = int.Parse(HttpContext.Current.Session["counter"].ToString());
counter++;
}
to this:
if (HttpContext.Current.Session["counter"] != null)
{
counter = int.Parse(HttpContext.Current.Session["counter"].ToString());
counter++;
HttpContext.Current.Session["counter"] = counter;
}
So, CheckNumberOfEnters should look like this (I have tested it and it is working as expected):
public static int CheckNumberOfEnters()
{
int result = 0;
int counter = 0;
DateTime TimeCounter;
try
{
if (HttpContext.Current.Session["counter"] != null)
{
counter = int.Parse(HttpContext.Current.Session["counter"].ToString());
counter++;
HttpContext.Current.Session["counter"] = counter;
}
else
{
HttpContext.Current.Session.Add("counter", counter);
}
if (counter < int.Parse(ConfigurationManager.AppSettings["LoginTry"].ToString()) + 1)
{
result = 1;
HttpContext.Current.Session["counter"] = counter;
}
else
{
if (counter < int.Parse(ConfigurationManager.AppSettings["LoginTry"].ToString()) + 4)
{
result = -1;
HttpContext.Current.Session["counter"] = counter;
}
else
{
HttpContext.Current.Session["counter"] = counter;
if (HttpContext.Current.Session["TimeCounter"] != null)
{
TimeCounter = DateTime.Parse(HttpContext.Current.Session["TimeCounter"].ToString());
}
else
{
HttpContext.Current.Session.Add("TimeCounter", DateTime.Now);
TimeCounter = DateTime.Now;
}
TimeSpan ts = DateTime.Now - TimeCounter;
if (ts.TotalMinutes >= int.Parse(ConfigurationManager.AppSettings["LogINTryMinuts"].ToString()))
{
HttpContext.Current.Session["TimeCounter"] = null;
result = 1;
counter = 0;
HttpContext.Current.Session["counter"] = counter;
}
else
{
result = 0;
}
}
}
}
catch (Exception ex)
{
ErrorLoging.InsertLogError("BasePage.aspx", "CheckNumberOfEnters fail", ex.ToString(), "", 0);
}
return result;
}
Please use int.TryParse instead of int.Parse
if (HttpContext.Current.Session["counter"] != null)
{
int.TryParse(HttpContext.Current.Session["counter"].ToString(),counter);
counter++;
}
So let me start by saying that I'm a newbie with little to moderate knowledge about C#.
Coming to the topic: I need to make a program that is able to add/subtract very large integers. Initially, used BigInt only to find out it's not allowed. There should be a logical workaround for this? I have an idea which is using "elementary school method" where you add each digit starting from right to left.
I made a string which I split into char array and added each digit from right to left(GetUpperBound-i). But it doesn't seem to work.
My Code:
string s, s2;
char[] c_arr, c_arr2;
int i, erg;
s = "1234";
s2 = "5678";
c_arr = s.ToCharArray();
c_arr2 = s2.ToCharArray();
for (i = 0; i <= c_arr.GetUpperBound(0); i++)
{
erg = c_arr[c_arr.GetUpperBound(0)-i]+c_arr2[c_arr2.GetUpperBound(0)-i];
Console.Write(erg);
}
Console.ReadKey();
There are a few things wrong with your code for the 'elementary school method'. You don't account for carry, you're adding up ascii values rather than actual values between 0-9, and you're outputting the results in the wrong order.
The code below, whilst not very elegant, does produce the correct results:
var s1 = "12345";
var s2 = "5678";
var carry = false;
var result = String.Empty;
if(s1.Length != s2.Length)
{
var diff = Math.Abs(s1.Length - s2.Length);
if(s1.Length < s2.Length)
{
s1 = String.Join("", Enumerable.Repeat("0", diff)) + s1;
}
else
{
s2 = String.Join("", Enumerable.Repeat("0", diff)) + s2;
}
}
for(int i = s1.Length-1;i >= 0; i--)
{
var augend = Convert.ToInt32(s1.Substring(i,1));
var addend = Convert.ToInt32(s2.Substring(i,1));
var sum = augend + addend;
sum += (carry ? 1 : 0);
carry = false;
if(sum > 9)
{
carry = true;
sum -= 10;
}
result = sum.ToString() + result;
}
if(carry)
{
result = "1" + result;
}
Console.WriteLine(result);
The following program can be used to add two large numbers, I have used string builder to store the result. You can add numbers containing digits upto '2,147,483,647'.
Using System;
using System.Text;
using System.Linq;
public class Test
{
public static void Main()
{
string term1="15245142151235123512352362362352351236";
string term2="1522135123612646436143613461344";
StringBuilder sum=new StringBuilder();
int n1=term1.Length;
int n2=term2.Length;
int carry=0;
int n=(n1>n2)?n1:n2;
if(n1>n2)
term2=term2.PadLeft(n1,'0');
else
term1=term1.PadLeft(n2,'0');
for(int i=n-1;i>=0;i--)
{
int value=(carry+term1[i]-48+term2[i]-48)%10;
sum.Append(value);
carry=(carry+term1[i]-48+term2[i]-48)/10;
}
char[] c=sum.ToString().ToCharArray();
Array.Reverse(c);
Console.WriteLine(c);
}
}
string Add(string s1, string s2)
{
bool carry = false;
string result = string.Empty;
if(s1[0] != '-' && s2[0] != '-')
{
if (s1.Length < s2.Length)
s1 = s1.PadLeft(s2.Length, '0');
if(s2.Length < s1.Length)
s2 = s2.PadLeft(s1.Length, '0');
for(int i = s1.Length-1; i >= 0; i--)
{
var augend = Convert.ToInt64(s1.Substring(i,1));
var addend = Convert.ToInt64(s2.Substring(i,1));
var sum = augend + addend;
sum += (carry ? 1 : 0);
carry = false;
if(sum > 9)
{
carry = true;
sum -= 10;
}
result = sum.ToString() + result;
}
if(carry)
{
result = "1" + result;
}
}
else if(s1[0] == '-' || s2[0] == '-')
{
long sum = 0;
if(s2[0] == '-')
{
//Removing negative sign
char[] MyChar = {'-'};
string NewString = s2.TrimStart(MyChar);
s2 = NewString;
if(s2.Length < s1.Length)
s2 = s2.PadLeft(s1.Length, '0');
for (int i = s1.Length - 1; i >= 0; i--)
{
var augend = Convert.ToInt64(s1.Substring(i,1));
var addend = Convert.ToInt64(s2.Substring(i,1));
if(augend >= addend)
{
sum = augend - addend;
}
else
{
int temp = i - 1;
long numberNext = Convert.ToInt64(s1.Substring(temp,1));
//if number before is 0
while(numberNext == 0)
{
temp--;
numberNext = Convert.ToInt64(s1.Substring(temp,1));
}
//taking one from the neighbor number
int a = int.Parse(s1[temp].ToString());
a--;
StringBuilder tempString = new StringBuilder(s1);
string aString = a.ToString();
tempString[temp] = Convert.ToChar(aString);
s1 = tempString.ToString();
while(temp < i)
{
temp++;
StringBuilder copyS1 = new StringBuilder(s1);
string nine = "9";
tempString[temp] = Convert.ToChar(nine);
s1 = tempString.ToString();
}
augend += 10;
sum = augend - addend;
}
result = sum.ToString() + result;
}
//Removing the zero infront of the answer
char[] zeroChar = {'0'};
string tempResult = result.TrimStart(zeroChar);
result = tempResult;
}
}
return result;
}
string Multiply(string s1, string s2)
{
string result = string.Empty;
//For multipication
bool Negative = false;
if(s1[0] == '-' && s2[0] == '-')
Negative = false;
else if(s1[0] == '-' || s2[0] == '-')
Negative = true;
char[] minusChar = {'-'};
string NewString;
NewString = s2.TrimStart(minusChar);
s2 = NewString;
NewString = s1.TrimStart(minusChar);
s1 = NewString;
List<string> resultList = new List<string>();
for(int i = s2.Length - 1; i >= 0; i--)
{
string multiplycation = string.Empty;
for (int j = s1.Length - 1; j >= 0; j--)
{
var augend = Convert.ToInt64(s1.Substring(j,1));
var addend = Convert.ToInt64(s2.Substring(i,1));
long multiply = augend * addend;
// print(multiply);
multiplycation = multiply.ToString() + multiplycation;
}
//Adding zero at the end of the multiplication
for (int k = s2.Length - 1 - i; k > 0; k--)
{
multiplycation += "0";
}
resultList.Add(multiplycation);
}
for (int i = 1; i < resultList.Count; i++)
{
resultList[0] = Add(resultList[0],resultList[i]);
}
//Finally assigning if negative negative sign in front of the number
if(Negative)
result = resultList[0].Insert(0,"-");
else
result = resultList[0];
return result;
}
string Divide(string dividend, string divisor)
{
string result = string.Empty;
int remainder = 0;
int intNumberstoGet = divisor.Length;
int currentInt = 0;
int dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
int intDivisor = int.Parse(divisor);
while(currentInt < dividend.Length)
{
if(dividing == 0)
{
currentInt++;
result += "0";
}
else
{
while(dividing < intDivisor)
{
intNumberstoGet++;
dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
}
if (dividing > 0)
{
remainder = dividing % intDivisor;
result += ((dividing - remainder) / intDivisor).ToString();
intNumberstoGet = 1;
if(currentInt < dividend.Length - 2)
currentInt += 2;
else
currentInt++;
if(currentInt != dividend.Length)
{
dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
remainder *= 10;
dividing += remainder;
}
}
}
}
return result;
}
Here you go. Another example. It's 10 to 30 times faster than the accepted answer.
static string AddNumStr(string v1, string v2)
{
var v1Len = v1.Length;
var v2Len = v2.Length;
var count = Math.Max(v1Len, v2Len);
var answ = new char[count + 1];
while (count >= 0) answ[count--] = (char)((v1Len > 0 ? v1[--v1Len] & 0xF:0) + (v2Len>0 ? v2[--v2Len]&0xF : 0));
for (var i = answ.Length - 1; i >= 0; i--)
{
if (answ[i] > 9)
{
answ[i - 1]++;
answ[i] -= (char)10;
}
answ[i] = (char)(answ[i] | 48);
}
return new string(answ).TrimStart('0');
}
Below SO question has some interesting approaches. Though the answer is in Java, but you will surely get to know what needs to be done.
How to handle very large numbers in Java without using java.math.BigInteger
public static int[] addTwoNumbers(string s1, string s2)
{
char[] num1 = s1.ToCharArray();
char[] num2 = s2.ToCharArray();
int sum = 0;
int carry = 0;
int size = (s1.Length > s2.Length) ? s1.Length + 1 : s2.Length + 1;
int[] result = new int[size];
int index = size - 1;
int num1index = num1.Length - 1;
int num2index = num2.Length - 1;
while (true)
{
if (num1index >= 0 && num2index >= 0)
{
sum = (num1[num1index]-'0') + (num2[num2index]-'0') + carry;
}
else if(num1index< 0 && num2index >= 0)
{
sum = (num2[num2index]-'0') + carry;
}
else if (num1index >= 0 && num2index < 0)
{
sum = (num1[num1index]-'0') + carry;
}
else { break; }
carry = sum /10;
result[index] = sum % 10;
index--;
num1index--;
num2index--;
}
if(carry>0)
{
result[index] = carry;
}
return result;
}
as all newbies to the searching algorithms, i am working on an example of the old fashion 8-problem puzzle, i have done the breadth first algorithm which is in the code below, and i was wondering how can convert it to the depth first limited search.
how can I convert from the breadth first algorithm to the depth first limited search algorithm??
code :
class BFS
{
int[] GoalState = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
private Queue<Node> Frontier;
private HashSet<Node> Solution;
private Node RootNode;
public BFS(int[] StartState)
{
this.RootNode = new Node(StartState, -1, "\0");
Solution = new HashSet<Node>();
Frontier = new Queue<Node>();
}
public void Solve()
{
Node ActiveNode = RootNode;
bool IsSolved = false;
while (!IsGoalState(ActiveNode.GetState()))
{
Solution.Add(ActiveNode);
foreach (Node successor in GenerateSuccessor(ActiveNode))
{
Frontier.Enqueue(successor);
if (IsGoalState(successor.GetState()))
{
IsSolved = true;
Solution.Add(successor);
break;
}
}
if (IsSolved)
break;
ActiveNode = Frontier.Dequeue();
}
WriteSolution();
}
public IEnumerable<Node> GenerateSuccessor(Node ParentNode)
{
int[] ParentState = ParentNode.GetState();
int EmptySpacePosition = 0;
int temp;
for (int x = 0; x < 9; x++)
{
if (ParentState[x] == 0)
{
EmptySpacePosition = x;
break;
}
}
//Can move empty space to LEFT?
if (EmptySpacePosition != 0 && EmptySpacePosition != 3 && EmptySpacePosition != 6)
{
int[] _State = (int[])ParentState.Clone();
_State[EmptySpacePosition] = _State[EmptySpacePosition - 1];
_State[EmptySpacePosition - 1] = 0;
yield return new Node(_State, ParentNode.GetId(), "Left ");
}
//Can move empty space to RIGHT?
if (EmptySpacePosition != 2 && EmptySpacePosition != 5 && EmptySpacePosition != 8)
{
int[] _State = (int[])ParentState.Clone();
_State[EmptySpacePosition] = _State[EmptySpacePosition + 1];
_State[EmptySpacePosition + 1] = 0;
yield return new Node(_State, ParentNode.GetId(),"Right ");
}
//Can move empty space to UP?
if (EmptySpacePosition > 2)
{
int[] _State = (int[])ParentState.Clone();
_State[EmptySpacePosition] = _State[EmptySpacePosition - 3];
_State[EmptySpacePosition - 3] = 0;
yield return new Node(_State, ParentNode.GetId(), "Up ");
}
//Can move empty space to DOWN?
if (EmptySpacePosition < 6)
{
int[] _State = (int[])ParentState.Clone();
_State[EmptySpacePosition] = _State[EmptySpacePosition + 3];
_State[EmptySpacePosition + 3] = 0;
yield return new Node(_State, ParentNode.GetId(),"Down ");
}
}
public bool IsGoalState(int[] State)
{
for (int x = 0; x < 9; x++)
{
if (State[x] != GoalState[x])
return false;
}
return true;
}
public void WriteSolution()
{
StringBuilder s = new StringBuilder();
int ParentId = 0;
#region InfoPrint
Console.Write("Puzzle= ");
foreach (int i in RootNode.GetState())
{
Console.Write(i);
}
Console.WriteLine();
Console.WriteLine("Nodes Generated= " + (Solution.Count + Frontier.Count));
#endregion
foreach (Node n in Solution.Reverse())
{
if (ParentId == 0 || n.GetId() == ParentId)
{
s.Append(n.GetMove());
ParentId = n.GetParentId();
}
}
Console.WriteLine("Solution Length= " + (s.Length - 1));
Console.WriteLine("Solution= " + s.ToString());
}
}
and here is my class node
class Node
{
static int _IdCnt = 0;
private int[] State;
private int Id;
private int ParentId;
private string Move;
public Node(int[] State, int ParentId, string Move)
{
Id = _IdCnt++;
this.State = State;
this.ParentId = ParentId;
this.Move = Move;
}
public void SetState(int[] State)
{
this.State = State;
}
public int[] GetState()
{
return (int[])State.Clone();
}
public int GetId()
{
return Id;
}
public int GetParentId()
{
return ParentId;
}
public string GetMove()
{
return Move;
}
}
In the DFS, you'll need to use stack instead of queue. Basically, you add the root node to a stack, and while stack contains a node, you pop the node, do your logic, add its neighbors to the stack and continue.
1. Add root to a stack.
2. while(stack.Count > 0)
{
3. pop the stack
4. if matches, return
5. else add neighbors to stack
}
return not found
Is it possible to display fractions in a NumericUpDown or a DomainUpDown?
I know there are some fonts that have various fraction characters, but I would like to keep my form using Microsoft Sans Serif uniformly.
What do you mean by upto one-tenth.
I have a sample code for you, try if it works for you
nupdwn.Minimum = -10;
nupdwn.Maximum = 10;
nupdwn.Increment = 0.25;
nupdwn.DecimalPlaces = 2;
Microsoft Sans Serif does support fractional characters:
I will try to program a derived NumericUpDown to show fractional values. If it succeeds, i will share the code here...
Here is my Sample-Code for a FractionalUpDown.
Be sure to set DecimalPlaces to your needs.
With Mode, you can choose the formatting of the value:
EMode.Decimal => 2,500.
EMode.Fractional => ⁵⁄₂
EMode.FractionalMixed => 2 ¹⁄₂
EMode.FractionalASCII => 5/2
EMode.FractionalMixedASCII => 2 1/2
Code:
public class FractionalUpDown: NumericUpDown {
//Hide Hexadecimal
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool Hexadecimal {
get { return false; }
set { base.Hexadecimal = false; }
}
private EMode mode;
[DefaultValue(EMode.Fractional)]
public EMode Mode {
get { return mode; }
set {
if (value != mode) {
mode = value;
UpdateEditText();
}
}
}
public enum EMode {
Fractional,
FractionalMixed,
FractionalASCII,
FractionalMixedASCII,
Decimal
}
public FractionalUpDown() {
}
protected override void UpdateEditText() {
if (Mode == EMode.Decimal) {
base.UpdateEditText();
return;
}
double accuracy = Math.Pow(10.0, -(DecimalPlaces + 1));
if (accuracy > 0.1) accuracy = 0.1;
this.Text = FractionToString(DoubleToFraction((double)Value, accuracy), Mode);
}
public struct Fraction {
public Fraction(int n, int d) {
N = n;
D = d;
}
public int N { get; private set; }
public int D { get; private set; }
}
private static readonly char[] numbers = new char[10] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
private static readonly char[] numerators = new char[10] { '⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹' };
private static readonly char[] denumerators = new char[10] { '₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉' };
protected string FractionToString(Fraction frac, EMode mode) {
int full = 0;
int n = frac.N;
string result = string.Empty;
bool mixed = mode == EMode.FractionalMixed ||
mode == EMode.FractionalMixedASCII;
bool useFractionalChars = mode == EMode.Fractional ||
mode == EMode.FractionalMixed;
if (mixed && Math.Abs(frac.N) >= frac.D) {
full = frac.N / frac.D;
n = Math.Abs(frac.N % frac.D);
if (full != 0) result = full.ToString();
else if (n == 0) return "0";
}
if (n != 0) {
string fracNtext = n.ToString();
string fracDtext = frac.D.ToString();
if (useFractionalChars) {
for (int i = 0; i < 10; i++) fracNtext = fracNtext.Replace(numbers[i], numerators[i]);
for (int i = 0; i < 10; i++) fracDtext = fracDtext.Replace(numbers[i], denumerators[i]);
} else {
if (full != 0) result += " ";
}
result += fracNtext + '⁄' + fracDtext;
} else {
//Fractional Part == 0/?
if (full == 0) {
if (mixed == true) {
return "0";
} else {
if (useFractionalChars) {
return numerators[0].ToString() + '⁄' + denumerators[1].ToString();
} else {
return numbers[0].ToString() + '⁄' + numbers[1].ToString();
}
}
}
}
return result;
}
//Source: https://stackoverflow.com/questions/5124743/algorithm-for-simplifying-decimal-to-fractions/32903747#32903747
protected Fraction DoubleToFraction(double value, double accuracy) {
if (accuracy <= 0.0 || accuracy >= 1.0) {
throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
}
int sign = Math.Sign(value);
if (sign == -1) {
value = Math.Abs(value);
}
// Accuracy is the maximum relative error; convert to absolute maxError
double maxError = sign == 0 ? accuracy : value * accuracy;
int n = (int)Math.Floor(value);
value -= n;
if (value < maxError) {
return new Fraction(sign * n, 1);
}
if (1 - maxError < value) {
return new Fraction(sign * (n + 1), 1);
}
// The lower fraction is 0/1
int lower_n = 0;
int lower_d = 1;
// The upper fraction is 1/1
int upper_n = 1;
int upper_d = 1;
while (true) {
// The middle fraction is (lower_n + upper_n) / (lower_d + upper_d)
int middle_n = lower_n + upper_n;
int middle_d = lower_d + upper_d;
if (middle_d * (value + maxError) < middle_n) {
// real + error < middle : middle is our new upper
Seek(ref upper_n, ref upper_d, lower_n, lower_d, (un, ud) => (lower_d + ud) * (value + maxError) < (lower_n + un));
upper_n = middle_n;
upper_d = middle_d;
} else if (middle_n < (value - maxError) * middle_d) {
// middle < real - error : middle is our new lower
Seek(ref lower_n, ref lower_d, upper_n, upper_d, (ln, ld) => (ln + upper_n) < (value - maxError) * (ld + upper_d));
lower_n = middle_n;
lower_d = middle_d;
} else {
// Middle is our best fraction
return new Fraction((n * middle_d + middle_n) * sign, middle_d);
}
}
}
/// <summary>
/// Binary seek for the value where f() becomes false.
/// Source: https://stackoverflow.com/questions/5124743/algorithm-for-simplifying-decimal-to-fractions/32903747#32903747
/// </summary>
protected void Seek(ref int a, ref int b, int ainc, int binc, Func<int, int, bool> f) {
a += ainc;
b += binc;
if (f(a, b)) {
int weight = 1;
do {
weight *= 2;
a += ainc * weight;
b += binc * weight;
}
while (f(a, b));
do {
weight /= 2;
int adec = ainc * weight;
int bdec = binc * weight;
if (!f(a - adec, b - bdec)) {
a -= adec;
b -= bdec;
}
}
while (weight > 1);
}
}
}