Skip to content

Instantly share code, notes, and snippets.

@mueschm
Created October 6, 2012 00:25
Show Gist options
  • Save mueschm/3843213 to your computer and use it in GitHub Desktop.
Save mueschm/3843213 to your computer and use it in GitHub Desktop.
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