Created
October 6, 2012 00:25
-
-
Save mueschm/3843213 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ESolver | |
{ | |
public delegate double operationFunction(double[] input); | |
private List<Operation> operationDeclerations; | |
private List<Variable> variables; | |
/// <summary> | |
/// Default constructor | |
/// </summary> | |
public ESolver() | |
{ | |
operationDeclerations = new List<Operation>(); | |
variables = new List<Variable>(); | |
} | |
/// <summary> | |
/// Constructor | |
/// </summary> | |
/// <param name="operations">List of operations that can be found in the equation</param> | |
public ESolver(List<ESolver.Operation> operations) | |
{ | |
operationDeclerations = operations; | |
variables = new List<Variable>(); | |
} | |
/// <summary> | |
/// Constructor | |
/// </summary> | |
/// <param name="variables">List of variables that can be found in the equation</param> | |
public ESolver(List<ESolver.Variable> variables) | |
{ | |
operationDeclerations = new List<Operation>(); | |
this.variables = variables; | |
} | |
/// <summary> | |
/// Constructor | |
/// </summary> | |
/// <param name="opertaions">List of operations that can be found in the equation</param> | |
/// <param name="variables">List of variables that can be found in the equation</param> | |
public ESolver(List<ESolver.Operation> opertaions, List<ESolver.Variable> variables) | |
{ | |
operationDeclerations = opertaions; | |
this.variables = variables; | |
} | |
/// <summary> | |
/// Add a new operation to the list of operations | |
/// </summary> | |
/// <param name="operation">The operation to be added</param> | |
public void addNewOperation(Operation operation) | |
{ | |
operationDeclerations.Add(operation); | |
} | |
/// <summary> | |
/// Add a list of new operations to the current list of operations | |
/// </summary> | |
/// <param name="operations">The list of operations to be added</param> | |
public void addNewOperation(List<Operation> operations) | |
{ | |
operationDeclerations = operationDeclerations.Union(operations).ToList(); | |
} | |
/// <summary> | |
/// Add or modify a variable for the equation | |
/// </summary> | |
/// <param name="name">The name of the variable</param> | |
/// <param name="value">The value of the variable</param> | |
public void setVariable(String name, double value) | |
{ | |
int numVariables = variables.Count; | |
for (int i = 0; i < numVariables; i++) | |
if (variables[i].getID().CompareTo(name) == 0) | |
{ | |
variables[i].setValue(value); | |
return; | |
} | |
variables.Add(new Variable(name, value)); | |
} | |
/// <summary> | |
/// Get a list of default operations for solving most equations | |
/// </summary> | |
/// <returns>A default list of operations</returns> | |
public static List<Operation> generateDefaultOperations() | |
{ | |
List<Operation> operationDeclerations = new List<Operation>(); | |
operationDeclerations.Add(new Operation("+", add, 2, 2)); | |
operationDeclerations.Add(new Operation("-", subtract, 2, 2)); | |
operationDeclerations.Add(new Operation("*", multiply, 2, 3)); | |
operationDeclerations.Add(new Operation("/", divide, 2, 3)); | |
operationDeclerations.Add(new Operation("^", exponent, 2, 4)); | |
operationDeclerations.Add(new Operation("sin", sin, 1, 1)); | |
operationDeclerations.Add(new Operation("cos", cos, 1, 1)); | |
operationDeclerations.Add(new Operation("(", null, 0, 10)); | |
return operationDeclerations; | |
} | |
/// <summary> | |
/// Solve a given equation using the operations and variables set before this function is called. | |
/// </summary> | |
/// <param name="s">The equation to solve</param> | |
/// <returns>The value of the equation</returns> | |
public double solve(String s) | |
{ | |
Stack<Operation> operations = new Stack<Operation>(); | |
Stack<double> numbers = new Stack<double>(); | |
int curStringPos = 0; | |
int numOperatins = operationDeclerations.Count; | |
while (true) | |
{ | |
if (s[curStringPos] == ')') | |
{ | |
Operation curOp; | |
while (operations.Count != 0 && (curOp = operations.Pop()).getID()[0] != '(') | |
performOperation(curOp, numbers); | |
curStringPos++; | |
} | |
for (int i = 0; i < numOperatins; i++) | |
{ | |
Operation currentOp = operationDeclerations[i]; | |
if (s.Length - curStringPos < currentOp.getID().Length) | |
continue; | |
if (currentOp.getID().CompareTo(s.Substring(curStringPos, currentOp.getID().Length)) == 0) | |
{ | |
if (operations.Count == 0) | |
operations.Push(currentOp); | |
else | |
{ | |
while (currentOp.getPriority() < operations.Peek().getPriority()) | |
{ | |
performOperation(operations.Pop(), numbers); | |
if (operations.Count == 0) | |
break; | |
} | |
operations.Push(currentOp); | |
} | |
curStringPos += currentOp.getID().Length; | |
continue; | |
} | |
} | |
String number = ""; | |
while (curStringPos < s.Length && isValidNumberChar(s[curStringPos])) | |
{ | |
number += s[curStringPos++]; | |
} | |
if (number.CompareTo("") != 0) | |
{ | |
double value = Double.Parse(number); | |
numbers.Push(value); | |
} | |
int numVariables = variables.Count; | |
for (int i = 0; i < numVariables; i++) | |
{ | |
Variable variable = variables[i]; | |
if (s.Length - curStringPos < variable.getID().Length) | |
continue; | |
if (variable.getID().CompareTo(s.Substring(curStringPos, variable.getID().Length)) == 0) | |
{ | |
numbers.Push(variable.getValue()); | |
curStringPos += variable.getID().Length; | |
} | |
} | |
if (curStringPos >= s.Length) | |
break; | |
} | |
while (operations.Count != 0) | |
performOperation(operations.Pop(), numbers); | |
return numbers.Pop(); | |
} | |
private static void performOperation(Operation operation, Stack<double> numbers) | |
{ | |
double[] input = new double[operation.getNumArguments()]; | |
for (int i = 0; i < operation.getNumArguments(); i++) | |
{ | |
input[i] = numbers.Pop(); | |
} | |
if (operation.getFunction() != null) | |
numbers.Push(operation.getFunction()(input)); | |
} | |
private static bool isValidNumberChar(char s) | |
{ | |
if ((s >= 48 && s <= 57) || s == 46) | |
return true; | |
return false; | |
} | |
public class Operation | |
{ | |
String id; | |
operationFunction function; | |
int arguments; | |
int priority; | |
public Operation(String id, operationFunction function, int arguments, int priority) | |
{ | |
this.id = id; | |
this.function = function; | |
this.arguments = arguments; | |
this.priority = priority; | |
} | |
public String getID() { return id; } | |
public operationFunction getFunction() { return function; } | |
public int getNumArguments() { return arguments; } | |
public int getPriority() { return priority; } | |
} | |
public class Variable | |
{ | |
String id; | |
double value; | |
public Variable(String id, double value) | |
{ | |
this.id = id; | |
this.value = value; | |
} | |
public String getID() { return id; } | |
public double getValue() { return value; } | |
public void setValue(double value) { this.value = value; } | |
} | |
private static double add(double[] input) | |
{ | |
return input[0] + input[1]; | |
} | |
private static double subtract(double[] input) | |
{ | |
return input[0] - input[1]; | |
} | |
private static double multiply(double[] input) | |
{ | |
return input[0] * input[1]; | |
} | |
private static double divide(double[] input) | |
{ | |
return input[1] / input[0]; | |
} | |
private static double sin(double[] input) | |
{ | |
return System.Math.Sin(input[0]); | |
} | |
private static double cos(double[] input) | |
{ | |
return System.Math.Cos(input[0]); | |
} | |
private static double exponent(double[] input) | |
{ | |
return System.Math.Pow(input[1], input[0]); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment