Skip to content
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
823468f
init : 프로젝트 초기화
heenahan Jun 5, 2023
9f99b95
feat : 중위 표기식을 후위 표기식으로 변환해서 계산
heenahan Jun 9, 2023
c78db4c
test : 사칙 연산 테스트
heenahan Jun 9, 2023
4e840f1
test : 후위표기식 변환 후 계산 테스트
heenahan Jun 9, 2023
27c0031
feat : 연산 결과 맵에 저장
heenahan Jun 9, 2023
bb2ba06
feat : 문자열 연산을 리스트 연산으로 변환
heenahan Jun 9, 2023
104c54b
test : 저장소, 문자열 연산을 리스트 연산으로 변환 테스트
heenahan Jun 9, 2023
91ae6e6
chore : 출력문 삭제
heenahan Jun 10, 2023
dd89153
feat : 유효하지 않은 입력값은 예외 던짐
heenahan Jun 10, 2023
73a262d
feat : DB은 불변해야 하므로 final
heenahan Jun 10, 2023
e4a7702
test : 잘못된 수식이 입력되는 예외 테스트
heenahan Jun 10, 2023
88acf06
feat : 입력과 출력 추가
heenahan Jun 10, 2023
46aed93
feat : 컨트롤러 추가
heenahan Jun 10, 2023
ef913ec
docs : gradle 파일 추가
heenahan Jun 15, 2023
679a107
refactor : 우선순위 enum에서 관리 및 enum 안에서 사칙 연산 수행
heenahan Jun 15, 2023
b00a4fb
refactor : 자료구조 변경 stack -> deque
heenahan Jun 15, 2023
9a70dfa
feat : custom exception 만듦
heenahan Jun 15, 2023
0abe54e
refactor : Operator를 ParameterizedTest를 사용해 여러 개를 테스트 및 Calculator 메서…
heenahan Jun 15, 2023
fa9691b
feat : 동일한 수식도 저장 및 시간 순으로 정렬한 리스트 반환
heenahan Jun 15, 2023
91ee3a9
feat : 자주 사용되는 정규식 패턴 미리 컴파일 후 사용
heenahan Jun 15, 2023
a8161ac
feat : 메뉴 enum에서 관리
heenahan Jun 15, 2023
6b41677
feat : 서비스 레이어로 분리
heenahan Jun 15, 2023
f0aff99
refactor : 컨트롤러 레이어 리팩토링
heenahan Jun 15, 2023
5e74365
refactor : 애플리케이션 클래스 이름 변경
heenahan Jun 15, 2023
752d38d
chore : import문 정리
heenahan Jun 15, 2023
d2e0f24
refactor : 후위 표현식 변환과 계산 분리
heenahan Jun 17, 2023
26995f4
refactor : Formula가 스스로 계산하도록 변경
heenahan Jun 17, 2023
8984cd5
feat : 저장소 List로 자료구조 변경
heenahan Jun 17, 2023
6ce753c
refactor : 저장과 계산 테스트 코드 변경
heenahan Jun 17, 2023
3a2acbf
refactor : 메뉴 번호 String으로 변경
heenahan Jun 17, 2023
8ec3a90
refactor : 서비스 레이어 리팩토링
heenahan Jun 17, 2023
d59e1c0
refactor : 컨트롤러 레이어 리팩토링
heenahan Jun 17, 2023
b813f7c
fix : 마이너스 부호 입력 시 유효하지 않는 입력 예외 발생
heenahan Jun 17, 2023
f781b5f
refactor :인자로 Formula를 받음
heenahan Jun 19, 2023
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
48 changes: 48 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/8.1.1/userguide/building_java_projects.html
* This project uses @Incubating APIs which are subject to change.
*/

plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
}

repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}

dependencies {
// This dependency is used by the application.
implementation 'com.google.guava:guava:31.1-jre'

// https://mvnrepository.com/artifact/org.assertj/assertj-core
testImplementation 'org.assertj:assertj-core:3.24.2'
}

testing {
suites {
// Configure the built-in test suite
test {
// Use JUnit Jupiter test framework
useJUnitJupiter('5.9.1')
}
}
}

// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}

application {
// Define the main class for the application.
mainClass = 'com.programmers.App'
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import com.programmers.controller.CalculatorController;

public class App {
public class CalculatorApplication {

public static void main(String[] args) {
CalculatorController calculatorController = new CalculatorController();
Expand Down
61 changes: 9 additions & 52 deletions app/src/main/java/com/programmers/calculator/Calculator.java
Original file line number Diff line number Diff line change
@@ -1,63 +1,20 @@
package com.programmers.calculator;

import java.util.*;
import java.util.List;

public class Calculator {

public List<String> changeInfixToPostfix(List<String> infix) {
List<String> postfix = new ArrayList<>();
Stack<String> stack = new Stack<>();

for (String s : infix) {
if (s.matches("\\d+")) { // 숫자일 경우
postfix.add(s);
} else { // 숫자 아닐 경우
int priority = getPriority(s);
// 스택이 비었거나
while (!stack.isEmpty()) {
String topOperator = stack.peek();
int topPriority = getPriority(topOperator);

// top의 우선 순위가 높거나 같을 경우
if (topPriority >= priority) postfix.add(stack.pop());
// top의 우선 순위가 낮을 경우
else break;
}
stack.push(s); // 연산자 넣음
}
}

// 스택에 남아있는 연산자 모두 집어 넣음
while (!stack.isEmpty()) postfix.add(stack.pop());

return postfix;
}
private final PostfixConversion postfixConversion;
private final PostfixCalculator postfixCalculator;

public Integer calcPostfix(List<String> postfix) {
Stack<Integer> stack = new Stack<>();

for (String s : postfix) {
// 숫자일 경우 스택에 넣음
if (s.matches("\\d+")) stack.push(Integer.parseInt(s));
else { // 연산자 일 경우
Integer op1 = stack.pop();
Integer op2 = stack.pop();

Operator calc = Operator.of(s);
Integer result = calc.getFunc().apply(op2, op1);

stack.push(result);
}
}

return stack.pop();
public Calculator() {
postfixConversion = new PostfixConversion();
postfixCalculator = new PostfixCalculator();
}

public Integer getPriority(String operator) {
// * 와 / 는 우선순위 높음
if (operator.equals("*") || operator.equals("/")) return 1;
// 그 외 낮음
return -1;
public Integer calculate(Formula formula) {
List<String> postfix = postfixConversion.changeInfixToPostfix(formula.getInfixListFormula());
return postfixCalculator.calculatePostfix(postfix);
}

}
44 changes: 44 additions & 0 deletions app/src/main/java/com/programmers/calculator/Formula.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.programmers.calculator;

import com.programmers.exception.InvalidFormulaException;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class Formula {

private static final Pattern FORMULA_REGEX = Pattern.compile("([0-9] [+|\\-|*|/] )+[0-9]");
private static final String EQUAL = " = ";

private final Calculator calculator;

private String formula;
private Integer result;

public Formula(String formula) {
isValid(formula);
this.formula = formula;
this.calculator = new Calculator();
}
Comment on lines +10 to +24

Choose a reason for hiding this comment

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

Formula는 어떻게 보면 데이터만 가지고 있는 객체인듯 한데요.
Calculator를 의존하신 이유가 있을까요??


public List<String> getInfixListFormula() {
return Arrays.stream(formula.split(" "))
.collect(Collectors.toList());
}

public void isValid(String formula) {
if (!FORMULA_REGEX.matcher(formula).matches()) throw new InvalidFormulaException("유효하지 않은 수식 입력입니다.");
}

public Integer calcualteFormula() {
result = calculator.calculate(this);
return result;
}

public String toString() {
return formula + EQUAL + result;
}

}
42 changes: 0 additions & 42 deletions app/src/main/java/com/programmers/calculator/Operator.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.programmers.calculator;

import com.programmers.util.Operator;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.regex.Pattern;

public class PostfixCalculator {

private static final Pattern NUMBER = Pattern.compile("\\d+");

public Integer calculatePostfix(List<String> postfix) {
Deque<Integer> deque = new ArrayDeque<>();

postfix.stream()
.forEach(s -> { calculatePostfixWithDeque(s, deque); });

return deque.pollLast();
}

private void calculatePostfixWithDeque(String s, Deque<Integer> deque) {
if (NUMBER.matcher(s).matches()) {
deque.addLast(Integer.parseInt(s));
return;
}
// 연산자 일 경우
Integer op1 = deque.pollLast();
Integer op2 = deque.pollLast();

Operator calc = Operator.of(s);
Integer result = calc.calculateOperation(op2, op1);

deque.addLast(result);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.programmers.calculator;

import com.programmers.util.Operator;

import java.util.List;
import java.util.ArrayList;
import java.util.Deque;
import java.util.ArrayDeque;
import java.util.regex.Pattern;

public class PostfixConversion {

private static final Pattern NUMBER = Pattern.compile("\\d+");

public List<String> changeInfixToPostfix(List<String> infix) {
List<String> postfix = new ArrayList<>();
Deque<String> deque = new ArrayDeque<>();

infix.stream()
.forEach(s -> { makePostfixWithDeque(s, postfix, deque); });

// 스택에 남아있는 연산자 모두 집어 넣음
while (!deque.isEmpty()) postfix.add(deque.pollLast());

return postfix;
}

private void makePostfixWithDeque(String s, List<String> postfix, Deque<String> deque) {
if (NUMBER.matcher(s).matches()) { // 숫자일 경우
postfix.add(s);
return;
}
// 숫자 아닐 경우
Operator operator = Operator.of(s);
int priority = operator.getPriority();
// 덱이 비었거나
while (!deque.isEmpty()) {
Operator topOperator = Operator.of(deque.peekLast());
int topPriority = topOperator.getPriority();

// top의 우선 순위가 높거나 같을 경우
if (topPriority >= priority) postfix.add(deque.pollLast());
// top의 우선 순위가 낮을 경우
else break;
}
deque.addLast(s); // 연산자 넣음
}

}
Loading