Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3주차 예제코드 구현 완료 #25

Merged
merged 11 commits into from
Jul 30, 2020
Merged
Changes from all 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
11 changes: 11 additions & 0 deletions yoonexample/src/main/java/stack/InfixCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package stack;

public class InfixCalculator {

InfixToPostfix infixToPostfix = new InfixToPostfix();
PostCalculator postCalculator = new PostCalculator();

public int calculate(String input) {
return postCalculator.calculate(infixToPostfix.convertInputToPostfix(input));
}
}
62 changes: 62 additions & 0 deletions yoonexample/src/main/java/stack/InfixToPostfix.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package stack;

import java.util.Arrays;

public class InfixToPostfix {

public char[] convertInputToPostfix(String input) {
return this.convertInfixToPostfix(this.convertInputToCharArray(input));
}

public char[] convertInputToCharArray(String input) {
return input.replace(" ", "").toCharArray();
}

public char[] convertInfixToPostfix(char[] infixCharArray) {
Stack<Character> stack = new ListStack<>();
char[] postfixCharArray = new char[infixCharArray.length];

int idx = 0;
for (char tok : infixCharArray) {
if (Character.isDigit(tok)) { // tok이 숫자인지 확인
postfixCharArray[idx++] = tok; // 숫자형이면 그대로 넣고, idx값을 증가시킨다.
} else { // 연산자라면
switch (tok) {
case '(': // 여는 괄호라면
stack.push(tok); // 스택에 넣는다.
break;
case ')': // 닫는 괄호라면
while (true) { // 계속해서
char popOp = stack.pop(); // 스택에서 연산자를 꺼낸다.
if (popOp == '(') { // 연산자 (를 만날 때까지
break;
}
postfixCharArray[idx++] = popOp; // 연산자를 배열에 넣는다.
}
break;
case '+':
case '-':
case '*':
case '/':
// 사칙연산자가 들어오면, 스택이 비어있는지 확인하고, 스택이 비어있지 않다면, 맨 위의 연산자와 비교해서 스택에 있는 연산자가 연산을 먼저해야한다면
while (!stack.isEmpty() && compareOperator(stack.peek(), tok) >= 0) {
postfixCharArray[idx++] = stack.pop(); // 스택에서 연산자를 꺼내서 배열에 넣는다.
}
stack.push(tok); // 스택에 연산자를 넣는다.
break;
}
}
}
while (!stack.isEmpty()) { // 스택에 남아있는 모든 연산자를 배열에 저장한다.
postfixCharArray[idx++] = stack.pop();
}

return Arrays.copyOf(postfixCharArray, idx); // 후위 연산으로 변경되면 길이가 줄어들고, 배열의 길이는 idx값과 동일하므로
}

public int compareOperator(char op1, char op2) {
OperatorPriority op1Priority = OperatorPriority.getOperatorPriority(op1);
OperatorPriority op2Priority = OperatorPriority.getOperatorPriority(op2);
return op1Priority.getPriority() - op2Priority.getPriority();
}
}
33 changes: 33 additions & 0 deletions yoonexample/src/main/java/stack/OperatorPriority.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package stack;

public enum OperatorPriority {
TOP(3),
MID(2),
BOT(1),
NONE(-1);

private final int priority;

OperatorPriority(int priority) {
this.priority = priority;
}

public static OperatorPriority getOperatorPriority(char sign) {
switch (sign) {
case '*':
case '/':
return TOP;
case '+':
case '-':
return MID;
case '(':
return BOT;
default:
return NONE;
}
}

public int getPriority() {
return priority;
}
}
34 changes: 34 additions & 0 deletions yoonexample/src/main/java/stack/PostCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package stack;

public class PostCalculator {

public int calculate(char[] input) {
Stack<Integer> stack = new ListStack<>();

for (char tok : input) {
if (Character.isDigit(tok)) {
stack.push(Character.getNumericValue(tok));
} else {
int op2 = stack.pop();
int op1 = stack.pop();

switch (tok) {
case '+':
stack.push(op1 + op2);
break;
case '-':
stack.push(op1 - op2);
break;
case '*':
stack.push(op1 * op2);
break;
case '/':
stack.push(op1 / op2);
break;
}
}
}

return stack.pop();
}
}
41 changes: 41 additions & 0 deletions yoonexample/src/test/java/stack/InfixCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package stack;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class InfixCalculatorTest {

InfixCalculator infixCalculator;

@BeforeEach
void setUp() {
infixCalculator = new InfixCalculator();
}

@Test
@DisplayName("중위_표기법으로_작성된_수식_계산_테스트1")
void 중위_표기법으로_작성된_수식_계산_테스트1() {
String input = "1 + 2 * 3";

assertThat(infixCalculator.calculate(input)).isEqualTo(7);
}

@Test
@DisplayName("중위_표기법으로_작성된_수식_계산_테스트2")
void 중위_표기법으로_작성된_수식_계산_테스트2() {
String input = "(1 + 2) * 3";

assertThat(infixCalculator.calculate(input)).isEqualTo(9);
}

@Test
@DisplayName("중위_표기법으로_작성된_수식_계산_테스트3")
void 중위_표기법으로_작성된_수식_계산_테스트3() {
String input = "((1 - 2) + 3) * (5 - 2)";

assertThat(infixCalculator.calculate(input)).isEqualTo(6);
}
}
93 changes: 93 additions & 0 deletions yoonexample/src/test/java/stack/InfixToPostfixTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package stack;

import static org.assertj.core.api.Assertions.assertThat;
import static stack.OperatorPriority.getOperatorPriority;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class InfixToPostfixTest {

InfixToPostfix infixToPostfix;

@BeforeEach
void setUp() {
infixToPostfix = new InfixToPostfix();
}

@Test
@DisplayName("입력된 정보를 배열로 만드는지 테스트")
void 입력된_정보를_배열로_만드는지_테스트() {
String input = "1 + 2 * 3";
char[] expected = {'1', '+', '2', '*', '3'};
char[] actual = infixToPostfix.convertInputToCharArray(input);

assertThat(actual).isNotEmpty().hasSameSizeAs(expected).containsExactly(expected);
}

@Test
@DisplayName("중위 표기법 배열을 후위 표기법으로 바꾸는 함수 테스트1")
void 중위_표기법_배열을_후위_표기법으로_바꾸는_함수_테스트1() {
char[] input = {'1', '+', '2', '*', '3'}; // 123*+
char[] expected = {'1', '2', '3', '*', '+'};
char[] actual = infixToPostfix.convertInfixToPostfix(input);

assertThat(actual).isNotEmpty().hasSameSizeAs(expected).containsExactly(expected);
}

@Test
@DisplayName("중위 표기법 배열을 후위 표기법으로 바꾸는 함수 테스트2")
void 중위_표기법_배열을_후위_표기법으로_바꾸는_함수_테스트2() {
char[] input = {'(', '1', '*', '2', '+', '3', ')', '/', '4'}; // 12*3+4/
char[] expected = {'1', '2', '*', '3', '+', '4', '/'};
char[] actual = infixToPostfix.convertInfixToPostfix(input);

assertThat(actual).isNotEmpty().hasSameSizeAs(expected).containsExactly(expected);
}

@Test
@DisplayName("연산자의 연산 우선순위 정보를 반환하는 함수테스트")
void 연산자의_연산_우선순위_정보를_반환하는_함수_테스트() {
char multiplicationSign = '*';
char divisionSign = '/';
char plusSign = '+';
char minusSign = '-';
char openingParenthesis = '(';
char noSign = ')';

assertThat(getOperatorPriority(multiplicationSign)).isEqualTo(OperatorPriority.TOP);
assertThat(getOperatorPriority(divisionSign)).isEqualTo(OperatorPriority.TOP);
assertThat(getOperatorPriority(plusSign)).isEqualTo(OperatorPriority.MID);
assertThat(getOperatorPriority(minusSign)).isEqualTo(OperatorPriority.MID);
assertThat(getOperatorPriority(openingParenthesis)).isEqualTo(OperatorPriority.BOT);
assertThat(getOperatorPriority(noSign)).isEqualTo(OperatorPriority.NONE);
}

@Test
@DisplayName("연산자의 우선순위 정보를 바탕으로 그 결과를 반환하는 함수 테스트1")
void 연산자의_우선순위_정보를_바탕으로_그_결과를_반환하는_함수_테스트1() {
char op1 = '*';
char op2 = '+';

assertThat(infixToPostfix.compareOperator(op1, op2)).isGreaterThan(0);
}

@Test
@DisplayName("연산자의 우선순위 정보를 바탕으로 그 결과를 반환하는 함수 테스트2")
void 연산자의_우선순위_정보를_바탕으로_그_결과를_반환하는_함수_테스트2() {
char op1 = '-';
char op2 = '+';

assertThat(infixToPostfix.compareOperator(op1, op2)).isEqualTo(0);
}

@Test
@DisplayName("연산자의 우선순위 정보를 바탕으로 그 결과를 반환하는 함수 테스트3")
void 연산자의_우선순위_정보를_바탕으로_그_결과를_반환하는_함수_테스트3() {
char op1 = '(';
char op2 = '+';

assertThat(infixToPostfix.compareOperator(op1, op2)).isLessThan(0);
}
}
33 changes: 33 additions & 0 deletions yoonexample/src/test/java/stack/PostCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package stack;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class PostCalculatorTest {

PostCalculator postCalculator;

@BeforeEach
void setUp() {
postCalculator = new PostCalculator();
}

@Test
@DisplayName("후위_표기법으로_작성된_수식_계산_테스트1")
void 후위_표기법으로_작성된_수식_계산_테스트1() {
char[] input = {'4', '2', '*', '8', '+'};

assertThat(postCalculator.calculate(input)).isEqualTo(16);
}

@Test
@DisplayName("후위_표기법으로_작성된_수식_계산_테스트2")
void 후위_표기법으로_작성된_수식_계산_테스트2() {
char[] input = {'1', '2', '3', '+', '*', '4', '/'};

assertThat(postCalculator.calculate(input)).isEqualTo(1);
}
}