Calculator to calculate multiple equations - c#

I'm really new to C# and needed to create a calculator class that does multiple equations. For example 4+5*8-3/2. Why it doesn't work? It only does additions and I don't know how to make it do subtraction or do multiplication. Here is the code I have already created, but it doesn't work. Could somebody please help me. It only adds numbers and nothing else. I have tried absolutely everything.
namespace Calculator
{
class Program
{
static void Main(string[] args)
{
var expression = "4+5*8";
var calculator = new Calculator();
foreach (var chr in expression)
{
calculator.KeyPress(chr);
}
Console.WriteLine(calculator.Value);
}
}
public class Calculator
{
public double? Value { get; set; }
private Stack<double> stack = new Stack<double>();
public void KeyPress(char key)
{
if (Char.IsDigit(key))
{
// If the key is a digit, add it to the current value
if (Value == null)
{
Value = Char.GetNumericValue(key);
}
else
{
Value = Value + Char.GetNumericValue(key);
}
}
else if (key == '+' || key == '-' || key == '*' || key == '/')
{
// If the key is an operator, perform the pending calculation
// and store the result in the stack
double result = PerformCalculation(key, stack);
stack.Push(result);
}
}
private double PerformCalculation(char op, Stack<double> stack)
{
double result = 0;
if (stack.Count > 1)
{
// Pop the last two values from the stack
double right = stack.Pop();
double left = stack.Pop();
// Perform the calculation based on the operator
switch (op)
{
case '+':
result = left + right;
break;
case '-':
result = left - right;
break;
case '*':
result = left * right;
break;
case '/':
result = left / right;
break;
}
}
else if (stack.Count == 1)
{
// If there is only one value in the stack, store it as the result
result = stack.Pop();
}
// Only push the result back into the stack if the Value property is not null
if (Value != null)
{
stack.Push(result);
}
return result;
}
}
}

You must perform an operation of the left value and right value of the operator.
Your loop proceeds one by one to read the characters, you have to memorize the operator because you don't know the right operand.
public char LastOperator { get; set; }
/* ... */
else if (key == '+' || key == '-' || key == '*' || key == '/')
{
LastOperator = key;
}
As soon as stack reaches two values ​​in its list (with the Count property), you can perform the calculation:
var result = PerformCalculation(LastOperator, stack);
This new result must be inserted into the stack as the left operator, having previously cleared your stack with the Clear method.
In the case of an empty stack at the beginning of your program, you just have to insert the value in stack.
Note:
I don't want to give you the solution if it is a duty in which one learns by seeking, but leads.
Anyway, you don't have to touch the PerformCalculation method, it works fine.

Related

What 's the best solution to find an element in a deepest binary tree

Recently I had an interview question about finding an element in a binary tree. I coded both recursive and iterative solutions with C# but the problem was that in test cases when we have a tree with 1000000 nodes and all of them are on the left side. The interviewer said to me that my solutions (recursive and iterative) didn't save memory RAM enough for this case and I don't understand how to improve my solution.
// recusive Mode
public Node Find(int v)
{
if(v == value)
{
return this;
}else if(v <value){
if (left == null) return null;
return left.Find(v);
}else{
if (right == null) return null;
return right.Find(v);
}
}
// iterative
public Node Find(int v)
{
Node current = this;
while(value != v && current != null)
{
if (v < current.value)
{
if (current.left == null){ current = null};
else{current = current.left};
}
else
{
if (current.right == null) { current = null};
else{current = current.right };
}
}
return current;
}
Your iterative solution has some bugs in it.
// iterative
public Node Find(int v)
{
Node current = this;
// Here you need to compare current.value instead of just value
// Also, to use short-circuiting you need to put null-check first
// otherwise you might access current.value while current is null
while(current != null && current.value != v)
{
if (v < current.value)
{
//if (current.left == null){ current = null};
//else{current = current.left};
current = current.left; // the same as two commented out lines
}
else
{
//if (current.right == null) { current = null};
//else{current = current.right };
current = current.right; // the same as two commented out lines
}
}
return current;
}

Binary Search Tree Validation

Thank you for reading my topic. I am practising a little bit with C# at Test Dome. The exercise I am currently trying to program is the following:
http://www.testdome.com/Questions/Csharp/BinarySearchTree/484?testId=21&testDifficulty=Hard
My current result:
Example case: Correct answer
Simple cases: Correct answer
Regular cases: Wrong answer
Edge cases: Wrong answer
Performance test: Wrong answer
You can read the code I wrote so far below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
public class Node
{
public int Value { get; set; } // Value of {node} == integer (1,2,3,4,5)
public Node Left { get; set; } // Reference to left node (n1, n2, n3) == Node.
public Node Right { get; set; } // Reference to right node (n1, n2, n3) == Node.
public Node(int value, Node left, Node right)
{
Value = value; // (int)
Left = left; // (node)
Right = right; // (node)
}
}
public class BinarySearchTree
{
public static bool IsValidBST(Node root)
{
if (root.Left == null && root.Right == null)
return true;
else if (root.Left == null)
{
// Checking root.Right.Value
if (root.Value <= root.Right.Value)
return true;
else
return false;
}
else if (root.Right == null)
{
// Checking root.Left.Value
if (root.Value > root.Left.Value)
return true;
else
return false;
}
else
{
// Checking both Values
if (root.Value > root.Left.Value && root.Value <= root.Right.Value)
return true;
else
return false;
}
}
public static void Main(string[] args)
{
Node n1 = new Node(1, null, null);
Node n3 = new Node(3, null, null);
Node n2 = new Node(2, n1, n3);
// Execute function and write it to the console
Console.WriteLine(IsValidBST(n2));
Console.ReadLine();
}
}
I have no idea what to implement to pass the test. I don't want you to give me written-code, but more information about the exercice. Keep in mind that my current-code is far from neat. Thank you all.
You are not checking all upper nodes values. You should have array/list of all upper nodes, so you can check it.
And also you should use recursion call.
Like this
IsValidBST(Node root, List<int> upperValues = null)
{
...
bool childIsValid = IsValidBST (root.Left, upperValuesLeft ) && IsValidBST(root.Right, upperValuesRight )
}
You should check those other nodes root.Left and root.Right by calling IsValidBST on them if they are not null and then checking these results. Right now you only test the root node instead of descending into the tree
The answer code:
if (root.Value == value) return true;
if (root.Left != null && value < root.Value)
if (Contains(root.Left, value)) return true;
if (root.Right != null && value > root.Value)
if (Contains(root.Right, value)) return true;
return false;
Read my post of the same question.

GetAsyncKeyState Multiple characters

I have problem with GetAsyncKeyState.
public static void GetKey()
{
string keyBuffer = "";
foreach (System.Int32 i in Enum.GetValues(typeof(Keys)))
{
if (Enum.GetName(typeof(Keys), i) != "LButton")
{
int x = GetAsyncKeyState(i);
if ((x == 1) || (x == -32767) || (x == -32768))
{
keyBuffer += Enum.GetName(typeof(Keys), i) + " ";
Object ki = Enum.ToObject(typeof(Keys), i);
if (keyBuffer == "LButton")
{
}
if (keyBuffer == "RButton")
{
}
if (keyBuffer == "LShiftKey")
{
}
if (keyBuffer == "RShiftKey")
{
}
if (keyBuffer == "RMouse")
{
}
if (keyBuffer == "LMouse")
{
}
else
{
Console.WriteLine(ki);
}
}
}
}
The problem is that i'm getting multiple key when i change code to:
if ((x == 1) || (x == -32767))
i'm getting only one pressed but i'm not getting keys from excel.
Taking a look at your code, I see a couple of problems.
GetAsyncKeyState returns a signed 16 bit short. If you've not defined it that way you should change you definition. I say that because I note that you use int to hold the return value and wonder whether or not you declared the function correctly.
The other problem that I see with your code is that you test for the key being down incorrectly. Test if the return value is negative to check if the key is down:
if (GetAsyncKeyState(...) < 0)
{
// key is down
}
Beyond that, I expect that you are mistaken in using GetAsyncKeyState. Judging from your comments, you are trying to read text input, and GetAsyncKeyState is the wrong function for that.

Convert String To Int in LINQ

I have a LINQ query that queries a DataTable. In the DataTable, the field is a string and I need to compare that to an integer, basically:
if ((electrical >= 100 && electrical <= 135) || electrical == 19)
{
// The device passes
}
the problem is, I am trying to do this in LINQ like this:
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where (Int32.Parse(row.Field<String>("electrical")) >= 100 &&
Int32.Parse(row.Field<String>("electrical")) <= 135) &&
Int32.Parse(row.Field<String>("electrical")) != 19 &&
row.Field<String>("print") == printName
select row;
I keep getting the exception:
Input string was not in a correct format
The main problem occurs when electrical == ""
Unfortunately, the framework doesn't provide a nice clean way to handle parsing scenarios where it fails. Of what's provided, they only throw exceptions or use out parameters, both of which does not work well with linq queries. If any one value you're parsing fails, the entire query fails and you just can't really use out parameters. You need to provide a method to handle the parsing without that does not throw and does not require using out parameters.
You can handle this in many ways. Implement it where upon failure, you return some default sentinel value.
public static int ParseInt32(string str, int defaultValue = 0)
{
int result;
return Int32.TryParse(str, out result) ? result : defaultValue;
}
Or what I would recommend, return a nullable value (null indicating it failed).
public static int? ParseInt32(string str)
{
int result;
return Int32.TryParse(str, out result) ? result : null;
}
This simplifies your query dramatically while still leaving it readable.
public bool GetElectricalStatus(string printName)
{
var query =
from row in singulationOne.Table.AsEnumerable()
where row.Field<string>("print") == printName
// using the nullable implementation
let electrical = ParseInt32(row.Field<string>("electrical"))
where electrical != null
where electrical == 19 || electrical >= 100 && electrical <= 135
select row;
return !query.Any();
}
p.s., your use of the Convert.ToInt32() method is incorrect. It is the same as calling Int32.Parse() and does not return a nullable, it will throw on failure.
I would check if the data in the column does not contain leading/trailing whitespaces - i.e. "15 " rather than "15" and if it does (or might do) trim it before trying to convert:
Int32.Parse(row.Field<String>("electrical").Trim())
BTW: not related to the error but I'd use let statement to introduce a local variable and do the conversion once:
let x = Int32.Parse(row.Field<String>("electrical").Trim())
where x >= 100...
I could not get anything to work, so I re-did the whole method:
public bool GetElectricalStatus(string printName)
{
List<object> eGoodList = new List<object>();
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where row.Field<String>("print") == printName
select row.Field<String>("electrical");
foreach (var eCode in eGoodCountQuery)
{
if (!string.IsNullOrEmpty(eCode.ToString()))
{
int? eCodeInt = Convert.ToInt32(eCode);
if (eCodeInt != null &&
(eCodeInt >= 100 && eCodeInt <= 135) || eCodeInt == 19)
{
eGoodList.Add(eCode);
}
}
}
if (eGoodList.Count() > 0)
{
return false;
}
else
{
return true;
}
}
The main problem occurs when electrical == ""
Why not make a function that does your evaluation, and call it in your Linq query. Put logic in to check the validity of the data contained within (so if you can't parse the data, it should return false)...
The function:
bool IsInRange(string text, int lower, int upper, params int[] diqualifiers)
{
int value = int.MinValue;
if (!int.TryParse(text, out value)) {
return false;
}
if (!(value >= lower && value <= upper)) {
return false;
}
if (disqualifiers != null && disqualifiers.Any(d => d == value)) {
return false;
}
return true;
}
The Linq query...
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where
IsInRange(row.Field<String>("electrical"), 100, 135, 19)
&& row.Field<String>("print") == printName
select row;

How do I swap 2 elements in a list [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Swap two items in List<T>
Edit: Maybe this will work for getting the 'b' value?
for (int i = 0; i < inventory.Count; i++)
{
if (inventory[a].ItemRectangle.Intersects(inventory[i].ItemRectangle))
{
itemB = inventory[i];
}
}
Edit: Here's my progress.
Item itemA;
Item itemB;
int a = -1;
int b = -1;
if (a != -1 && b != -1)
{
itemA = inventory[a];
itemB = inventory[b];
Swap(ref itemA, ref itemB);
inventory[a] = itemA;
inventory[b] = itemB;
}
And here's is where I'm getting the 'a' value.
if (item.ItemSelected == true)
{
a = item.ItemIndex;
}
else
a = -1;
I haven't figured out how to get the 'b' value because I would have to check for an item colliding with another item that are both in the same list. If anybody know how I can do this, please tell me. It would look something like this I guess:
if (item.ItemRectangle.Intersects(//the other item.ItemRectangle)
{
b = item.ItemIndex;
}
else
b = -1;
I've made a List < Item > called inventory. So now I want to implement a swap function, like this:
foreach (Item item in inventory)
{
if (mouseRectangle.Intersects(item.ItemRectangle))
{
if (Input.EdgeDetectLeftMouseDown())
{
switch (item.ItemSelected)
{
case false:
item.ItemSelected = true;
break;
case true:
item.ItemSelected = false;
break;
}
}
}
else if (Input.EdgeDetectLeftMouseDown())
{
switch (item.ItemSelected)
{
case true:
item.ItemSelected = false;
break;
}
}
else if (item.ItemSelected == true)
{
item.ItemPosition = new Vector2(mouseRectangle.X, mouseRectangle.Y);
item.ItemRectangle = new Rectangle(mouseRectangle.X, mouseRectangle.Y, 32, 32);
}
else if (item.ItemSelected == false && //a lot of checks to determine it is not intersecting with an equip slot
{
item.ItemPosition = item.OriginItemPosition;
item.ItemRectangle = item.OriginItemRectangle;
}
else if (item.ItemRectangle.Intersects(item.ItemRectangle))
{
//SwapItem(inventory, item, item);
}
So that's the part of the code I need help with. I want any item in the list to be able to swap with any other item in the list. My SwapItem method is just a placeholder, I dont actually have a SwapItem method yet.
I want the arguments that you pass in to the method to be related to the items I want to swap. So the first item would be the item that I have selected with my mouse, and the other item should be the item that the first item is intersecting with.
To swap an element of the list you can write an extension method as.
public static class ExtensionMethods
{
public static void Swap<T>(this List<T> list, int index1, int index2)
{
T temp = list[index1];
list[index1] = list[index2];
list[index2] = temp;
}
}
Remember to put the extension method inside a static class.
then you can do:
yourList.Swap(0,1); // swap element at index 0 with element at index 1
To swap the values of two variables, the easiest method is using references. This is a classic pointer exercise in c++, but it can apply to C# as well.
// Replace int with any data type / class you need
void Swap (ref int a, ref int b)
{
int c = a;
a = b;
b = c;
}
The algorithm used is very simple, and the explanation is usually done like this: you have two glasses, one with water, and one with oil. To put the oil in the first glass, you will need to use a third glass, put the water inside, then put the oil in the first glass, and the water in the second one.
Here is what I had in mind. Look for the comments, so you can understand what's going on.:
// Unlike foreach, with for I can change the values in the list
for (int i = 0; i < inventory.Count; i++)
{
if (mouseRectangle.Intersects(inventory[i].ItemRectangle))
{
if (Input.EdgeDetectLeftMouseDown())
{
// You can replace the switch with this shorter structure
// if A is a bool value, !A will have the opposite value
inventory[i].ItemSelected = !inventory[i].ItemSelected;
}
}
else if (Input.EdgeDetectLeftMouseDown())
{
// You don't need a case-switch for a single condition. An if should suffice
if (inventory[i].ItemSelected)
inventory[i].ItemSelected = false;
}
else if (inventory[i].ItemSelected == true)
{
inventory[i].ItemPosition = new Vector2(mouseRectangle.X, mouseRectangle.Y);
inventory[i].ItemRectangle = new Rectangle(mouseRectangle.X, mouseRectangle.Y, 32, 32);
}
else if (inventory[i].ItemSelected == false && //a lot of checks to determine it is not intersecting with an equip slot
{
inventory[i].ItemPosition = inventory[i].OriginItemPosition;
inventory[i].ItemRectangle = inventory[i].OriginItemRectangle;
}
// Something definitely wrong with this line, a rectangle to instersect with itself??
else if (inventory[i].ItemRectangle.Intersects(inventory[PROBABLY_SOMETHING_ELSE].ItemRectangle))
{
Swap (ref inventory[i], ref inventory[PROBABLY_SOMETHING_ELSE])
}
}

Categories

Resources