import java.lang.*;
import java.util.*;
import java.util.regex.*;
//********************************************************************
// ListNode.java Author: AP Committee, comments added by
// Lewis/Loftus/Cocking
//
// A node in a linked list.
//********************************************************************
class ListNode
{
private Object value;
private ListNode next;
//-----------------------------------------------------------------
// Initializes this node.
//-----------------------------------------------------------------
public ListNode (Object initValue, ListNode initNext)
{
value = initValue;
next = initNext;
}
//-----------------------------------------------------------------
// Returns the value of this node.
//-----------------------------------------------------------------
public Object getValue ()
{
return value;
}
//-----------------------------------------------------------------
// Returns the next reference in this node.
//-----------------------------------------------------------------
public ListNode getNext ()
{
return next;
}
//-----------------------------------------------------------------
// Sets the value of this node.
//-----------------------------------------------------------------
public void setValue (Object theNewValue)
{
value = theNewValue;
}
//-----------------------------------------------------------------
// Sets the next reference in this node.
//-----------------------------------------------------------------
public void setNext (ListNode theNewNext)
{
next = theNewNext;
}
}
//********************************************************************
// LinkedList.java
//********************************************************************
class LinkedList
{
private ListNode head;
public LinkedList() { head = null; }
public void addToHead(Object o)
{
head = new ListNode(o, head);
}
public Object removeFromHead()
{
if(head==null) return null;
Object o = head.getValue();
head = head.getNext();
return o;
}
public Object head()
{
return (head==null)?null:head.getValue();
}
public Object removeFromTail()
{
Object o;
boolean headless = (head == null);
if(headless || head.getNext() == null)
{
if(!headless)
{
o = head.getValue();
head = null;
return o;
}
return null;
}
ListNode n = head;
while(n.getNext() != null && n.getNext().getNext() != null) { n = n.getNext(); }
o = n.getNext().getValue();
n.setNext(null);
return o;
}
public Object tail()
{
Object o;
boolean headless = (head == null);
if(headless || head.getNext() == null)
{
return headless?null:head.getValue();
}
ListNode n = head;
while(n.getNext() != null) { n = n.getNext(); }
return n.getValue();
}
public boolean isEmpty() { return (head == null); }
}
//********************************************************************
// Queue.java
//********************************************************************
class Queue
{
protected LinkedList list;
//-----------------------------------------------------------------
// Initializes the Queue.
//-----------------------------------------------------------------
public Queue() { list = new LinkedList(); }
//-----------------------------------------------------------------
// Returns true if queue is empty.
//-----------------------------------------------------------------
public boolean isEmpty() { return list.isEmpty(); }
//-----------------------------------------------------------------
// Adds an object to the queue.
//-----------------------------------------------------------------
public void push(Object o) { list.addToHead(o); }
//-----------------------------------------------------------------
// Removes an object from the queue.
//-----------------------------------------------------------------
public Object pop() { return list.removeFromTail(); }
//-----------------------------------------------------------------
// Returns the frontmost object.
//-----------------------------------------------------------------
public Object top() { return list.tail(); }
}
//********************************************************************
// Stack.java
//
// Stack extends Queue because they only differ by one function.
// Queue could have just as easily been based on Stack.
//********************************************************************
class Stack extends Queue
{
//-----------------------------------------------------------------
// Initializes the Stack.
//-----------------------------------------------------------------
public Stack() { super(); }
//-----------------------------------------------------------------
// Removes an object from the stack.
//-----------------------------------------------------------------
public Object pop() { return list.removeFromHead(); }
}
//********************************************************************
// my_prefixExpression.java
//********************************************************************
public class my_prefixExpression
{
public static void main(String args[])
{
Queue queue = new Queue();
System.out.println("Enter a prefix expression with format similar to \'(+ 1 (* 2 (% 3 4)))\':");
Scanner in = new Scanner(System.in);
String string = in.nextLine();
in.close();
System.out.println("Value:");
if(enqueuePrefix(queue, string))
{
System.out.println(evaluatePrefix(queue));
}
else
{
System.out.println("Invalid");
}
}
public static double dmod(double a, double b)
{
double c = Math.IEEEremainder(a, b);
return (c < 0.0)?(c+b):(c);
}
//-----------------------------------------------------------------
// Traverses & enqueue input using regular expressions.
//
// Note that this enqueuePrefix handles all syntactical errors.
//-----------------------------------------------------------------
private static boolean enqueuePrefix(Queue queue, String string)
{
// An operation is in the format (operator a b)
// where a and b can be operations or numbers
// The following is the regular expression for (operator a b)
Pattern op = Pattern.compile("^(\\(([+-/*%]) ([\\d]+|\\(.+\\)) ([\\d]+|\\(.+\\))\\))$");
// The following is the regular expression for an integer
Pattern num = Pattern.compile("^[\\d]+$");
Matcher match_op = op.matcher(string);
Matcher match_num = num.matcher(string);
if(match_op.matches()) // Input matched operation format
{
// Order the pieces backwards
boolean r = enqueuePrefix(queue, match_op.group(4))
&& enqueuePrefix(queue, match_op.group(3));
// Operations are stored as String
// because char does not extend Object
queue.push(match_op.group(2));
return r;
}
else if(match_num.matches()) // Input matched number format
{
queue.push(new Double(string));
return true;
}
return false;
}
//-----------------------------------------------------------------
// Evaluates enqueued prefix expression
//
// Note that this enqueuePrefix handles all syntactical errors.
//-----------------------------------------------------------------
private static double evaluatePrefix(Queue queue)
{
Stack stack = new Stack();
Double a, b;
// Transfer to stack and evaluate all objects in the queue
while(!queue.isEmpty())
{
Object o = queue.pop();
char op = o.toString().charAt(0);
if("+-*/%".indexOf(op,0)>-1) // Check for operation
{
a = (Double)stack.pop();
b = (Double)stack.pop();
// Extract char operation from String and evaluate
switch(op)
{
case '+': stack.push(new Double(a + b)); break;
case '-': stack.push(new Double(a - b)); break;
case '*': stack.push(new Double(a * b)); break;
case '/': stack.push(new Double(a / b)); break;
case '%': stack.push(new Double(dmod(a, b))); break;
}
}
else
{
stack.push(o);
}
}
return ((Double)stack.pop()).doubleValue();
}
}