Commit 7a6314aa authored by Adam Blank's avatar Adam Blank
Browse files

after lecture07

parent 152e3895
Showing with 286 additions and 0 deletions
+286 -0
/** This class provides a method to evaluate fully parenthesized mathematical
* expressions.
*
* @author Adam Blank
*/
public class Evaluator {
/** Evaluates fully parenthesized mathematical expressions that use addition
* and multiplication. */
public static int evaluate(String exp) throws NotImplementedException {
if (EvaluatorUtilities.isNumber(exp)) {
return Integer.parseInt(exp);
}
else {
exp = exp.substring(1, exp.length() - 1);
int nextOpIdx = EvaluatorUtilities.nextOperatorIndex(exp);
char op = EvaluatorUtilities.nextOperator(exp);
String left = exp.substring(0, nextOpIdx);
String right = exp.substring(nextOpIdx + 1);
int resultLeft = evaluate(left);
int resultRight = evaluate(right);
if (op == '+') {
return resultLeft + resultRight;
}
else if (op == '*') {
return resultLeft * resultRight;
}
else {
throw new NotImplementedException();
}
}
}
public static void main(String[] args) throws NotImplementedException {
String[] exps = {"(1+(2*4))", "((1+1)*(2*(3+3)))"};
for (int i = 0; i < exps.length; i++) {
System.out.println(exps[i] + " = " + evaluate(exps[i].replaceAll(" ", "")));
}
}
}
/** This class provides methods that are useful for
* processing mathematical expressions as strings.
*
* @author Adam Blank
*/
public class EvaluatorUtilities {
/** Returns true if the given string can be interpreted
* as a number, false otherwise.
*/
public static boolean isNumber(String x) {
for (int i = 0; i < x.length(); i++) {
if (x.charAt(i) < '0' || x.charAt(i) > '9') {
return false;
}
}
return true;
}
/** Returns the index in the given string of the next operator to be
* evaluated. <br> Returns -1 if there is no operator in exp.<br><br>
*
* For example, if exp is "(((1+2)*3)+(4*2))", nextOperator
* would return 10, because the "+" is the outermost operator
* and should be evaluated next.<br><br>
*
* This method considers "+", "*", "^", and "-" to be operators.
*/
public static int nextOperatorIndex(String exp) {
int parens = 0;
for (int i = 0; i < exp.length(); i++) {
char c = exp.charAt(i);
if (c == '(') {
parens++;
}
else if (c == ')') {
parens--;
}
if (parens == 0 && (c == '+' || c == '*' || c == '^' || c == '-')) {
return i;
}
}
return -1;
}
/** Returns a character representing the next operator in
* the given string. <br> Returns '?' if there is no such operator.<br><br>
*
* See {@link #nextOperatorIndex(String) nextOperatorIndex} for more description of 'next'
* and 'operator'.
*/
public static char nextOperator(String exp) {
int opIndex = nextOperatorIndex(exp);
if (opIndex == -1) {
return '?';
}
return exp.charAt(nextOperatorIndex(exp));
}
}
class NotImplementedException extends Exception {
private static final long serialVersionUID = 1L;
}
/** This class provides a method to evaluate fully parenthesized mathematical
* expressions.
*
* @author Adam Blank
*/
public class IterativeEvaluator {
/** Evaluates fully parenthesized mathematical expressions that use addition
* and multiplication. */
public static int evaluate(String exp) throws NotImplementedException {
int lastOpen = -1;
while (!EvaluatorUtilities.isNumber(exp)) {
int nextClose = 0;
/* Find the next chunk surrounded by parentheses. */
while (exp.charAt(nextClose) != ')') {
if (exp.charAt(nextClose) == '(') {
lastOpen = nextClose;
}
nextClose++;
}
String subExp = exp.substring(lastOpen + 1, nextClose);
/* Split the string up by the op */
int opIndex = EvaluatorUtilities.nextOperatorIndex(subExp);
String left = subExp.substring(0, opIndex);
String right = subExp.substring(opIndex + 1, subExp.length());
char op = EvaluatorUtilities.nextOperator(subExp);
String result = "";
if (op == '+') {
result = "" + (Integer.parseInt(left) + Integer.parseInt(right));
}
else if (op == '*') {
result = "" + (Integer.parseInt(left) * Integer.parseInt(right));
}
else {
throw new NotImplementedException();
}
exp = exp.substring(0, lastOpen) + result + exp.substring(nextClose + 1);
}
return Integer.parseInt(exp);
}
public static void main(String[] args) throws NotImplementedException {
String[] exps = {"(1+(2*4))", "((1+1)*(2*(3+3)))"};
for (int i = 0; i < exps.length; i++) {
System.out.println(exps[i] + " = " + evaluate(exps[i].replaceAll(" ", "")));
}
}
}
public class LinkedListStuff {
private static class ListNode {
int data;
ListNode next;
public ListNode(int data) {
this(data, null);
}
public ListNode(int data, ListNode next) {
this.data = data;
this.next = next;
}
}
public static boolean contains(ListNode head, int needle) {
if (head == null) {
return false;
}
else {
int data = head.data;
if (data == needle) {
return true;
}
ListNode rest = head.next;
boolean result = contains(rest, needle);
return result;
}
}
public static void main(String[] args) {
System.out.println(contains(new ListNode(1, new ListNode(2, new ListNode(3))), 4));
}
}
/** This class provides a method to compute symbolic derivatives of the
* given function with respect to x.
*
* @author Adam Blank
*/
public class SymbolicDifferentiation {
private static final String x = "x";
/** Checks if exp is a constant with respect to x */
public static boolean isConstant(String exp) {
return EvaluatorUtilities.isNumber(exp) || exp.equals("n") || exp.equals("e");
}
/** Computes the symbolic derivative of exp with respect to x */
public static String ddx(String exp) throws NotImplementedException {
exp = exp.replaceAll(" ", "");
/* Remove the outermost parentheses */
if (exp.charAt(0) == '(') {
exp = exp.substring(1, exp.length() - 1);
}
/* dx/dx = 1 */
if (exp.equals(x)) {
return "1";
}
/* dc/dx = 0 */
else if (EvaluatorUtilities.nextOperatorIndex(exp) == -1) {
return "0";
}
/* Split the string up by the op */
int opIndex = EvaluatorUtilities.nextOperatorIndex(exp);
String left = exp.substring(0, opIndex);
String right = exp.substring(opIndex + 1, exp.length());
char op = EvaluatorUtilities.nextOperator(exp);
/* (d/dx)(f(x) + g(x)) = df/dx + dg/dx */
if (op == '+' || op == '-') {
return String.format("(%s %s %s)", ddx(left), op, ddx(right));
}
/* (d/dx)(f(x) * g(x)) = ((f(x) * dg/dx) + (df/dx * g(x))) */
else if (op == '*') {
return String.format("((%s * %s) + (%s * %s))", left, ddx(right), right, ddx(left));
}
else if (op == '^') {
/* dc/dx = 0 */
if ((isConstant(left) && isConstant(right))) {
return "0";
}
/* (d/dx)(e^x) = e^x */
else if (left.equals("e") && right.equals(x)) {
return "(e^x)";
}
/* (d/dx)(x^n) = (n * (x ^ (n - 1))) */
else if (left.equals(x) && isConstant(right)) {
return String.format("(%s * ((%s^(%s - 1))))", right, left, right);
}
/* Chain Rule: Let f(x) = x^C -> f(g(x)).
* (d/dx)(f(g(x))) = ((df/dx)(g(x)) * (dg/dx)) */
else if (left.contains(x) && !right.contains(x)) {
System.out.println(left + " | " + right);
String df = ddx("(x^" + right + ")");
String dfOfg = df.replaceAll("x", left);
return String.format("(%s * %s)", dfOfg, ddx(left));
}
else {
/* Note that most of the other cases are a single case that we could
* write by implementing the chain rule. */
throw new NotImplementedException();
}
}
else {
/* This would just involve implementing more rules... */
throw new NotImplementedException();
}
}
public static void main(String[] args) throws NotImplementedException {
String[] exps = {"(2 * (x^n))", "(((2 * (x^n))*(e^x)) + (x*(2^n)))"};
for (int i = 0; i < exps.length; i++) {
System.out.println("(d/dx)(" + exps[i] + ") = " + ddx(exps[i].replaceAll(" ", "")));
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment