Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions homework-g597-kirilenko/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
</parent>
<modelVersion>4.0.0</modelVersion>

<properties>
<spring.boot.version>1.4.2.RELEASE</spring.boot.version>
</properties>

<artifactId>homework-g597-kirilenko</artifactId>

<dependencies>
Expand All @@ -24,6 +28,38 @@
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.jeval</groupId>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Эту зависимость можно было бы выпилить, в целом.

<artifactId>jeval</artifactId>
<version>0.9.4</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.193</version>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,319 @@
package ru.mipt.java2016.homework.g597.kirilenko.task1;



import javafx.util.Pair;
import ru.mipt.java2016.homework.base.task1.Calculator;
import ru.mipt.java2016.homework.base.task1.ParsingException;

import java.util.Stack;
import java.util.*;

import static java.lang.Math.*;


public class MyCalculator implements Calculator {
private Stack<Double> numbers;
private Stack<Character> operations;

private final Map<String, String> variablesExpressions = new HashMap();
private final Map<String, Pair<ArrayList<String>, String>> functions = new HashMap();

private double calculateStandardExpression(String functionName, ArrayList<Double> arguments)
throws ParsingException {
if (functionName.equals("sin")) {
if (arguments.size() != 1) {
throw new ParsingException("Incorrect expression");
}
return sin(arguments.get(0));
}
if (functionName.equals("cos")) {
if (arguments.size() != 1) {
throw new ParsingException("Incorrect expression");
}
return cos(arguments.get(0));
}
if (functionName.equals("tg")) {
if (arguments.size() != 1) {
throw new ParsingException("Incorrect expression");
}
return tan(arguments.get(0));
}
if (functionName.equals("sqrt")) {
if (arguments.size() != 1) {
throw new ParsingException("Incorrect expression");
}
return sqrt(arguments.get(0));
}
if (functionName.equals("abs")) {
if (arguments.size() != 1) {
throw new ParsingException("Incorrect expression");
}
return abs(arguments.get(0));
}
if (functionName.equals("max")) {
if (arguments.size() != 2) {
throw new ParsingException("Incorrect expression");
}
return max(arguments.get(0), arguments.get(1));
}
if (functionName.equals("min")) {
if (arguments.size() != 2) {
throw new ParsingException("Incorrect expression");
}
return min(arguments.get(0), arguments.get(1));
}
if (functionName.equals("pow")) {
if (arguments.size() != 2) {
throw new ParsingException("Incorrect expression");
}
return pow(arguments.get(0), arguments.get(1));
}
if (functionName.equals("log")) {
if (arguments.size() != 2) {
throw new ParsingException("Incorrect expression");
}
return log(arguments.get(0)) / log(arguments.get(1));
}
if (functionName.equals("log2")) {
if (arguments.size() != 1) {
throw new ParsingException("Incorrect expression");
}
return log(arguments.get(0)) / log(2);
}
if (functionName.equals("rnd")) {
if (arguments.size() != 0) {
throw new ParsingException("Incorrect expression");
}
return random();
}
if (functionName.equals("sign")) {
if (arguments.size() != 1) {
throw new ParsingException("Incorrect expression");
}
return signum(arguments.get(0));
}
throw new ParsingException("Not standard expression.");
}

private boolean isStandardFunction(String functionName) {
return functionName.equals("sin") ||
functionName.equals("cos") ||
functionName.equals("tg") ||
functionName.equals("sqrt") ||
functionName.equals("pow") ||
functionName.equals("abs") ||
functionName.equals("sign") ||
functionName.equals("log") ||
functionName.equals("log2") ||
functionName.equals("rnd") ||
functionName.equals("max") ||
functionName.equals("min");

}

public String getVariableExpression(String variable) {
if (!variablesExpressions.keySet().contains(variable)) {
return null;
}
return variablesExpressions.get(variable);
}

public void setVariableExpression(String variable, String expression) {
variablesExpressions.put(variable, expression);
}

public void deleteVariable(String variable) {
variablesExpressions.remove(variable);
}

public ArrayList<String> getAllVariables() {
return new ArrayList<>(variablesExpressions.keySet());
}

public Pair<ArrayList<String>, String> getFunctionInfo(String functionName) {
return functions.get(functionName);
}

public boolean setFunction(String functionName, ArrayList<String> arguments, String expression) {
if (isStandardFunction(functionName)) {
return false;
}
functions.put(functionName, new Pair<>(arguments, expression));
return true;
}

public boolean deleteFunction(String functionName) {
if (isStandardFunction(functionName)) {
return false;
}
functions.remove(functionName);
return true;
}

public ArrayList<String> getAllFunctions() {
return new ArrayList<>(functions.keySet());
}

private boolean isDigit(char c) {
return (c >= '0' && c <= '9');
}

private boolean isLatinSymbol(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}

private boolean isUnderscore(char c) {
return c == '_';
}

private boolean isOpeningBracket(char c) {
return c == '(';
}


private Pair<Integer, Integer> getValueLexem(String expression, Integer startIndex) {
Integer firstIndex = startIndex;
while (firstIndex < expression.length() && !isUnderscore(expression.charAt(firstIndex)) &&
!isLatinSymbol(expression.charAt(firstIndex))) {
firstIndex += 1;
}
if (firstIndex >= expression.length()) {
return null;
}
Integer secondIndex = firstIndex;
while (secondIndex < expression.length() && (isUnderscore(expression.charAt(secondIndex)) ||
isLatinSymbol(expression.charAt(secondIndex)) || isDigit(expression.charAt(secondIndex)))) {
secondIndex += 1;
}
if (secondIndex == expression.length() || expression.charAt(secondIndex) != '(') {
return new Pair<>(firstIndex, secondIndex);
} else {
return getValueLexem(expression, secondIndex + 1);
}
}

private Pair<Pair<String, Pair<Integer, Integer>>, ArrayList<String>> getFunctionLexem(String expression) {
Integer firstIndex = 0;
while (firstIndex < expression.length() && !isUnderscore(expression.charAt(firstIndex)) &&
!isLatinSymbol(expression.charAt(firstIndex))) {
firstIndex += 1;
}
if (firstIndex >= expression.length()) {
return null;
}
Integer secondIndex = firstIndex;
while (secondIndex < expression.length() && (isUnderscore(expression.charAt(secondIndex)) ||
isLatinSymbol(expression.charAt(secondIndex)) || isDigit(expression.charAt(secondIndex)))) {
secondIndex += 1;
}
String name = expression.substring(firstIndex, secondIndex);
Pair<ArrayList<String>, Integer> arg = getArguments(expression, secondIndex);
ArrayList<String> arguments = arg.getKey();
Integer lastIndex = arg.getValue();
Pair<Integer, Integer> indices = new Pair<>(firstIndex, lastIndex);
return new Pair<>(new Pair<>(name, indices), arguments);
}

private Pair<ArrayList<String>, Integer> getArguments(String expression, Integer startIndex) {
ArrayList<String> arguments = new ArrayList<>();
Integer lastIndex = 0;
Integer balance = 1;
Integer currentIndex = startIndex + 1;
String currentArgument = "";
while (balance != 0) { //выражение уже проверено на корректность -> exception не выбрасываем
if (expression.charAt(currentIndex) == '(') {
balance += 1;
currentArgument += expression.charAt(currentIndex);
currentIndex++;
} else if (expression.charAt(currentIndex) == ')') {
balance -= 1;
currentArgument += expression.charAt(currentIndex);
currentIndex++;
} else if (balance == 1 && expression.charAt(currentIndex) == ',') {
arguments.add(currentArgument);
currentArgument = "";
currentIndex++;
} else {
currentArgument += expression.charAt(currentIndex);
currentIndex++;
}
}
arguments.add(currentArgument.substring(0, currentArgument.length() - 1));
return new Pair<>(arguments, currentIndex);
}

private Pair<Integer, Integer> findArgument(String expression, String argument) {
int lastIndex = expression.indexOf(argument, 0);
if (lastIndex == -1) {
return null;
}
return new Pair<>(lastIndex, lastIndex + argument.length());
}

private Double evaluateFunction(String expression, ArrayList<String> argumentsList,
ArrayList<Double> arguments) throws ParsingException {
for (int i = 0; i < argumentsList.size(); i++) {
String argument = argumentsList.get(i);
Pair<Integer, Integer> argCoord = findArgument(expression, argument);
while (argCoord != null) {
expression = expression.substring(0, argCoord.getKey()) + arguments.get(i).toString() +
expression.substring(argCoord.getValue(), expression.length());
argCoord = findArgument(expression, argument);
}
}
try {
return evaluateExpression(expression);
} catch (ParsingException e) {
throw e;
}
}



public double evaluateExpression(String expression) throws ParsingException {
expression = deleteSpaces(expression);


try {
Pair<Integer, Integer> valueLexem = getValueLexem(expression, 0);
while (valueLexem != null) {
Integer start = valueLexem.getKey();
Integer end = valueLexem.getValue();
String valueName = expression.substring(start, end);
String valExpr = getVariableExpression(valueName);
Double result = evaluateExpression(valExpr);
expression = expression.substring(0, start) + result.toString() +
expression.substring(end, expression.length());
valueLexem = getValueLexem(expression, 0);
}
Pair<Pair<String, Pair<Integer, Integer>>, ArrayList<String>> functionLexem =
getFunctionLexem(expression);
while (functionLexem != null) {
String functionName = functionLexem.getKey().getKey();
Integer start = functionLexem.getKey().getValue().getKey();
Integer end = functionLexem.getKey().getValue().getValue();
ArrayList<String> arguments = functionLexem.getValue();
ArrayList<Double> calculatedArguments = new ArrayList<>();
for (int i = 0; i < arguments.size(); i++) {
calculatedArguments.add(evaluateExpression(arguments.get(i)));
}
Double result = Double.NaN;
if (isStandardFunction(functionName)) {
result = calculateStandardExpression(functionName, calculatedArguments);
} else {
Pair<ArrayList<String>, String> func = getFunctionInfo(functionName);
result = evaluateFunction(func.getValue(), func.getKey(), calculatedArguments);
}
expression = expression.substring(0, start) + result.toString() +
expression.substring(end, expression.length());
functionLexem = getFunctionLexem(expression);
}
return calculate(expression);
} catch (ParsingException p) {
throw p;
}
}

@Override
public double calculate(String expression) throws ParsingException {
numbers = new Stack<>();
Expand All @@ -21,7 +325,6 @@ public double calculate(String expression) throws ParsingException {
if (!checkForConsequentNumbers(expression)) {
throw new ParsingException("Incorrect expression");
}
expression = deleteSpaces(expression);
if (!checkIncorrectExpression(expression)) {
throw new ParsingException("Incorrect expression");
}
Expand Down
Loading