Inspired by Dan's question on Stack Overflow.
Given this "program", the Stack will have one number at the top (i.e. 12).
( 3 * 4 ) .
/* * Copyright © 2013 - Elliott Frisch * * THIS SOFTWARE IS PROVIDED UNDER THE CREATIVE COMMONS * LICENSE 3.0 "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR * A PARTICULAR PURPOSE. * * To use this software you must agree to the complete * license terms available at: * http://creativecommons.org/licenses/by/3.0/us/deed.en_US * * It is the intent of the author(s) that you may use or * modify this software for any purpose (including your own * commercial gain) provided that this notice remains in its * entirety. * * Created by Elliott Frisch - www.frischcode.com * Daniel Brackett - www.danielbrackett.com */ package com.frischcode.util; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * <b>Rationale:</b> Implementing a basic Stack. Then * demonstrate an arbitrary precision math REPL with two * unbounded Stacks. Inspired by <a * href="http://stackoverflow.com/users/1516132/dan" * >Dan</a>'s question on <a href= * "http://stackoverflow.com/questions/19988147/stack-adding-machine-0doesnt-add-but-hangs-waiting-for-more-args" * >Stack Overflow</a>. * * @author Elliott Frisch * * @param <T> * A generic stack container. */ public class Stack<T> { private static final String UNDERFLOW = "Stack underflow error. Continuing."; private static final String OVERFLOW = "Stack over-flow error. Continuing."; private static final void say(String in) { if (in != null) { if (in.length() > 0) { System.out.println(in); System.out.flush(); } } } private static final void underFlow() { say(UNDERFLOW); } private static final void overFlow() { say(OVERFLOW); } private enum Operators { ADD("+"), SUB("-"), MULTIPLY("*"), DIVIDE("/"), POW( "^"); Operators(String oper) { _oper = oper; } private String _oper; public String toString() { return _oper; } public BigDecimal execute(BigDecimal a, BigDecimal b) { switch (this) { case ADD: return a.add(b); case SUB: return b.subtract(a); case MULTIPLY: return a.multiply(b); case DIVIDE: return b.divide(a); case POW: return a.pow(b.intValue()); } return null; } public static Operators matchOper(String in) { if (in != null) { in = in.trim(); for (Operators oper : Operators.values()) { if (oper.toString().equals(in)) { return oper; } } } return null; } } private List<T> a; public static void main(String[] args) { Stack<String> ops = new Stack<String>(5); Stack<BigDecimal> vals = new Stack<BigDecimal>(100); say("REPL loaded - BEGIN"); Scanner console = new Scanner(System.in); try { while (console.hasNext()) { String str = console.next().trim(); if (str.equals(".")) { say(vals.peek().toString()); } else if (str.equals("(")) { ; } else if (Operators.matchOper(str) != null) { ops.push(str); } else if (str.equals(")") || str.equals("=")) { Operators op = Operators .matchOper(ops.pop()); if (op != null) { BigDecimal a = vals.pop(); BigDecimal b = vals.pop(); if (a != null && b != null) { a = op.execute(a, b); } if (a != null) { vals.push(a); } } } else { try { final BigDecimal a = new BigDecimal(str); if (a != null) { vals.push(a); } } catch (Exception e) { say(e.getMessage() + ": " + str); } } } } finally { console.close(); } } /** * Construct an Empty Stack. Default to an initial * capacity of 10. */ public Stack() { this(10); } /** * Construct a Stack with an initial capacity of cap. * * @param cap * An initial capacity size. */ public Stack(int cap) { a = new ArrayList<T>(cap); } /** * Pushes an Item onto this Stack. Ignores null. * * @param item * The item to push onto the stack. */ public void push(T item) { if (item != null && !isFull()) { a.add(item); } else { overFlow(); } } /** * Pops the top item off the stack. Null if empty. * * @return The top item on the stack. Removes it. */ public T pop() { if (!isEmpty()) { return a.remove(a.size() - 1); } underFlow(); return null; } /** * Returns the item at the top of the Stack. That is what * pop() would return without modifying the Stack. * * @return The top item on the stack. Without removing it. */ public T peek() { if (!isEmpty()) { return a.get(a.size() - 1); } underFlow(); return null; } /** * This Stack is unbounded. * * @return return false. */ public boolean isFull() { return false; } /** * Return true if the Stack doesn't have any items. * * @return true if the Stack contains no items. */ public boolean isEmpty() { return a.size() == 0; } /** * The size of the stack + 1. * * @return The size of the Stack + 1. */ public int size() { return a.size(); } }
No comments :
Post a Comment