Created
December 17, 2021 12:07
-
-
Save kosciolek/013ff1155422251141bb1c2a2ef62d9f to your computer and use it in GitHub Desktop.
some uni homework project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.Scanner; | |
import java.util.Stack; | |
// Troche pozmienialem nazwy metod/interfejsow ale poza tym to struktura prawie taka sama | |
// Dziala troche jak reverse polish notation (op popuje argumenty ze stacku i wrzuca result na stack) | |
class Main { | |
public static void main(String[] args) { | |
var calc = new Calculator( | |
List.of(new Factorial(), new Square(), new Sum(), new Diff(), new Pow(), new Mul(), new IntDiv(), | |
new Mod())); | |
while (2137 == 2137) { | |
Scanner sc = new Scanner(System.in); | |
System.out.println("Enter an op or an arg or 'RESET'."); | |
var line = sc.nextLine().trim(); | |
if ("RESET".equals(line)) { | |
calc.reset(); | |
System.out.println("Resetting the calculator..."); | |
continue; | |
} | |
try { | |
// arg case | |
var arg = Integer.parseInt(line); | |
calc.pushArg(arg); | |
calc.printStack(); | |
} catch (NumberFormatException ex) { | |
// op case | |
calc.setOpForSymbol(line); | |
calc.calculate(); | |
calc.printStack(); | |
} | |
} | |
} | |
} | |
class Calculator { | |
IOp op; | |
Stack<Integer> stack = new Stack<>(); | |
List<IOp> ops = new ArrayList<>(); | |
public Calculator(List<IOp> ops) { | |
this.ops = ops; | |
} | |
void pushArg(int arg) { | |
stack.add(arg); | |
} | |
void setOp(IOp op) { | |
this.op = op; | |
} | |
void setOpForSymbol(String symbol) { | |
var op = ops.stream().filter(operation -> operation.getSymbol().equals(symbol)).findAny().orElse(null); | |
if (op == null) | |
throw new Error("Could not find op for symbol " + symbol); | |
setOp(op); | |
} | |
void printStack() { | |
var argsList = new ArrayList<Integer>(stack); | |
Collections.reverse(argsList); | |
System.out.println( | |
"Stack: " + argsList.toString()); | |
} | |
int calculate() { | |
if (op instanceof IUnaryOp) { | |
if (stack.size() < 1) | |
throw new Error("Too few arguments on the stack to execute " + op.getSymbol()); | |
var unaryOp = (IUnaryOp) op; | |
var result = unaryOp.execute(stack.pop()); | |
stack.push(result); | |
return result; | |
} else if (op instanceof IBinaryOp) { | |
if (stack.size() < 2) | |
throw new Error("Too few arguments on the stack to execute " + op.getSymbol()); | |
var binaryOp = (IBinaryOp) op; | |
var result = binaryOp.execute(stack.pop(), stack.pop()); | |
stack.push(result); | |
return result; | |
} else | |
throw new Error("Invalid operation."); | |
}; | |
void reset() { | |
stack = new Stack<>(); | |
} | |
} | |
/* INTERFACES */ | |
interface IOp { | |
public String getSymbol(); | |
} | |
interface IUnaryOp extends IOp { | |
public int execute(int x); | |
} | |
interface IBinaryOp extends IOp { | |
public int execute(int x, int y); | |
} | |
/* OPS */ | |
class Factorial implements IUnaryOp { | |
String symbol = "!"; | |
public String getSymbol() { | |
return symbol; | |
} | |
public int execute(int x) { | |
if (x < 0) | |
throw new Error("Cannot compute the factorial of a negative number."); | |
return x == 0 ? 1 : x * this.execute(x - 1); | |
} | |
} | |
class Square implements IUnaryOp { | |
String symbol = "sqr"; | |
public String getSymbol() { | |
return symbol; | |
} | |
public int execute(int x) { | |
return (int) Math.pow(x, 2); | |
} | |
} | |
class Sum implements IBinaryOp { | |
String symbol = "+"; | |
public String getSymbol() { | |
return symbol; | |
} | |
public int execute(int x, int y) { | |
return x + y; | |
} | |
} | |
class Diff implements IBinaryOp { | |
String symbol = "-"; | |
public String getSymbol() { | |
return symbol; | |
} | |
public int execute(int x, int y) { | |
return x - y; | |
} | |
} | |
class Pow implements IBinaryOp { | |
String symbol = "^"; | |
public String getSymbol() { | |
return symbol; | |
} | |
public int execute(int x, int y) { | |
return (int) Math.pow(x, y); | |
} | |
} | |
class Mul implements IBinaryOp { | |
String symbol = "*"; | |
public String getSymbol() { | |
return symbol; | |
} | |
public int execute(int x, int y) { | |
return x * y; | |
} | |
} | |
class IntDiv implements IBinaryOp { | |
String symbol = "/"; | |
public String getSymbol() { | |
return symbol; | |
} | |
public int execute(int x, int y) { | |
if (y == 0) | |
throw new Error("Cannot divide by 0."); | |
return x / y; | |
} | |
} | |
class Mod implements IBinaryOp { | |
String symbol = "%"; | |
public String getSymbol() { | |
return symbol; | |
} | |
public int execute(int x, int y) { | |
return x % y; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment