📅 2023-12-28, 15일차
🧮계산기 만들기
(20 + 20) + 20 == 60
(10 + 20) * 3 == 90
- 괄호로 시작하는 테스트케이스는 괄호가 있는 인덱스 찾아서 잘 쪼개지만
10 + (10 + 5) == 25
- 괄호로 시작하지 않고 중간에 괄호가 나오는 테스트 케이스 같은 경우에는 쪼개지 못한다. 모든 테스트케이스가 괄호로 시작 할 수는 없다는 경우의 수를 생각하고, 나눌 수 있는 더하기 기호를 TRUE/FALSE 사용하여 찾아보기. 만약 FALSE라면 plan B로, 나눌 수 있는 곱하기 기호 찾기.
public static int run(String exp) {
boolean needToSplit = exp.contains("(") || exp.contains(")");
if (needToSplit) {
int splitPointIndex = findSplitPointIndex(exp);
String firstExp = exp.substring(0, splitPointIndex);
String secondExp = exp.substring(splitPointIndex + 1);
char operator = exp.charAt(splitPointIndex);
exp = Calc.run(firstExp) + " " + operator + " " + Calc.run(secondExp);
return Calc.run(exp);
private static int findSplitPointIndexBy(String exp, char findChar) {
int bracketCount = 0;
for (int i = 0; i < exp.length(); i++) {
char c = exp.charAt(i);
if (c == '(') {
bracketCount++;
} else if (c == ')') {
bracketCount--;
} else if (c == findChar) {
if (bracketCount == 0) return i;
}
}
return -1;
}
private static int findSplitPointIndex(String exp) {
int index = findSplitPointIndexBy(exp, '+');
if (index >= 0) return index;
return findSplitPointIndexBy(exp, '*');
}
재귀함수
- 함수 내부에서 ‘자기 자신을 호출’하는 함수. 이를 통해서 함수가 자신을 반복적으로 호출하면서 원하는 결과를 도출할 수 있다.
재귀함수를 사용한 factorial 구하기
- Factorial 함수에 4라는 인자값을 매개변수로 받아서
그 4를 재료로 사용하여 함수 내부 실행 후 나온 결과 값을, 함수를 처음 호출하고 끝난 자리(이 예시에서는 출력문)에 리턴.
- factorial이라는 함수내에서 factorial이라는 함수로 호출 중
public static void main(String[] args) {
System.out.println("4! : " + Factorial(4));
}
private static int Factorial(int n) {
if (n == 0 || n == 1) {
return 1;
}
return n * Factorial(n - 1);
}
3항연산자를 사용한 재귀함수 factorial 구하기
- 리턴. n이 1보다 크다면. 뭘해라? n 곱하기 나 자신인 Factorial이라는함수에다 (n - 1) 값을 넘겨줘. 그렇지 않다면 1을 반환해.
private static int Factorial(int n) {
return (n > 1) ? n * Factorial(n -1) : 1
}
재귀호출 되는 구조를 쉽게 파악하기 위해 recursionDebug 활용
- 출력문을 사용하여 실행문이 돌 때마다 몇번 도는지, 돌때마다 테스트케이스가 어떻게 연산을 하는지 변수와 출력문을 활요하여 눈으로 확인 할 수 있다.
- boolean debug를 false에서 true로 바꿔주면 debug모드를 수동으로 키는 것 처럼 테스트케이스 연산을 추적하여 보여준다.
public static boolean debug = false;
public static int runCallCount = 0;
public static int run(String exp) {
runCallCount++;
if(recursionDbug) {
System.out.printf("exp(%d) : %s\n", runCallCount, exp)
}
}
대입과 비교를 동시에 하기
while ((pos = findNegativeCaseBracket(exp)) != null) {
exp = changeNegativeBracket(exp, pos[0], pos[1]);
}
IntelliJ 의 plugin - Sequence Diagram
- 인텔리제이에서 Sequence Diagram이라는 플러그인을 다운받을 수 있다
- Sequence Diagram은 어떤 순서로 어떤 객체와 어떻게 상호작용했는지 보여주는 diagram이다. 이걸 사용하면 시스템이 어떤 시나리오로 움직이고 있는지 파악하기 쉽다.