Reduce number of parentheses for a binary expression tree - java

I have a function that receives a binary expression tree and returns a String with the expression in-order. The only "problem" is that the resulting expression have too many parentheses,
e.g.: The function returns (a + (b * c)), but it can be reduced to a + b * c.
It is defined with the binary operators +, -, *, /, and the unary operator _ (negative).
What I really want to know is if I can modify the already existing function to reduce the number of parentheses in an efficient way, or create another function that operates with the String of the in-order expression.
The function is as follows:
private static String infijo(ArbolB t){
String s = "";
if (t != null) {
String info = String.valueOf(t.info);
if ("+-*/".contains(info)) s += "(";
if ("_".contains(info)) s += "-(";
s += infijo(t.left) + (info.equals("_") ? "" : info) + infijo(t.right);
if ("+-*/_".contains(String.valueOf(t.info))) s += ")";
}
return s;
}
Where ArbolB is a binary tree defined by:
public class ArbolB {
ArbolB right;
ArbolB left;
Object info;
public ArbolB(Object info, ArbolB right, ArbolB left){
this.info = info;
this.right = right;
this.left = left;
}
}

After writing this whole thing out, I realized that I didn't really answer your question properly (my solution ignores PEMDAS and just matches pairs, d'oh!). So, take from this what you can... I'm not throwing it out :P
I think you COULD solve this either way, but here would be my preferred method, using and trusting what you already have. There's probably a good way to use nodes to do this, but why not use what you have, right?
Starting from the point where you have your expression as a string (e.g. "((2*2) + _(3+3))" you could try something like:
public string RemoveUnnecessaryParens(string expression)
{
readonly string openParen = "(";
readonly string closeParen = ")";
// char array would also work for this
// multiple ways to track "balance" of parens, lets use int
int unclosedParenCount = 0;
string toReturn = "";
// iterate through the expression
for (int i = 0; i < expression.Length; i++)
{
string current = expression.Substring(i,1);
if (openParen == current)
unclosedParenCount++;
else if (closedParen == current)
unclosedParenCount--;
else
toReturn += current;
if (unclosedParenCount < 0) throw new UnbalancedExpressionException(); // One more close than open! Uh oh!
}
if (0 != unclosedParenCount) throw new UnbalancedExpressionException(); // One more open than close at the end! Uh oh!
else return toReturn;
}
Make sense?

Well, after thinking it a while, I got to a solution myself, by adding a priority function for determining when parentheses were necessary, and a variable that indicates if the operation was on the left or the right side of the formula, this because a-b+c don't need parentheses, but c+(a-b) do need them.
private static String infijo(ArbolB t, int priority, boolean right) {
String s = "";
int oP = 0;
if (t != null) {
String info = String.valueOf(t.info);
int pi = priority(info);
if ("+-*/".contains(info)) {
/* this only adds parentheses if the operation has higher priority or if the
operation on the right side should be done before the one on the left side*/
if ("+-*/".contains(info)) {
if (pi/2 < priority/2) s += "(";
else s += pi/2 == priority/2 && pi != priority && right ? "(" : "";
oP = priority; //stores the old priority
priority= pi; //priority of the new operator
}
}
if ("_".contains(info)) {
s += "-";
oP = priority;
priority = pi;
}
s += infijo(t.left, priority, false) + (info.equals("_") ? "" : info)
+ infijo(t.right, priority, true);
if ("+-*/".contains(info)) {
// adds the closing parentheses following the same rules as for the opening ones
if (priority / 2 < oP / 2) s += ")";
else s += priority / 2 == oP / 2 && priority != oP && right ? ")" : "";
}
}
return s;
}
private static int priority(String op) {
if ("_".contains(op)) return 4;
if ("/".contains(op)) return 3;
if ("*".contains(op)) return 2;
if ("-".contains(op)) return 1;
return 0;
}
#Override
public String toString() {
ArbolB f = getFormula(); //this returns the Binary Expression Tree
return infijo(f, Integer.MIN_VALUE, false);
}

Related

Fastest way to check if a haystack contains set of needles

I have a haystack string and I would like to check if it contains any of the needle strings. Currently I do it that way:
Set<String> needles = ...;
...
String [] pieces = haystack.split(" ");
for (String piece: pieces) {
if (needles.contains(piece) {
return true;
}
}
return false;
It works, but it is relatively slow.
Question: Is there a faster way to accomplish the task?
Example.
Haystack: I am a big tasty potato .
Needles: big, tasty
== RUN ==
I am a big tasty potato .
|
[tasty] got a match, we are good!
You should take a look at Aho-Corasick algorithm. This suits your problem because it build an automaton of all words(needles) and traverse the text(haystack) over the built automaton to find all matching words. Its basically constructs a finite state machine that resembles a trie.
The time complexity is O(n + m + z) where
z is the total number of occurrences of words in text, n is the length of text and m is the total number characters in all words.
Edit 2
Here is a straight-forward implementation which stop traversing after finding first occurrence of any needle.
import java.util.*;
class AhoCorasick {
static final int ALPHABET_SIZE = 256;
Node[] nodes;
int nodeCount;
public static class Node {
int parent;
char charFromParent;
int suffLink = -1;
int[] children = new int[ALPHABET_SIZE];
int[] transitions = new int[ALPHABET_SIZE];
boolean leaf;
{
Arrays.fill(children, -1);
Arrays.fill(transitions, -1);
}
}
public AhoCorasick(int maxNodes) {
nodes = new Node[maxNodes];
// create root
nodes[0] = new Node();
nodes[0].suffLink = 0;
nodes[0].parent = -1;
nodeCount = 1;
}
public void addString(String s) {
int cur = 0;
for (char ch : s.toCharArray()) {
int c = ch;
if (nodes[cur].children[c] == -1) {
nodes[nodeCount] = new Node();
nodes[nodeCount].parent = cur;
nodes[nodeCount].charFromParent = ch;
nodes[cur].children[c] = nodeCount++;
}
cur = nodes[cur].children[c];
}
nodes[cur].leaf = true;
}
public int suffLink(int nodeIndex) {
Node node = nodes[nodeIndex];
if (node.suffLink == -1)
node.suffLink = node.parent == 0 ? 0 : transition(suffLink(node.parent), node.charFromParent);
return node.suffLink;
}
public int transition(int nodeIndex, char ch) {
int c = ch;
Node node = nodes[nodeIndex];
if (node.transitions[c] == -1)
node.transitions[c] = node.children[c] != -1 ? node.children[c] : (nodeIndex == 0 ? 0 : transition(suffLink(nodeIndex), ch));
return node.transitions[c];
}
// Usage example
public static void main(String[] args) {
AhoCorasick ahoCorasick = new AhoCorasick(1000);
ahoCorasick.addString("big");
ahoCorasick.addString("tasty");
String s = "I am a big tasty potato";
int node = 0;
for (int i = 0; i < s.length(); i++) {
node = ahoCorasick.transition(node, s.charAt(i));
if (ahoCorasick.nodes[node].leaf) {
System.out.println("A match found! Needle ends at: " + i); // A match found! Needle ends at: 9
break;
}
}
}
}
However currently this code will find the end position of any occurrences in text. If you need the starting position and/or the needle, you can trace back from the ending position until finding a space to get the matched word.
This doesn't guaranty speed in worst-case, but should work better on average and best cases.
You can use java8 plus with parallel streams with anymatch function
boolean hi=Arrays.stream(pieces).parallel().anyMatch(i->needle.contains(i));
You should make sure needless is an instance of a HashSet which makes contains a "fast", constant time operation. Next, don't process all of haystack if you don't have to... Try this:
int i, j, l = haystack.length();
for(i = 0; i < l; i = j + 1) {
j = haystack.indexOf(' ', i + 1);
if(j == -1) {
j = l - 1;
}
String hay = haystack.s substring(i, j - 1).trim();
if(hay.length() > 0 && needles.contains(hay)) {
return true;
}
}
return false;
*note: this is untested and indexes might be off by +-1, as well as some edge cases might exist. use at your own risk.
Generally most of your slowdown is the split command. You are way better off searching the one string you have than allocating a crap ton of objects. You'd be better off doing regex, and avoiding new object construction. And using Aho would be quite effective. Assuming your lists are big enough to be troublesome.
public class NeedleFinder {
static final int RANGEPERMITTED = 26;
NeedleFinder next[];
public NeedleFinder() {
}
public NeedleFinder(String haystack) {
buildHaystack(haystack);
}
public void buildHaystack(String haystack) {
buildHaystack(this,haystack,0);
}
public void buildHaystack(NeedleFinder node, String haystack, int pos) {
if (pos >= haystack.length()) return;
char digit = (char) (haystack.charAt(pos) % RANGEPERMITTED);
if (digit == ' ') {
buildHaystack(this,haystack,pos+1);
return;
}
if (node.next == null) node.next = new NeedleFinder[RANGEPERMITTED];
if (node.next[digit] == null) node.next[digit] = new NeedleFinder();
NeedleFinder nodeNext = node.next[digit];
buildHaystack(nodeNext,haystack,pos+1);
}
public boolean findNeedle(String needle) {
return findNeedle(this, needle,0);
}
private boolean findNeedle(NeedleFinder node, String needle, int pos) {
if (pos >= needle.length()) return true;
char digit = (char) (needle.charAt(pos) % RANGEPERMITTED);
if (node.next == null) return false;
if (node.next[digit] == null) return false;
return findNeedle(node.next[digit],needle,pos+1);
}
}
On success, check the contains to make sure it's not a false positive. But, it's fast. We're talking 1/5th the speed of binary search.
Speaking of, binary search is a great idea. It's in the right time complexity alone. Just sort your silly list of haystack strings then when you look through the needles do a binary search. In java these are really basic and items in Collections. Both the .sort() and the .binarySearch() commands. And it's going to be orders of magnitude better than brute.
value = Collections.binarySearch(haystackList, needle, strcomp);
If value is positive it was found.
Collections.sort(words, strcomp);
With the strcomp.
public Comparator<String> strcomp = new Comparator<String>() {
#Override
public int compare(String s, String t1) {
if ((s == null) && (t1 == null)) return 0;
if (s == null) return 1;
if (t1 == null) return -1;
return s.compareTo(t1);
}
};
If it's really all about speed, and you want to search through a list of items instead of a solid string, you could divide the work into different threads (I'm not sure how many items you're checking with, but if it's not taking minutes, this might not be the way to go)
If you don't need to make the haystack into an array, you could instead iterate through needles, and test haystack via String.contains();

Constructing a Tree from an arithmetic expression

I'm pretty lost at the moment on how I would go about implementing this Tree, I'm trying to construct a Tree from a string representation of input "(4 + 6) + (2 + 3)". How would I go about making a Tree from two Stacks?
public class Tree {
private Stack opStk = new Stack();
private Stack valStk = new Stack();
private Tree parent = null;
public Tree(String str){
System.out.println((EvaluateExpression(str)));
}
public void doOperation() {
Object x = valStk.pop();
Object y = valStk.pop();
Object op = opStk.pop();
if ((Integer) x <= 0 || (Integer) y <= 0){
throw new NumberFormatException();
}
if (op.equals("+")) {
int sum = (Integer) x + (Integer) y;
valStk.push(sum);
}
}
public void repeatOps(char refOp) {
while (valStk.count() > 1 &&
prec(refOp) <= prec((char)opStk.pop())) {
doOperation();
}
}
int prec(char op) {
switch (op) {
case '+':
case '-':
return 0;
case '*':
case '/':
return 1;
case '^':
return 2;
default:
throw new IllegalArgumentException("Operator unknown: " + op);
}
}
public Object EvaluateExpression(String str) {
System.out.println("Evaluating " + str);
Scanner s = null;
try {
s = new Scanner(str);
//while there is tokens to be read
while (s.hasNext()) {
//if token is an int
if (s.hasNextInt()) {
//read it
int val = s.nextInt();
if(val <= 0) {
throw new NumberFormatException("Non-positive");
}
System.out.println("Val " + val);
//push it to the stack
valStk.push(val);
} else {
//push operator
String next = s.next();
char chr = next.charAt(0);
System.out.println("Repeat Ops " + chr);
repeatOps(chr);
System.out.println("Op " + next);
opStk.push(chr);
}
repeatOps('+');
}
} finally {
if (s != null) {
s.close();
}
}
System.out.println("Should be the result: " + valStk.pop());
return valStk.pop();
}
I have a few suggestions to make that might set you on the right path (hopefully).
Firstly I suggest your expression tree follow the Composite Design Pattern. It works very well for these types of hierarchies. For your purpose it would look something like:
interface Expression {
int getValue();
}
class Constant implements Expression {
private int value;
public int getValue() {
return value;
}
}
class Operation implements Expression {
private Expression operand1;
private Operator operator;
private Expression operand2;
public int getValue() {
return operator.apply(operand1, operand2);
}
}
Note that you don't need any concept of operator precedence or parentheses: it's entirely implicit in how the tree is constructed. For example "3 + 4 * 2" should result in a tree "(+ 3 (* 4 2))" while "(3 + 4) * 2" should result in a tree "(* (+ 3 4) 2)".
Secondly I suggest you make your operators into an enum rather than relying on the string values:
enum Operator {
TIMES((n1, n2) -> n1 * n2),
DIVIDE((n1, n2) -> n1 / n2),
PLUS((n1, n2) -> n1 + n2),
MINUS((n1, n2) -> n1 - n2);
private final BinaryOperator<Integer> operation;
Operator(BinaryOperator<Integer> operation) {
this.operation = operation;
}
public int apply(int operand1, int operand2) {
return operation.apply(operand1, operand2);
}
}
The advantage of this approach is that it's trivial to add new operators without changing the structure of the tree at all.
Thirdly I suggest you split your conversion from string to expression tree into two steps. The first is to convert from string to tokens and the second from token to trees. These are call lexical and semantic analysis in the jargon.
If you are using the shunting yard algorithm for the semantic analysis then keep in mind that the output stack will hold Expression instances ready to become operands. I can give you more detail on how to shunt operators but it's probably worth you giving the suggestions above a try first.

Detecting if a word is valid when it contains a blank

I'm working on a phone based word game, and there could potentially be quite a few blanks (representing any letter) that a player could have the option to use.
I store all the possible words in a hashSet, so detecting if a word is valid when it has one blank is simply a matter of looping through the alphabet replacing the blank with a letter and testing the word. I have a recursive call so this will work with any number of blanks. The code is as follows:
public boolean isValidWord(String word) {
if (word.contains(" ")){
for (char i = 'A'; i <= 'Z'; i++) {
if (isValidWord(word.replaceFirst(" ", Character.toString(i))))
return true;
}
return false;
}
else
return wordHashSet.contains(word);
}
As the number of blanks increases, the number of words we have to test increase exponentially. By the time we get to 3 blanks we're having to do 17576 lookups before we can reject a word, and this is affecting game play. Once there are 4 blanks the game will just freeze for a while.
What is the most efficient way for me to check words with multiple blanks. Should I just iterate through the hashset and check if we have a match against each word? If so, then what's the fastest way for me to compare two strings taking the blanks into account? I've tried doing this using a regular expression and String.matches(xx), but it's too slow. A straight String.equals(xx) is fast enough, but that obviously doesn't take blanks into account.
A very fast method althrough somewhat challenging to implement would be to store your words in a Trie - http://en.wikipedia.org/wiki/Trie
A trie is a tree structure that contains a char in every node and an array of pointers pointing to next nodes.
Without blank spaces it would be easy - just follow the trie structure, you can check this in linear time. When you have a blank, you will have a loop to search all possible routes.
This can sound complicated and difficult if you are not familiar with tries but if you get stuck I can help you with some code.
EDIT:
Ok, here is some c# code for your problem using tries, I think you will have no problems converting it in JAVA. If you do, leave a comment and I will help.
Trie.cs
public class Trie
{
private char blank = '_';
public Node Root { get; set; }
public void Insert(String key)
{
Root = Insert(Root, key, 0);
}
public bool Contains(String key)
{
Node x = Find(Root, key, 0);
return x != null && x.NullNode;
}
private Node Find(Node x, String key, int d)
{ // Return value associated with key in the subtrie rooted at x.
if (x == null)
return null;
if (d == key.Length)
{
if (x.NullNode)
return x;
else
return null;
}
char c = key[d]; // Use dth key char to identify subtrie.
if (c == blank)
{
foreach (var child in x.Children)
{
var node = Find(child, key, d + 1);
if (node != null)
return node;
}
return null;
}
else
return Find(x.Children[c], key, d + 1);
}
private Node Insert(Node x, String key, int d)
{ // Change value associated with key if in subtrie rooted at x.
if (x == null) x = new Node();
if (d == key.Length)
{
x.NullNode = true;
return x;
}
char c = key[d]; // Use dth key char to identify subtrie.
x.Children[c] = Insert(x.Children[c], key, d + 1);
return x;
}
public IEnumerable<String> GetAllKeys()
{
return GetKeysWithPrefix("");
}
public IEnumerable<String> GetKeysWithPrefix(String pre)
{
Queue<String> q = new Queue<String>();
Collect(Find(Root, pre, 0), pre, q);
return q;
}
private void Collect(Node x, String pre, Queue<String> q)
{
if (x == null) return;
if (x.NullNode) q.Enqueue(pre);
for (int c = 0; c < 256; c++)
Collect(x.Children[c], pre + ((char)c), q);
}
}
Node.cs
public class Node
{
public bool NullNode { get; set; }
public Node[] Children { get; set; }
public Node()
{
NullNode = false;
Children = new Node[256];
}
}
Sample usage:
Trie tr = new Trie();
tr.Insert("telephone");
while (true)
{
string str = Console.ReadLine();
if( tr.Contains( str ) )
Console.WriteLine("contains!");
else
Console.WriteLine("does not contain!");
}
A straight String.equals(xx) is fast enough, but that obviously
doesn't take blanks into account.
So I recommend to implement this simple solution, which is very close to String.equals(), and takes blanks into account:
public boolean isValidWord(String word) {
if (wordHashSet.contains(word)) {
return true;
}
for (String fromHashSet: wordHashSet){
if (compareIgnoreBlanks(fromHashSet, word)) {
return true;
}
}
return false;
}
/**
* Inspired by String.compareTo(String). Compares two String's, ignoring blanks in the String given as
* second argument.
*
* #param s1
* String from the HashSet
* #param s2
* String with potential blanks
* #return true if s1 and s2 match, false otherwise
*/
public static boolean compareIgnoreBlanks(String s1, String s2) {
int len = s1.length();
if (len != s2.length()) {
return false;
}
int k = 0;
while (k < len) {
char c1 = s1.charAt(k);
char c2 = s2.charAt(k);
if (c2 != ' ' && c1 != c2) {
return false;
}
k++;
}
return true;
}
public boolean isValidWord(String word) {
word = word.replaceAll(" ", "[a-z]");
Pattern pattern = Pattern.compile(word);
for (String wordFromHashSet: hashSet){
Matcher matcher = pattern.matcher(wordFromHashSet);
if (matcher.matches()) return true;
}
return false;
}
public boolean isValidWord(String word) {
ArrayList<Integer> pos = new ArrayList<Integer>();
for (int i=0; i!=word.length();i++){
if (word.charAt(i) == ' ') pos.add(i);
}
for (String hashSetWord: hashSet){
for (Integer i: pos){
hashSetWord = hashSetWord.substring(0,i)+" "+hashSetWord.substring(i+1);
}
if (hashSetWord.equals(word)) return true;
}
return false;
}
A kind of ugly, but I would guess fairly fast method would be to create a string containing all valid words like this:
WORD1
WORD2
WORD3
etc.
Then use a regex like (^|\n)A[A-Z]PL[A-Z]\n (i.e. replacing all blanks with [A-Z]), and match it on that string.

Java Binary Expression Tree - Checking parenthesis in an expression [duplicate]

This question already has answers here:
Handling parenthesis while converting infix expressions to postfix expressions
(2 answers)
Closed 6 years ago.
I coded up this program which will take an infix notation expression and build a binary tree from it. Right now the only input expression that actually works would be like 2 + 2. I can't seem to figure out at all how to make it handle parenthesis and take in longer expressions such as ( ( 2 + 2 ) * 3 ). For my output I am trying to get it into postfix notation and also evaluate the expression. So right now if I plug in 2 + 2 without the parenthesis my output is 22+ and it evaluates it so it prints 4.
I need to figure out a way for it to print out the output with spaces in between each number and operator and also get it to accept longer expressions with parenthesis. I have no idea right now how to continue from here. Can anyone please help me out?
Thanks!
This is my code:
class ExpressionEvaluator<T> {
ExpressionEvaluator() {
Scanner reader = new Scanner(System.in);
System.out.println("Enter your expression: ");
String expression = reader.nextLine(); // Reads the expression and trims the spaces.
expression = expression.replaceAll(" ", "");
ExpressTree<T> tree = new ExpressTree(expression); // Creates a new binary tree.
}
public static void main(String[] args) {
new ExpressionEvaluator();
}
}
interface Tree<T> {
// This is the tree interface with its methods.
public Node<T> getRoot();
public void setRoot(Node<T> value);
}
class ExpressTree<T> implements Tree<T> {
private Node<T> _root;
private String _value, _expression;
private Node<T> _treeNode;
private Stack storage1;
private Stack<String> storage2;
public ExpressTree(String expression) {
expressTreeBuilder(expression); // Calls the expressTreeBuilder method on the expression.
postfixTraversal(this.getRoot());
System.out.println("");
System.out.println(this.storage2.pop());
}
public Node<T> getRoot() { // Gets the root of the tree.
return _root;
}
public void setRoot(Node<T> _treeNode2) { // Sets the root which will always be an operator.
this._root = _treeNode2;
}
public boolean isDigit(char value) { // Method to check if a value is a digit or not.
if (Character.isDigit(value)) {
return true;
} else {
return false;
}
}
public void expressTreeBuilder(String expression) {
storage1 = new Stack(); // Stores the nodes.
storage2 = new Stack<String>(); // Stores the value of the nodes.
_treeNode = new Node(); // Creates a new node
_value = null;
String next = "";
for (int i = 0; i < expression.length(); i++) {
char traverse = expression.charAt(i);
if (i + 1 < expression.length()) {
next = Character.toString(expression.charAt(i + 1));
}
if (traverse == '+') { // This checks to see the expression is an addition operator.
Node<T> pop1, pop2; // It pops the first 2 values from the stack and stores them
String value1, value2; // in pop1 and pop2. Then it uses another stack to add them.
pop1 = (Node<T>) storage1.pop();
value1 = storage2.pop(); // Stores the right side value.
value2 = next; // Stores the left side value.
_treeNode = new Node();
_treeNode.setElement(Character.toString(traverse));
pop2 = new Node();
pop2.setElement(next);
pop1.setParent(_treeNode);
pop2.setParent(_treeNode);
_treeNode.setLeftSide(pop1); // Sets the right side of the subtree.
_treeNode.setRightSide(pop2); // Sets the left side of the subtree.
storage1.push(_treeNode);
storage1.push(pop2);
int add = (Integer.parseInt(value2) + Integer.parseInt(value1));
storage2.push(Integer.toString(add));
this.setRoot(_treeNode);
i++;
} else if (traverse == '-') { // This checks to see the expression is a subtraction operator.
Node<T> pop1, pop2; // It pops the first 2 values from the stack and stores them
String value1, value2; // in pop1 and pop2. Then it uses another stack to subtract them.
pop1 = (Node<T>) storage1.pop();
value1 = storage2.pop(); // Stores the right side value.
value2 = next; // Stores the left side value.
_treeNode = new Node();
_treeNode.setElement(Character.toString(traverse));
pop2 = new Node();
pop2.setElement(next);
pop1.setParent(_treeNode);
pop2.setParent(_treeNode);
_treeNode.setLeftSide(pop1); // Sets the right side of the subtree.
_treeNode.setRightSide(pop2); // Sets the left side of the subtree.
storage1.push(_treeNode);
storage1.push(pop2);
int subtract = (Integer.parseInt(value2) - Integer.parseInt(value1));
storage2.push(Integer.toString(subtract));
this.setRoot(_treeNode);
i++;
} else if (traverse == '*') { // This checks to see the expression is a multiplication operator.
Node<T> pop1, pop2; // It pops the first 2 values from the stack and stores them
String value1, value2; // in pop1 and pop2. Then it uses another stack to multiply them.
pop1 = (Node<T>) storage1.pop();
value1 = storage2.pop(); // Stores the right side value.
value2 = next; // Stores the left side value.
_treeNode = new Node();
_treeNode.setElement(Character.toString(traverse));
pop2 = new Node();
pop2.setElement(next);
pop1.setParent(_treeNode);
pop2.setParent(_treeNode);
_treeNode.setLeftSide(pop1); // Sets the right side of the subtree.
_treeNode.setRightSide(pop2); // Sets the left side of the subtree.
storage1.push(_treeNode);
storage1.push(pop2);
int multiply = (Integer.parseInt(value2) * Integer.parseInt(value1));
storage2.push(Integer.toString(multiply));
this.setRoot(_treeNode);
i++;
} else if (traverse == '(') {
} else {
_treeNode = new Node();
String digits = "";
while (i < expression.length() && isDigit(expression.charAt(i))) {
digits += expression.charAt(i); // Checks if the value found at the expression is digit
if (digits.length() == 1) {
break;
}
i++;
}
_treeNode.setElement(digits); // If it is it will set the element of the node
storage1.push(_treeNode); // The node will be pushed onto the stack.
storage2.push(digits); // This node will store it's value.
}
}
}
public void infixTraversal(Node<T> n) {
if (n != null) {
infixTraversal(n.getLeftSide());
System.out.print(n.element() + "");
infixTraversal(n.getRightSide());
}
}
public void postfixTraversal(Node<T> n) {
if (n != null) {
postfixTraversal(n.getLeftSide());
postfixTraversal(n.getRightSide());
System.out.print(n.element());
}
}
}
class Node<T> {
public Node<T> _left, _right, _parent;
private String _element;
public Node() {
this._element = null;
this._left = null;
this._right = null;
this._parent = null;
}
public String element() { // Gets the value of the node.
return _element;
}
public Node<T> getLeftSide() { // Gets the left side of the node.
return _left;
}
public Node<T> getRightSide() { // Gets the right side of the node.
return _right;
}
public Node<T> getParent() { // Gets the parent of the node.
return _parent;
}
public void setElement(String e) { // Sets the value of the node.
_element = e;
}
public void setLeftSide(Node<T> n) { // Sets the left side of the node.
_left = n;
}
public void setRightSide(Node<T> n) { // Sets the right side of the node.
_right = n;
}
public void setParent(Node<T> n) { // Sets the parent of the node.
_parent = n;
}
}
You will need a proper algorithm for converting your infix expression into a postfix expression. Once you have the expression in postfix it's a fairly easy matter of constructing a parse tree or evaluate the expression outright. A classic algorithm is the Shunting-yard algorithm, which is explained in quite extensive detail on wikipedia.
Once the algorithm to postfix is completed you do no longer have to worry about parathesis or operator precedence. It's just a stack of values and popping and pushing results.
There are several different problems in your question :
1) Parsing an expression and breaking it down into a tree. You need a lexer (or tokenizer) for this, even a simple one, which takes of precedence, parentheses, etc.
2) Converting/Evaluating your tree. There are some good classical algorithms for this.
3) Printing the outcomes (which I suspect is fairly simple once you have part 2 done; it's just a matter of adding the correct whitespaces and parentheses at the right places).
I would suggest to read some existing articles about all of this, let's say for instance :
http://www.javaworld.com/javaworld/jw-01-1997/jw-01-indepth.html (on Lexical Analysis)
http://www.javaworld.com/javaworld/jw-05-1997/jw-05-indepth.html (on building a parse tree and an interpreter)

Assigning Variables in a Java Calculator Program [Handling Assignments and Variables]

I am currently in the middle of a Java calculator program and everything seems to be working correctly, but I want more functionality.
As of right now a user can enter a mathematic expression and the program will solve it. However, I'd like the program to assign numeric values to variables such as x, y, or z.
Sample input/output could be:
Enter Expression: x=10/5
=> 2
Enter Expression: x
=> 2
public class Calculator
{
String expstring;
int cursor;
double x;
double y;
double z;
public Calculator()
{
expstring = null;
x = 0;
y = 0;
z = 0;
}
public Calculator(String instring)
{
expstring = instring;
cursor = 0;
}
public void setExpression(String estring)
{
expstring = estring;
cursor = 0;
}
public float evalExp()
{
if (expstring == null)
{
System.err.println("There is no expression to evaluate.");
System.err.println("Call setExpression() before calling getResult().");
return 0;
}
cursor = 0;
float result = evalTerm();
while (nextOperator('+') || nextOperator('-'))
{
char operator = getOperator();
float term = evalTerm();
if (operator == '+')
result = result + term;
if (operator == '-')
result -= term;
else
System.err.println("Invalid operator: " + operator);
}
return result;
}
private float evalTerm()
{
float result = getOperand();
while (nextOperator('*') || nextOperator('/'))
{
char operator = getOperator();
float term = getOperand();
if (operator == '*')
result = result * term;
if (operator == '/')
result /= term;
else
break;
}
return result;
}
private float getOperand()
{
if (cursor >= expstring.length())
return 0;
String opstring = "";
char nextchar = expstring.charAt(cursor);
if (nextchar == '-')
{
opstring = opstring + '-';
cursor++;
nextchar = expstring.charAt(cursor);
}
/** if (nextchar == 'x')
{
x =
}
*/
while (cursor < expstring.length() && !isOperator(nextchar))
{
opstring = opstring + nextchar;
cursor++;
if (cursor < expstring.length())
nextchar = expstring.charAt(cursor);
}
return Float.parseFloat(opstring);
}
private char getOperator()
{
char operator = expstring.charAt(cursor);
cursor++;
return operator;
}
private boolean nextOperator(char op)
{
if (cursor < expstring.length() && expstring.charAt(cursor) == op)
return true;
else
return false;
}
private boolean isOperator(char c)
{
String opset = "+*-/";
return (opset.indexOf(c) >= 0);
}
}
Here's what I've worked out so far, but I'm unsure how to implement it into code... The handling of variables and assignments can be embedded as special cases within the logical structure above, or it can be done in separate logic before/after the expression is evaluated. Your calculator class will need a field to store the value of each variable (x, y, and z). In an assignment, the first operand is a variable name and the first operator is =. The value of the expression to the right of = must be evaluated, and the value then can be stored in the field corresponding to the variable. If x, y, or z occurs in the expression to the right of =, its current value can be found in the corresponding field. The variables can be replaced with their values in the code that gets the next operand, or the variable values can be inserted in a separate pass through the expression before it is evaluated.
Any help, inciteful links, or suggestions would be great!
I'm new on the programming scene and would like to learn.
instead of the line
return Float.parseFloat(opstring);
you can verify if opstring begins with digit, something like
if (Character.isDigit(opstring.charAt(0)))
return Float.parseFloat(opstring);
else
return variables.get(opstring); // add additional test for null value!
you can declare variables container in your class as
final Map<String,Float> variables=new HashMap<String,Float>();
and initialize them when your parser encounters statements like var = expr
variable.put( name, value );
I don't know if this answer would be useful to you as I could not understand the problem very well but here are few suggestions :
To take a variable as input and print its value you can use a HashMap (java.util.HashMap) with String keys and Double values. This can be used to lookup values of variables by variable names. The same map can be used for complex expression such as x + y *z by parsing the expression and looking up the values.
For parsing you can use methods of String class such as indexOf, substring() etc. Also consider using the StringTokenizer class which can take delimiters (+,-,*,/ in your case) and split an expression into tokens.

Categories

Resources