Computer Science A
Course Progress
0/0
OCS Build and Lesson
Code Runner - Java
Code Runner - Examples
Code Runner - JavaScript
FRQ - Methods and Control Structures
Challenge Submission Test
2021 FRQ 3
2023 FRQ 3
2024 FRQ 3
2024 FRQ 2
2024 FRQ 1
2024 FRQ 4
FRQ 2 - Sign Class
2023 FRQ 1
2021 FRQ 2
2019 FRQ 4
2019 FRQ 2
2019 FRQ 1
2016 FRQ 3
2018 FRQ Question 4
2018 FRQ Question 3
2018 FRQ Question 2
2018 FRQ Q1
2017 FRQ 4
2017 FRQ 3
2017 FRQ Question 2
2017 FRQ 1 - Homework
2016 FRQ 4
2016 FRQ 2
2016 FRQ Q1
FRQ - 2D Arrays
FRQ - ArrayLists
2025 FRQ 4
2025 FRQ 3
2025 FRQ 2
2025 FRQ 1
FRQ - Classes
FRQ - Array
2023 FRQ 4
2022 FRQ 4
2022 FRQ 3
2022 FRQ 2
2022 FRQ 1
2021 FRQ 4
2021 FRQ 1
2015 FRQ 4
2015 FRQ 2
2015 FRQ 1
2015 FRQ 3
2014 FRQ Q2 - Writing a Class
2019 FRQ 3 - Delimiters
2014 FRQ 1
RPN Calculator Lesson
Introduction to Java ML
Graph Heuristics - Data Structures
Graph Heuristics - Data Structures
Graph Heuristics
Collections
Calculator Enactment 2
Calculator Enactment 1
Sorts Part 2
Collectable Types and Collections
RPN Calculator - Interactive Lesson
Calculator Hack
Understanding Reverse Polish Notation (RPN)
Calculator Hack - Wayfinding
Calculator Hack - Tracking
Abstract Fibonaccii Hack
Data Types
Selection - Insertion Sort
Merge Sort
Search - Linear, Binary, HashMaps
Single Responsibility & API Chaining
Calculator Hack - Wayfinding
6 min read
•
Assignment
- Hack
- Calculator Project/Hack
- Code Runner Challenge
- Calulator takes an Expression
Hack
Review this code for key data structures. You will be required to enact a Calculator in the classroom.
Here are the guidelines…
- Enactment starts with Original Expression, turns into Tokenized Expression, then to RPN, and finishes with Final Result.
- Appoint a Caller(s). A caller is a person who prompts the figures (tokens) through the steps of the calculations. There could be a person that is the overall Caller and others that coordinate entrance and exits into Queues or Stacks.
- Create two to three Calculation expressions, one simple and one interesting. Assign people to be a Token, aka TermOrOperator. They will need to move through steps of calculation and into Queues or Stacks.
- On Calculation, you will need to simulate the compression of two to three TermOrOperator becoming a single TermOrOperator. This process will continue until you obtain a result.
- Do not rush through this, you will be judged for clarity and accuracy on representing alogorithm. It would be best if you simulated all the steps, as the main System.out.println shows it.
- To be a TermOrOperator, there are phone apps that make big numbers or symbols. You could change your representation on phone after a calculation, making your phone calculate to intermediate step.
- Forming teams in class of 9-10 would be best, three teams per class. Work it out. You have a class and a half, finals will be in Office Hours.
- Step through code in debugger, this will help you visualize. Code is in Hacks in Spring Portfolio.
- There will be a write-up and capture that needs to be a part of this assignment and blog.
Calculator Project/Hack
The intention of this project is to use the RPN technique to calculate an expression. This led to breaking down the expression into objects as follows.
Code Runner Challenge
RPN Calculator
View IPYNB Source
// CODE_RUNNER: RPN Calculator
class Main {
static class Token {
private final Character token;
private final int precedence;
private final java.util.function.BiFunction<Double, Double, Double> calculation;
private final int numArgs;
public Token() { this('0'); }
public Token(Character token) { this(token, 0, null, 0); }
public Token(Character token, int precedence, java.util.function.BiFunction<Double, Double, Double> calculation, int numArgs) {
this.token = token;
this.precedence = precedence;
this.calculation = calculation;
this.numArgs = numArgs;
}
public Character getToken() { return token; }
public int getPrecedence() { return precedence; }
public int getNumArgs() { return numArgs; }
public boolean isPrecedent(Token token) { return this.precedence > token.getPrecedence(); }
public Double calculate(Double operand1, Double operand2) { return this.calculation.apply(operand1, operand2); }
public String toString() { return this.token.toString(); }
}
static class TermOrOperator extends Token {
private final String value;
public TermOrOperator(String value) { this.value = value; }
public TermOrOperator(Character token) { super(token); this.value = null; }
public TermOrOperator(Character token, int precedence, java.util.function.BiFunction<Double, Double, Double> calculation) {
super(token, precedence, calculation, 2); this.value = null;
}
public TermOrOperator(Character token, int precedence, java.util.function.BiFunction<Double, Double, Double> calculation, int numArgs) {
super(token, precedence, calculation, numArgs); this.value = null;
}
public String getValue() { return value; }
public String toString() { return this.value == null ? super.toString() : this.value; }
}
static class Tokens {
private java.util.Map<Character, TermOrOperator> map;
public Tokens() { this.map = new java.util.HashMap<>(); }
public void put(Character token) { this.map.put(token, new TermOrOperator(token)); }
public void put(Character token, int precedence, java.util.function.BiFunction<Double, Double, Double> calculation) {
this.map.put(token, new TermOrOperator(token, precedence, calculation));
}
public void put(Character token, int precedence, java.util.function.BiFunction<Double, Double, Double> calculation, int numArgs) {
this.map.put(token, new TermOrOperator(token, precedence, calculation, numArgs));
}
public TermOrOperator get(Character token) { return this.map.get(token); }
public int getPrecedence(Character token) { return this.map.get(token).getPrecedence(); }
public boolean contains(Character token) { return this.map.containsKey(token); }
public String toString() { return this.map.toString(); }
}
static class Calculator {
private final String expression;
private java.util.ArrayList<TermOrOperator> terms = new java.util.ArrayList<>();
private java.util.ArrayList<TermOrOperator> rpnTerms = new java.util.ArrayList<>();
private Tokens operators = new Tokens();
private Tokens seperators = new Tokens();
private Double result = 0.0;
public Calculator(String expression) {
initOperators();
initSeperators();
this.expression = expression;
this.termTokenizer();
this.termsToRPN();
this.rpnToResult();
}
private void initOperators() {
operators.put('*', 3, (a, b) -> a * b);
operators.put('/', 3, (a, b) -> a / b);
operators.put('%', 3, (a, b) -> a % b);
operators.put('+', 4, (a, b) -> a + b);
operators.put('-', 4, (a, b) -> a - b);
operators.put('^', 2, (a, b) -> Math.pow(a, b));
operators.put('√', 1, (a, b) -> Math.sqrt(a), 1);
}
private void initSeperators() {
seperators.put(' ');
seperators.put('(');
seperators.put(')');
}
private void termTokenizer() {
int start = 0;
StringBuilder multiCharTerm = new StringBuilder();
for (int i = 0; i < this.expression.length(); i++) {
Character c = this.expression.charAt(i);
if (operators.contains(c) || seperators.contains(c)) {
if (multiCharTerm.length() > 0)
this.terms.add(new TermOrOperator(this.expression.substring(start, i)));
TermOrOperator t = operators.get(c);
if (t == null) t = seperators.get(c);
if (t != null && t.getToken() != ' ') this.terms.add(t);
start = i + 1;
multiCharTerm = new StringBuilder();
} else { multiCharTerm.append(c); }
}
if (multiCharTerm.length() > 0)
this.terms.add(new TermOrOperator(this.expression.substring(start)));
}
private void termsToRPN() {
java.util.Stack<TermOrOperator> operatorStack = new java.util.Stack<>();
for (TermOrOperator term : terms) {
if (term.getToken() == '(') {
operatorStack.push(term);
} else if (term.getToken() == ')') {
while (operatorStack.peek() != null && operatorStack.peek().getToken() != '(')
rpnTerms.add(operatorStack.pop());
operatorStack.pop();
} else if (operators.contains(term.getToken())) {
while (!operatorStack.isEmpty() && operators.contains(operatorStack.peek().getToken())
&& term.isPrecedent(operatorStack.peek()))
rpnTerms.add(operatorStack.pop());
operatorStack.push(term);
} else { this.rpnTerms.add(term); }
}
while (!operatorStack.isEmpty()) rpnTerms.add(operatorStack.pop());
}
private void rpnToResult() {
java.util.Stack<Double> calcStack = new java.util.Stack<>();
for (TermOrOperator term : this.rpnTerms) {
Double operand1 = 0.0, operand2 = 0.0, result = 0.0;
if (operators.contains(term.getToken())) {
if (term.getNumArgs() == 1) {
operand1 = calcStack.pop();
} else {
operand2 = calcStack.pop();
operand1 = calcStack.pop();
}
result = term.calculate(operand1, operand2);
calcStack.push(result);
} else { calcStack.push(Double.valueOf(term.getValue())); }
}
this.result = calcStack.pop();
}
public String toString() {
return "Original expression: " + this.expression + "\n" +
"Tokenized expression: " + this.terms.toString() + "\n" +
"Reverse Polish Notation: " + this.rpnTerms.toString() + "\n" +
"Final result: " + String.format("%.2f", this.result);
}
}
public static void main(String[] args) {
String[][] testCases = {
{"100 + 200 * 3", "Simple Math"},
{"(100 + 200) * 3", "Parenthesis Math"},
{"100.2 - 99.3", "Decimal Math"},
{"300 % 200", "Modulo Math"},
{"300/200", "Division Math"},
{"√(3^2 + 4^2)", "Pythagorean Theorem"}
};
for (String[] testCase : testCases) {
Calculator calc = new Calculator(testCase[0]);
System.out.println("=== " + testCase[1] + " ===");
System.out.println(calc);
System.out.println();
}
}
}
Main.main(null);
Lines: 1
Characters: 0
Output
Click "Run" in code control panel to see output ...
Calulator takes an Expression
Ultimately the class Calculator constructs a calculation object for an expression. This calculates the expression and saves the result and each of the intermediate step into instance variables.