So this is a bit of homework I have. I have to create a calculator application that asks for user input then calculates it. The input must be in an equation format. For example: " x = 3 + 8 ", " x = 6 - 3 " or x = " 6 - 3 * 9 ".
My approach to this problem is to first break down the string user input and store it into an array of char:
private char[] userInput;
string input = Console.ReadLine();
input = input.Replace(" " ,"");
userInput = input.ToCharArray();
At this point, userInput will contain all char from input. Next, I look for the variable of equation by looping through the array, this should give me the first alphabet character it found:
char var = 'x';
for (int i = 0; i < userInput.Length; i++)
{
char c = userInput[i];
if (Char.IsLetter(c)){
var = c;
break;
}
}
Next, I will break the equation up with variable one side and all of the number and operator in the other side, separated by '=', then add all number and operator to a new char array:
//get '=' position
int equalPos = 0;
for (int i = 0; i < userInput.Length; i++)
{
char c = userInput[i];
if (Char.IsSymbol(c))
{
if (c.Equals('='))
{
equalPos = i;
break;
}
}
}
//add equation to new array
rightSide = new char[userInput.Length-equalPos];
int a = 0;
for (int i = equalPos + 1; i < userInput.Length; i++)
{
char c = userInput[i];
rightSide[a] = c;
a++;
}
At this point, the rightSide array will contain all of the number and operator as character. I can calculate this part by using System.Data.DataTable().Compute(). However, if I am not allowed to use any library, how could I implement this? The equation should only contain 1 variable(always appear on the left side of the equation), four basic operators (+-/*) and no parenthesis.
Your answer can be divided into two parts
First How to convert char array to a string type
Second How to convert a string to a executable code block
For the first part use this method:
char[] chars;
string s = new string(chars);
For the Second part IT IS TOO DIFFiCULT to find a way without any pre-written code to do so then you must use Microsoft.CSharp.CSharpCodeProvider to compile code on-the-fly. In particular, search for CompileAssemblyFromFile.
If you first split the string by the = operator you will get the right and left hand side. So on the right hand side of the equation, if the equation is 'x = 6 * 2 + 1', we have '6 * 2 + 1', so we can compute that and follow standard BIDMAS rules using a loop and switch:
i have removed all error checking, this solution is for when a user inputs a perfect equation in the form 'x = {equation}' or '{equation} = x'
Also to note, a string is a char[]
//get user input
Console.Write("Enter equation:");
string input = Console.ReadLine();
string[] splitInput = input.Split('=');
int index = char.IsLetter(splitInput[0].Replace(" ", "")[0]) ? 1 : 0;
string sideWithEquation = splitInput[index];
//Compute right hand side
string[] equation = sideWithEquation.Split(' ');
Using BIDMAS, and ignoring brackets and indices, we compute divison and multiplication first.
//compute for * and /
for (int i = 1; i < equation.Length - 1; i++)
{
string item = equation[i];
int num = 0;
switch (item)
{
case "*":
num = Convert.ToInt32(equation[i - 1]) * Convert.ToInt32(equation[i + 1]);
break;
case "/":
num = Convert.ToInt32(equation[i - 1]) / Convert.ToInt32(equation[i + 1]);
break;
}
if (num > 0)
{
equation[i - 1] = "";
equation[i] = "";
equation[i + 1] = num.ToString();
}
}
And then we comoute for addition and subtraction
//Now compute for + and -
equation = string.Join(" ", equation).Split(' ');
for (int i = 1; i < equation.Length - 1; i++)
{
string item = equation[i];
int num = 0;
switch (item)
{
case "+":
num = Convert.ToInt32(equation[i - 1]) + Convert.ToInt32(equation[i + 1]);
break;
case "-":
num = Convert.ToInt32(equation[i - 1]) - Convert.ToInt32(equation[i + 1]);
break;
}
if (num > 0)
{
equation[i - 1] = "";
equation[i] = "";
equation[i + 1] = num.ToString();
}
}
and then to display the value of x to the user again
string total = string.Join("", equation);
//display what x is
Console.WriteLine($"x = {int.Parse(total)}" );
Related
My task: Merge and divide two strings with some step.
For example:
text = "abcd" key = "12" step = 2
result = "1ab2cd"
Пример:
1) Merging strings.
Input variables:
text = "abcd" key = "12" step = 2
Output variables:
result = "1ab2cd"
2) Now I need to decrypt the result of string to the source data, where key. Length and step variables are known.
Input variables:
result = "1ab2cd" key.Length = 2 step = 2
Output variables:
text = "abcd" key = "12"
Algorithm (1) has already been implemented:
int step, word;
string text, key, result = string.Empty;
Console.Write("Enter Text : ");
text = Console.ReadLine();
Console.Write("Enter Key : ");
key = Console.ReadLine();
Console.Write("Enter Step : ");
step = int.Parse(Console.ReadLine());
// MIX ARRAY
word = 0;
if (step <= text.Length)
{
for (int i = 0; i < key.Length; i++)
{
result += key.Substring(i, 1);
for (int k = 0; k < step; k++)
{
try
{
result += text.Substring(word, 1);
word++;
}
catch
{
break;
}
}
}
if (word < text.Length)
{
result += text.Substring(word, (text.Length - word));
}
}
Console.WriteLine("Result Text : " + result);
// DECIPHER ARRAY
Console.WriteLine("text: " + text);
Console.WriteLine("key: " + key);
Console.ReadKey();
How to implement the algorithm (2)?
I will write this as another code block you can merge 2 algorthym if you want.
Again Think with my 4 steps.
1- Find what variables do you need?
string key = "", text = "", result;
int step = 0, keyLength, textLength, word = 0;
2- Take All Values
Console.Write("Result Text : ");
result = Console.ReadLine();
Console.Write("Key Length: ");
keyLength = int.Parse(Console.ReadLine());
textLength = result.Length - keyLength;
Console.Write("Step: ");
step = int.Parse(Console.ReadLine());
3- Think about algorthym
4- Think about that may arise exceptions
for (int i = 0; i < result.Length; i = word)
{
if (keyLength > 0)
{
key += result.Substring(word, 1);
word++;
keyLength--;
}
if (textLength > 0)
{
for (int k = 0; k < step; k++)
{
try
{
text += result.Substring(word, 1);
word++;
textLength--;
}
catch
{
break;
}
}
}
}
Console.WriteLine("Text : " + text);
Console.Write("Key : " + key);
Console.ReadKey();
text = "abcd"
key = "12"
step = 2
result = "1ab2cd"
First ->Think about variables. How many and which kind of variable are your need.
int step,word;
string text,key,result;
Second ->Fill variables with needed values
Console.Write("Enter Text : ")
text = Console.ReadLine();
Console.Write("Enter Key : ")
key = Console.ReadLine();
Console.Write("Enter Step : ")
step = int.Parse(Console.ReadLine());
Third ->Create an algorthym for solve this problem
Forth ->Think about what exception can be and how can you solve them
for(int i=0;i<key.Length;i++)
{
result+=key.Substring(i,1);
for(int k=0; k<step; k++)
{
try
{
result+=text.Substring(word,1);
word++;
}
catch
{
/* This blok will break
when the text variable's last part's character count lest then step. */
break;
}
}
}
if(word < text.Length)
{
// if there is any text after all. Calculate how many letter left then write them
result += text.Substring(word,(text.Length-word))
}
Console.Write("Result Text : "+result);
Console.ReadKey();
I hope this can help to you
I'm sorry I can't test this. I hope it helps:
static string Combine(string text, string key, int step)
{
var result = "";
int stepCount = 0;
for (int i = 0; i < text.Length + key.Length; i++)
{
if (i % step == 0)
{
result += key[i / step];
stepCount++;
}
else
{
result += text[i - stepCount];
}
}
return result;
}
Below codes run perfectly fine. But how to I print converted number in left to right manner. For example if I input 898989, it will give me the output DB7AD. How do I print
DB7AD to
D
B
7
A
D
Codes:
public static void Main()
{
int decimalNumber, quotient;
int i = 1, j, num = 0;
char [] hexadecimalNumber = new char[100];
char temp;
Console.WriteLine("Decimal to HexaDecimal conversion using Ascii code.\n");
Console.WriteLine("Input DECIMAL NUMBER(S) you want to convert to HEXADECIMAL(S):\t\n");
Console.Write("Decimal Numbers : \t");
decimalNumber = int.Parse(Console.ReadLine());
quotient = decimalNumber;
while (quotient != 0)
{
num = quotient % 16;
if (num < 10)
num = num + 48;
else
num = num + 55;
temp = Convert.ToChar(num);
hexadecimalNumber[i++] = temp;
quotient = quotient / 16;
}
Console.Write("HexaDecimal Numbers : \t");
for (j = i - 1; j > 0; j--)
Console.Write(hexadecimalNumber[j]);
Console.WriteLine();
Console.Read();
}
Since you are printing your number character-by-character, you need to modify this loop
for (j = i - 1; j > 0; j--) {
Console.Write(hexadecimalNumber[j]);
}
in such a way as to print zero tabs before the first digit, one tab before the second digit, two tabs before the third digit, and so on. You can do it by making a string tabs variable, and adding a "\t" to it after each iteration:
string tabs = "";
for (j = i - 1; j > 0; j--) {
Console.WriteLine(tabs + hexadecimalNumber[j]);
tabs += "\t";
}
Demo on ideone.
I keep getting this error:
"Cannot implicitly convert type 'double' to 'int'. An explicit
conversion exists (are you missing a cast?)"
Code:
Console.WriteLine("ISBN-Prüfziffer berechnen");
Console.WriteLine("=========================");
Console.WriteLine();
Console.Write("ISBN-Nummer ohne Prüfziffer: ");
string ISBNstring = Console.ReadLine();
int ISBN = Convert.ToInt32(ISBNstring);
int PZ;
int i;
double x = Math.Pow(3, (i + 1) % 2);
int y = (int)x;
for (i = 1; i <= 12; i++)
{
PZ = ((10-(PZ + ISBN * x) % 10) % 10);
}
Console.WriteLine(PZ);
Console.ReadLine();
Here is the new code:
Console.WriteLine("ISBN-Prüfziffer berechnen");
Console.WriteLine("=========================");
Console.WriteLine();
Console.Write("ISBN-Nummer ohne Prüfziffer: ");
string ISBNstring = Console.ReadLine();
long ISBN = Convert.ToInt32(ISBNstring);
long ISBN1 = (Int64)ISBN;
int PZ = 0;
int i;
for (i = 1; i <= 12; i++)
{
double x = Math.Pow(3, (i + 1) % 2);
long y = (double)x;
PZ = ((10 - (PZ + ISBN * y) % 10) % 10);
}
Console.WriteLine(PZ);
Console.ReadLine();
But I'm still getting a conversion error for double to long and long to int...
I think you meant to use your y variable here instead of x :
PZ = ((10-(PZ + ISBN * y) % 10) % 10);
As a side note, you'll get compilation errors on both PZ and i, you need to initialize their values before using them, e.g. int PZ = 0; and int i = 0;
And please, use meaningful names; PZ, i, x and y don't mean anything to someone reading your code, or even to you in a few weeks.
Okay, I've modified it a little...
Console.WriteLine("ISBN-Prüfziffer berechnen");
Console.WriteLine("=========================");
Console.WriteLine();
Console.Write("ISBN-Nummer ohne Prüfziffer: ");
string ISBNstring = Console.ReadLine();
int sum = 0;
for (int i = 0; i < 12; i++)
{
int digit = ISBNstring[i] - '0';
if (i % 2 == 1)
{
digit *= 3;
}
sum += digit;
}
int result = 10 - (sum%10);
Console.WriteLine(result);
Console.ReadLine();
Here's the changes :
- You can declare i directly in your for loop, it'll save you a line.
- Instead of putting the ISBN into a long, keep in in a string. Just iterate over each character one by one.
- Each digit can be obtained by taking the ASCII value, and removing the value of 0.
- The % 2 == 1 thing is basically "If the number is at an odd position", where you can apply the *3. This replaces your Math.Pow that wasn't very clear.
How can i disable counting of deletion, in this implementation of Damerau-Levenshtein distance algorithm, or if there is other algorithm already implemented please point me to it.
Example(disabled deletion counting):
string1: how are you?
string2: how oyu?
distance: 1 (for transposition, 4 deletes doesn't count)
And here is the algorithm:
public static int DamerauLevenshteinDistance(string string1, string string2, int threshold)
{
// Return trivial case - where they are equal
if (string1.Equals(string2))
return 0;
// Return trivial case - where one is empty
if (String.IsNullOrEmpty(string1) || String.IsNullOrEmpty(string2))
return (string1 ?? "").Length + (string2 ?? "").Length;
// Ensure string2 (inner cycle) is longer_transpositionRow
if (string1.Length > string2.Length)
{
var tmp = string1;
string1 = string2;
string2 = tmp;
}
// Return trivial case - where string1 is contained within string2
if (string2.Contains(string1))
return string2.Length - string1.Length;
var length1 = string1.Length;
var length2 = string2.Length;
var d = new int[length1 + 1, length2 + 1];
for (var i = 0; i <= d.GetUpperBound(0); i++)
d[i, 0] = i;
for (var i = 0; i <= d.GetUpperBound(1); i++)
d[0, i] = i;
for (var i = 1; i <= d.GetUpperBound(0); i++)
{
var im1 = i - 1;
var im2 = i - 2;
var minDistance = threshold;
for (var j = 1; j <= d.GetUpperBound(1); j++)
{
var jm1 = j - 1;
var jm2 = j - 2;
var cost = string1[im1] == string2[jm1] ? 0 : 1;
var del = d[im1, j] + 1;
var ins = d[i, jm1] + 1;
var sub = d[im1, jm1] + cost;
//Math.Min is slower than native code
//d[i, j] = Math.Min(del, Math.Min(ins, sub));
d[i, j] = del <= ins && del <= sub ? del : ins <= sub ? ins : sub;
if (i > 1 && j > 1 && string1[im1] == string2[jm2] && string1[im2] == string2[jm1])
d[i, j] = Math.Min(d[i, j], d[im2, jm2] + cost);
if (d[i, j] < minDistance)
minDistance = d[i, j];
}
if (minDistance > threshold)
return int.MaxValue;
}
return d[d.GetUpperBound(0), d.GetUpperBound(1)] > threshold
? int.MaxValue
: d[d.GetUpperBound(0), d.GetUpperBound(1)];
}
public static int DamerauLevenshteinDistance( string string1
, string string2
, int threshold)
{
// Return trivial case - where they are equal
if (string1.Equals(string2))
return 0;
// Return trivial case - where one is empty
// WRONG FOR YOUR NEEDS:
// if (String.IsNullOrEmpty(string1) || String.IsNullOrEmpty(string2))
// return (string1 ?? "").Length + (string2 ?? "").Length;
//DO IT THIS WAY:
if (String.IsNullOrEmpty(string1))
// First string is empty, so every character of
// String2 has been inserted:
return (string2 ?? "").Length;
if (String.IsNullOrEmpty(string2))
// Second string is empty, so every character of string1
// has been deleted, but you dont count deletions:
return 0;
// DO NOT SWAP THE STRINGS IF YOU WANT TO DEAL WITH INSERTIONS
// IN A DIFFERENT MANNER THEN WITH DELETIONS:
// THE FOLLOWING IS WRONG FOR YOUR NEEDS:
// // Ensure string2 (inner cycle) is longer_transpositionRow
// if (string1.Length > string2.Length)
// {
// var tmp = string1;
// string1 = string2;
// string2 = tmp;
// }
// Return trivial case - where string1 is contained within string2
if (string2.Contains(string1))
//all changes are insertions
return string2.Length - string1.Length;
// REVERSE CASE: STRING2 IS CONTAINED WITHIN STRING1
if (string1.Contains(string2))
//all changes are deletions which you don't count:
return 0;
var length1 = string1.Length;
var length2 = string2.Length;
// PAY ATTENTION TO THIS CHANGE!
// length1+1 rows is way too much! You need only 3 rows (0, 1 and 2)
// read my explanation below the code!
// TOO MUCH ROWS: var d = new int[length1 + 1, length2 + 1];
var d = new int[2, length2 + 1];
// THIS INITIALIZATION COUNTS DELETIONS. YOU DONT WANT IT
// or (var i = 0; i <= d.GetUpperBound(0); i++)
// d[i, 0] = i;
// But you must initiate the first element of each row with 0:
for (var i = 0; i <= 2; i++)
d[i, 0] = 0;
// This initialization counts insertions. You need it, but for
// better consistency of code I call the variable j (not i):
for (var j = 0; j <= d.GetUpperBound(1); j++)
d[0, j] = j;
// Now do the job:
// for (var i = 1; i <= d.GetUpperBound(0); i++)
for (var i = 1; i <= length1; i++)
{
//Here in this for-loop: add "%3" to evey term
// that is used as first index of d!
var im1 = i - 1;
var im2 = i - 2;
var minDistance = threshold;
for (var j = 1; j <= d.GetUpperBound(1); j++)
{
var jm1 = j - 1;
var jm2 = j - 2;
var cost = string1[im1] == string2[jm1] ? 0 : 1;
// DON'T COUNT DELETIONS! var del = d[im1, j] + 1;
var ins = d[i % 3, jm1] + 1;
var sub = d[im1 % 3, jm1] + cost;
// Math.Min is slower than native code
// d[i, j] = Math.Min(del, Math.Min(ins, sub));
// DEL DOES NOT EXIST
// d[i, j] = del <= ins && del <= sub ? del : ins <= sub ? ins : sub;
d[i % 3, j] = ins <= sub ? ins : sub;
if (i > 1 && j > 1 && string1[im1] == string2[jm2] && string1[im2] == string2[jm1])
d[i % 3, j] = Math.Min(d[i % 3, j], d[im2 % 3, jm2] + cost);
if (d[i % 3, j] < minDistance)
minDistance = d[i % 3, j];
}
if (minDistance > threshold)
return int.MaxValue;
}
return d[length1 % 3, d.GetUpperBound(1)] > threshold
? int.MaxValue
: d[length1 % 3, d.GetUpperBound(1)];
}
here comes my explanation why you need only 3 rows:
Look at this line:
var d = new int[length1 + 1, length2 + 1];
If one string has the length n and the other has the length m, then your code needs a space of (n+1)*(m+1) integers. Each Integer needs 4 Byte. This is waste of memory if your strings are long. If both strings are 35.000 byte long, you will need more than 4 GB of memory!
In this code you calculate and write a new value for d[i,j]. And to do this, you read values from its upper neighbor (d[i,jm1]), from its left neighbor (d[im1,j]), from its upper-left neighbor (d[im1,jm1]) and finally from its double-upper-double-left neighbour (d[im2,jm2]). So you just need values from your actual row and 2 rows before.
You never need values from any other row. So why do you want to store them? Three rows are enough, and my changes make shure, that you can work with this 3 rows without reading any wrong value at any time.
I would advise not rewriting this specific algorithm to handle specific cases of "free" edits. Many of them radically simplify the concept of the problem to the point where the metric will not convey any useful information.
For example, when substitution is free the distance between all strings is the difference between their lengths. Simply transmute the smaller string into the prefix of the larger string and add the needed letters. (You can guarantee that there is no smaller distance because one insertion is required for each character of edit distance.)
When transposition is free the question reduces to determining the sum of differences of letter counts. (Since the distance between all anagrams is 0, sorting the letters in each string and exchanging out or removing the non-common elements of the larger string is the best strategy. The mathematical argument is similar to that of the previous example.)
In the case when insertion and deletion are free the edit distance between any two strings is zero. If only insertion OR deletion is free this breaks the symmetry of the distance metric - with free deletions, the distance from a to aa is 1, while the distance from aa to a is 1. Depending on the application this could possibly be desirable; but I'm not sure if it's something you're interested in. You will need to greatly alter the presented algorithm because it makes the mentioned assumption of one string always being longer than the other.
Try to change var del = d[im1, j] + 1; to var del = d[im1, j];, I think that solves your problem.
How to find column's name or header?
For example if i select column 5 in excel means i want the result as "E".
How to get the alphabet or letter corresponding to column no.
Please help me with the code
public static string GetColumnName(int columnNumber)
{
const string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string columnName = "";
while (columnNumber > 0)
{
columnName = letters[(columnNumber - 1) % 26] + columnName;
columnNumber = (columnNumber - 1) / 26;
}
return columnName;
}
What about using Application.ActiveCell.get_Address(true, true, Excel.AlReferenceStyle.xlA1, missing, missing) and then parse the result string or use a RegEx to get the column heading?
I simply used:
string location = Application.ActiveCell.get_Address(true, true, Excel.AlReferenceStyle.xlA1, missing, missing);
string tokens = x.Split("$".ToCharArray());
MessageBox.Show(String.Format("Column {0}", result[0]));
public static long GetColumnNumber(string columnName)
{
int letterPos = 0;
long columnNumber = 0;
for (int placeHolder = columnName.Length - 1; placeHolder >= 0; placeHolder--)
{
int currentSum = 1;
for (int multiplier = 0; multiplier < placeHolder; multiplier++)
currentSum *= 26;
int letterValue = (int) columnName[letterPos];
currentSum *= letterValue - 64;
columnNumber += currentSum;
if (letterPos != columnName.Length)
letterPos++;
//Console.WriteLine(((int)columnName[i]-64) + " = " + columnName[i]);
}
return columnNumber;
}
The following is a complete method which gives you the corresponding alphabet for an integer value that is passed.
private String Number2String(int number, bool isCaps)
{
int number1 = number / 27;
int number2 = number - (number1 * 26);
if (number2 > 26)
{
number1 = number1 + 1;
number2 = number - (number1 * 26);
}
Char a = (Char)((isCaps ? 65 : 97) + (number1 - 1));
Char b = (Char)((isCaps ? 65 : 97) + (number2 - 1));
Char c = (Char)((isCaps ? 65 : 97) + (number - 1));
string d = String.Concat(a, b);
if (number <= 26)
return c.ToString();
else
return d;
}
I use these two:
public string GetExcelColumn(int index)
{
int quotient = index / 26;
if (quotient > 0)
return GetExcelColumn(quotient - 1) + (char)((int)'A' + (index % 26));
else
return "" + (char)((int)'A' + index);
}
static IEnumerable<string> GetExcelColumns()
{
var alphabet = new string[]{""}.Union(from c in Enumerable.Range((int)'A', 26) select Convert.ToString((char)c));
return from c1 in alphabet
from c2 in alphabet
from c3 in alphabet.Skip(1) // c3 is never empty
where c1 == string.Empty || c2 != string.Empty // only allow c2 to be empty if c1 is also empty
select c1 + c2 + c3;
}
This works well in VBA by using a double replace, where R is a Single Cell Excel Range:
ColumnLetter = Replace(Replace(R.AddressLocal(ReferenceStyle:=1), "$", vbNullString), R.Row, vbNullString)
It is based on the equivalent idea for use on a Worksheet. In a Cell Formula use this, it is even shorter:
=SUBSTITUTE(ADDRESS(1,COLUMN(M1),4),1,"")
This returns the letter M and works right up to Column XFD. The cell reference M1 can be any Range anywhere. The top left Column is returned for Ranges or more than one cell.
It gets the ADDRESS of the first Cell in the Column and then removes the trailing 1 by substituting a NullString for it. (The 4 in the ADDRESS makes sure that the Address is returned as a Relative Address, i.e. one without and $ signs in it.)
Thanks to barry houdini who set me off on the quest for a good answer to this.