렝무식

[백준 17478번] 재귀함수가 뭔가요? (JAVA) 본문

Algorithm/Baekjoon

[백준 17478번] 재귀함수가 뭔가요? (JAVA)

렝9 2023. 1. 13. 03:02

BOJ - [17478] 재귀함수가 뭔가요?


image

🖍 챗봇의 응답을 재귀적으로 출력하는 문제
(link) 17478 재귀함수가 뭔가요?


[풀이 과정]

정말.. 재밌는 문제같다.

근데 확실히 재귀라는 개념을 단번에 이해할 수 있는 문제이기도하다.

 

일단 함수안에 문장을 그대로 적으면 복잡해보일 것 같아서 문장들을 따로 String 변수에 저장했다.
이때 주의할 점은 출력에서 재귀 단계에 따라 언더바를 4개씩 추가하여 출력해주어야 하기 때문에 언더바가 시작하는 문장마다 따로 저장해야 한다.
(이를테면 "잘 들어보게." 부터 "한 선비가 찾아와서 물었어." 까지는 한 문장 같지만 엔터처리되는 부분마다 언더바가 들어가므로 세 변수에 따로 저장한다)
물론 이렇게 하지 않아도 분명 다른 방법이 있긴 할 거다.

 

재귀함수에서의 출력은 간단하다.
일단 "라고 답변하였지."의 경우 끝자락에 나열되기 때문에 반환값으로 넣어주어야하는 문장이다.

종료 조건에는 한 번만 출력되는 문장을 넣어주면 되겠다. n = 0일 때, 즉 마지막 재귀단계에서 "재귀함수가 뭔가요?"와 함께, 그 답인 "재귀함수는 자기 자신을 호출하는 함수라네" 를 출력하게 하면 된다.

else문의 경우 재귀적으로 반복되는 문장인 "재귀함수가 뭔가요?"와 함께 "잘 들어보게 ~ ... ~ 한 선비가 찾아와서 물었어." 를 출력하도록 하면 된다.

"라고 답변하였지."를 반환값으로 넣어주는 동시에 재귀함수(인자 n-1)를 호출하도록 한다.

 

주의할 점이라면 위에서 말했듯이 엔터로 나누어지는 문장마다 앞에 언더바를 출력하게 해야 한다는 점이다. 반환값도 마찬가지로 출력하도록 해줘야한다.

그런데 언더바가 재귀함수를 호출 할 수록 4개씩 늘어나고, 반환할 수록 4개씩 작아진다. 이는 어떻게 처리할까?

우선 문자열을 유동적으로 사용하고 있다는 점에서 언더바는 StringBuilder를 사용하면 편리할 것 같다.

더보기

StringBuilder의 문자 출력 메소드는 toString()이다.

말했다시피 재귀를 호출할 수록 4개씩 늘어난다는 특징을 가지고 있다. 이는 else문에서 모두 출력하고 난 뒤 StringBuilder에 언더바 네 개를 추가해주면 된다. 종료 조건의 문장에서는 늘어나지 않으므로 추가하지 않아도 된다.

더보기

StringBuilder의 문자 추가 메소드는 .append()이다.

다음으로 반환될 수록 4개씩 줄어드는 처리는 당연히 반환값에서 해주면 된다. 이때도 역시 if문의 반환값은 건들지 않아야 한다.

"라고 답변하였지."라는 반환값 앞에서 4개씩 줄어드므로 반환값 앞에서 StringBuilder의 언더바를 네 개 삭제한다.

더보기

StringBuilder의 문자 삭제 메소드는 .delete(start index, end index+1)이다. 따라서 언더바를 네 개 삭제하려면 .delete(0, 4)를 사용하면 된다.

 

말로는 설명이 잘 되고 있는지 모르겠음....

이 문제야 말로 코드를 봐야 이해가 더 쉽게 되지 않을까싶다.

 

+++

코드 리뷰 후 선생님의 코드를 봤다.

나는 언더바 반복 출력에서 애를 먹었었는데 ... String 내부 메소드 중에 단어를 반복 출력해주는 메소드가 있었다.

알고보니까 자바 11버전에서 새로 나온 메소드라고 한다.

 

사용법은 간단함

str.repeat(); 괄호 안에 파라미터로 정수를 넣으면 된다.

0을 넣을 시 아무것도 출력하지 않고, 1을 넣을 시 문자열을 한 번 출력한다.

그러니까 파라미터의 숫자 만큼 문자열을 출력하는 것이다.

for문을 이용하지 않고도 반복하여 출력할 수 있는 편리한 메소드.. 🥺


[Pseudocode]

String recursive(int n)
1. if(n=0)
    2. toString() + "재귀함수가 뭔가요?"
    3. toString() + "재귀함수는 자기 자신을 호출하는 함수라네"
    4. return toString() + "라고 답변하였지."
5. else
    6. toString() + "재귀함수가 뭔가요?"
    7. toString() + "잘 들어보게. ..."
    8. toString() + "마을 사람들은 ..."
    9. toString() + "그의 답은 대부분 옳았다고 하네 ..."
    10. .append("____")
    11. return recursive(n-1) + .delete(0, 4).toString() + "라고 답변하였지."

[Code]

import java.util.*;
/**
 * 백준 17478번
 * 재귀함수가 뭔가요?
 * 분류 : 재귀
 */
public class Problem11 {
    static StringBuilder sb = new StringBuilder();
    static String str1 = "\"재귀함수가 뭔가요?\"";
    static String str2 = "\"잘 들어보게. 옛날옛날 한 산 꼭대기에 이세상 모든 지식을 통달한 선인이 있었어.";
    static String str3 = "마을 사람들은 모두 그 선인에게 수많은 질문을 했고, 모두 지혜롭게 대답해 주었지.";
    static String str4 = "그의 답은 대부분 옳았다고 하네. 그런데 어느 날, 그 선인에게 한 선비가 찾아와서 물었어.\"";
    static String str5 = "\"재귀함수는 자기 자신을 호출하는 함수라네\"";
    static String str6 = "라고 답변하였지.\n";
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int N = input.nextInt();
        System.out.println("어느 한 컴퓨터공학과 학생이 유명한 교수님을 찾아가 물었다.");
        System.out.println(recursive(N));

        input.close();
    }

    public static String recursive(int n) {
        if(n == 0) {
            System.out.print(sb.toString());
            System.out.println(str1);
            System.out.print(sb.toString());
            System.out.println(str5);
            return (sb.toString()) + str6;
        }
        else {
            System.out.print(sb.toString());
            System.out.println(str1);
            System.out.print(sb.toString());
            System.out.println(str2);
            System.out.print(sb.toString());
            System.out.println(str3);
            System.out.print(sb.toString());
            System.out.println(str4);
            sb.append("____");
            return recursive(n-1) + (sb.delete(0,4).toString()) + str6; // 메소드를 끝내면서 언더바가 4개씩 줄어들어야함
        }
    }
}

[Result]

image


 

(2021.07.22 풀이분)

재귀함수는 천천히 곱씹지 않으면 헷갈린다.

지금도 그렇다.

Comments