Skip to content

Commit 3689e1d

Browse files
authored
Merge pull request #25 from Data-Structure-Study/yoonexample
3주차 예제코드 구현 완료
2 parents 5a1dfaf + d2a5d55 commit 3689e1d

File tree

7 files changed

+307
-0
lines changed

7 files changed

+307
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package stack;
2+
3+
public class InfixCalculator {
4+
5+
InfixToPostfix infixToPostfix = new InfixToPostfix();
6+
PostCalculator postCalculator = new PostCalculator();
7+
8+
public int calculate(String input) {
9+
return postCalculator.calculate(infixToPostfix.convertInputToPostfix(input));
10+
}
11+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package stack;
2+
3+
import java.util.Arrays;
4+
5+
public class InfixToPostfix {
6+
7+
public char[] convertInputToPostfix(String input) {
8+
return this.convertInfixToPostfix(this.convertInputToCharArray(input));
9+
}
10+
11+
public char[] convertInputToCharArray(String input) {
12+
return input.replace(" ", "").toCharArray();
13+
}
14+
15+
public char[] convertInfixToPostfix(char[] infixCharArray) {
16+
Stack<Character> stack = new ListStack<>();
17+
char[] postfixCharArray = new char[infixCharArray.length];
18+
19+
int idx = 0;
20+
for (char tok : infixCharArray) {
21+
if (Character.isDigit(tok)) { // tok이 숫자인지 확인
22+
postfixCharArray[idx++] = tok; // 숫자형이면 그대로 넣고, idx값을 증가시킨다.
23+
} else { // 연산자라면
24+
switch (tok) {
25+
case '(': // 여는 괄호라면
26+
stack.push(tok); // 스택에 넣는다.
27+
break;
28+
case ')': // 닫는 괄호라면
29+
while (true) { // 계속해서
30+
char popOp = stack.pop(); // 스택에서 연산자를 꺼낸다.
31+
if (popOp == '(') { // 연산자 (를 만날 때까지
32+
break;
33+
}
34+
postfixCharArray[idx++] = popOp; // 연산자를 배열에 넣는다.
35+
}
36+
break;
37+
case '+':
38+
case '-':
39+
case '*':
40+
case '/':
41+
// 사칙연산자가 들어오면, 스택이 비어있는지 확인하고, 스택이 비어있지 않다면, 맨 위의 연산자와 비교해서 스택에 있는 연산자가 연산을 먼저해야한다면
42+
while (!stack.isEmpty() && compareOperator(stack.peek(), tok) >= 0) {
43+
postfixCharArray[idx++] = stack.pop(); // 스택에서 연산자를 꺼내서 배열에 넣는다.
44+
}
45+
stack.push(tok); // 스택에 연산자를 넣는다.
46+
break;
47+
}
48+
}
49+
}
50+
while (!stack.isEmpty()) { // 스택에 남아있는 모든 연산자를 배열에 저장한다.
51+
postfixCharArray[idx++] = stack.pop();
52+
}
53+
54+
return Arrays.copyOf(postfixCharArray, idx); // 후위 연산으로 변경되면 길이가 줄어들고, 배열의 길이는 idx값과 동일하므로
55+
}
56+
57+
public int compareOperator(char op1, char op2) {
58+
OperatorPriority op1Priority = OperatorPriority.getOperatorPriority(op1);
59+
OperatorPriority op2Priority = OperatorPriority.getOperatorPriority(op2);
60+
return op1Priority.getPriority() - op2Priority.getPriority();
61+
}
62+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package stack;
2+
3+
public enum OperatorPriority {
4+
TOP(3),
5+
MID(2),
6+
BOT(1),
7+
NONE(-1);
8+
9+
private final int priority;
10+
11+
OperatorPriority(int priority) {
12+
this.priority = priority;
13+
}
14+
15+
public static OperatorPriority getOperatorPriority(char sign) {
16+
switch (sign) {
17+
case '*':
18+
case '/':
19+
return TOP;
20+
case '+':
21+
case '-':
22+
return MID;
23+
case '(':
24+
return BOT;
25+
default:
26+
return NONE;
27+
}
28+
}
29+
30+
public int getPriority() {
31+
return priority;
32+
}
33+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package stack;
2+
3+
public class PostCalculator {
4+
5+
public int calculate(char[] input) {
6+
Stack<Integer> stack = new ListStack<>();
7+
8+
for (char tok : input) {
9+
if (Character.isDigit(tok)) {
10+
stack.push(Character.getNumericValue(tok));
11+
} else {
12+
int op2 = stack.pop();
13+
int op1 = stack.pop();
14+
15+
switch (tok) {
16+
case '+':
17+
stack.push(op1 + op2);
18+
break;
19+
case '-':
20+
stack.push(op1 - op2);
21+
break;
22+
case '*':
23+
stack.push(op1 * op2);
24+
break;
25+
case '/':
26+
stack.push(op1 / op2);
27+
break;
28+
}
29+
}
30+
}
31+
32+
return stack.pop();
33+
}
34+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package stack;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.junit.jupiter.api.DisplayName;
7+
import org.junit.jupiter.api.Test;
8+
9+
class InfixCalculatorTest {
10+
11+
InfixCalculator infixCalculator;
12+
13+
@BeforeEach
14+
void setUp() {
15+
infixCalculator = new InfixCalculator();
16+
}
17+
18+
@Test
19+
@DisplayName("중위_표기법으로_작성된_수식_계산_테스트1")
20+
void 중위_표기법으로_작성된_수식_계산_테스트1() {
21+
String input = "1 + 2 * 3";
22+
23+
assertThat(infixCalculator.calculate(input)).isEqualTo(7);
24+
}
25+
26+
@Test
27+
@DisplayName("중위_표기법으로_작성된_수식_계산_테스트2")
28+
void 중위_표기법으로_작성된_수식_계산_테스트2() {
29+
String input = "(1 + 2) * 3";
30+
31+
assertThat(infixCalculator.calculate(input)).isEqualTo(9);
32+
}
33+
34+
@Test
35+
@DisplayName("중위_표기법으로_작성된_수식_계산_테스트3")
36+
void 중위_표기법으로_작성된_수식_계산_테스트3() {
37+
String input = "((1 - 2) + 3) * (5 - 2)";
38+
39+
assertThat(infixCalculator.calculate(input)).isEqualTo(6);
40+
}
41+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package stack;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static stack.OperatorPriority.getOperatorPriority;
5+
6+
import org.junit.jupiter.api.BeforeEach;
7+
import org.junit.jupiter.api.DisplayName;
8+
import org.junit.jupiter.api.Test;
9+
10+
class InfixToPostfixTest {
11+
12+
InfixToPostfix infixToPostfix;
13+
14+
@BeforeEach
15+
void setUp() {
16+
infixToPostfix = new InfixToPostfix();
17+
}
18+
19+
@Test
20+
@DisplayName("입력된 정보를 배열로 만드는지 테스트")
21+
void 입력된_정보를_배열로_만드는지_테스트() {
22+
String input = "1 + 2 * 3";
23+
char[] expected = {'1', '+', '2', '*', '3'};
24+
char[] actual = infixToPostfix.convertInputToCharArray(input);
25+
26+
assertThat(actual).isNotEmpty().hasSameSizeAs(expected).containsExactly(expected);
27+
}
28+
29+
@Test
30+
@DisplayName("중위 표기법 배열을 후위 표기법으로 바꾸는 함수 테스트1")
31+
void 중위_표기법_배열을_후위_표기법으로_바꾸는_함수_테스트1() {
32+
char[] input = {'1', '+', '2', '*', '3'}; // 123*+
33+
char[] expected = {'1', '2', '3', '*', '+'};
34+
char[] actual = infixToPostfix.convertInfixToPostfix(input);
35+
36+
assertThat(actual).isNotEmpty().hasSameSizeAs(expected).containsExactly(expected);
37+
}
38+
39+
@Test
40+
@DisplayName("중위 표기법 배열을 후위 표기법으로 바꾸는 함수 테스트2")
41+
void 중위_표기법_배열을_후위_표기법으로_바꾸는_함수_테스트2() {
42+
char[] input = {'(', '1', '*', '2', '+', '3', ')', '/', '4'}; // 12*3+4/
43+
char[] expected = {'1', '2', '*', '3', '+', '4', '/'};
44+
char[] actual = infixToPostfix.convertInfixToPostfix(input);
45+
46+
assertThat(actual).isNotEmpty().hasSameSizeAs(expected).containsExactly(expected);
47+
}
48+
49+
@Test
50+
@DisplayName("연산자의 연산 우선순위 정보를 반환하는 함수테스트")
51+
void 연산자의_연산_우선순위_정보를_반환하는_함수_테스트() {
52+
char multiplicationSign = '*';
53+
char divisionSign = '/';
54+
char plusSign = '+';
55+
char minusSign = '-';
56+
char openingParenthesis = '(';
57+
char noSign = ')';
58+
59+
assertThat(getOperatorPriority(multiplicationSign)).isEqualTo(OperatorPriority.TOP);
60+
assertThat(getOperatorPriority(divisionSign)).isEqualTo(OperatorPriority.TOP);
61+
assertThat(getOperatorPriority(plusSign)).isEqualTo(OperatorPriority.MID);
62+
assertThat(getOperatorPriority(minusSign)).isEqualTo(OperatorPriority.MID);
63+
assertThat(getOperatorPriority(openingParenthesis)).isEqualTo(OperatorPriority.BOT);
64+
assertThat(getOperatorPriority(noSign)).isEqualTo(OperatorPriority.NONE);
65+
}
66+
67+
@Test
68+
@DisplayName("연산자의 우선순위 정보를 바탕으로 그 결과를 반환하는 함수 테스트1")
69+
void 연산자의_우선순위_정보를_바탕으로_그_결과를_반환하는_함수_테스트1() {
70+
char op1 = '*';
71+
char op2 = '+';
72+
73+
assertThat(infixToPostfix.compareOperator(op1, op2)).isGreaterThan(0);
74+
}
75+
76+
@Test
77+
@DisplayName("연산자의 우선순위 정보를 바탕으로 그 결과를 반환하는 함수 테스트2")
78+
void 연산자의_우선순위_정보를_바탕으로_그_결과를_반환하는_함수_테스트2() {
79+
char op1 = '-';
80+
char op2 = '+';
81+
82+
assertThat(infixToPostfix.compareOperator(op1, op2)).isEqualTo(0);
83+
}
84+
85+
@Test
86+
@DisplayName("연산자의 우선순위 정보를 바탕으로 그 결과를 반환하는 함수 테스트3")
87+
void 연산자의_우선순위_정보를_바탕으로_그_결과를_반환하는_함수_테스트3() {
88+
char op1 = '(';
89+
char op2 = '+';
90+
91+
assertThat(infixToPostfix.compareOperator(op1, op2)).isLessThan(0);
92+
}
93+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package stack;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.junit.jupiter.api.DisplayName;
7+
import org.junit.jupiter.api.Test;
8+
9+
class PostCalculatorTest {
10+
11+
PostCalculator postCalculator;
12+
13+
@BeforeEach
14+
void setUp() {
15+
postCalculator = new PostCalculator();
16+
}
17+
18+
@Test
19+
@DisplayName("후위_표기법으로_작성된_수식_계산_테스트1")
20+
void 후위_표기법으로_작성된_수식_계산_테스트1() {
21+
char[] input = {'4', '2', '*', '8', '+'};
22+
23+
assertThat(postCalculator.calculate(input)).isEqualTo(16);
24+
}
25+
26+
@Test
27+
@DisplayName("후위_표기법으로_작성된_수식_계산_테스트2")
28+
void 후위_표기법으로_작성된_수식_계산_테스트2() {
29+
char[] input = {'1', '2', '3', '+', '*', '4', '/'};
30+
31+
assertThat(postCalculator.calculate(input)).isEqualTo(1);
32+
}
33+
}

0 commit comments

Comments
 (0)