[제로베이스 데이터 스쿨] Group Study: Recursive Function

Sam Kim·2022년 6월 12일
0

Group Study

목록 보기
1/8
post-thumbnail

Prologue

이번 스터디 그룹 모임의 주제는 "재귀 함수(Recursive Function)".

Python 언어를 이용하여 [Baekjoon Online Judge] 사이트에 있는 재귀 함수 문제 5개를 풀고 함께 리뷰해 보는 시간을 가졌다.

특히 백준 17478번 문제를 스터디 조원들과 리뷰하면서 나의 사고가 좁은 틀 속에 갇혀있었다는 것을 깨달을 수 있었고 이번을 계기로 그 틀을 깨고 한 단계 밖으로 나올 수 있었다.

좁은 틀 속에 갇혀 있던 예전의 나로 '재귀'하지 않기를 바라는 마음으로 이 글을 남겨본다.

백준 17478번 문제: 재귀함수가 뭔가요?

문제 출처: Baekjoon Online Judge [문제 링크]

[문제 요약]

  • 재귀 횟수 n(1n50)n(1≤ n ≤ 50)이 주어진다.
  • 정해진 문자열을 nn 번 반복 출력하되 출력 당시의 반복 횟수 ×4\times 4 만큼 들여쓰기 한다.
  • 단, 첫 줄의 특정 문자열(1)^{(1)}과 마지막 재귀 시의 특정 문자열(2)^{(2)}은 한 번만 출력한다.

[출력 예시] n=2n=2일 때:

[시작]
[질문]
[딴소리]
____[질문]
____[딴소리]
________[질문]
________[대답]
________[마무리]
____[마무리]
[마무리]

이 문제에서 반복되지 않고 한 번씩만 출력되는 문자열이 두 가지가 있다.
그래서 내가 처음 문제를 직면하고 떠올린 방식은 이렇다.

  1. 특정 조건(1)^{(1)}을 만족하면 특정 문자열(1)^{(1)}을 출력한다.
  2. 재귀 횟수 nn에 따라 반복하며 정해진 문자열을 출력한다.
  3. 특정 조건(2)^{(2)}을 만족하면 특정 문자열(2)^{(2)}을 출력한다.

하지만 결국 다른 방법으로 풀어야만 했다.

스터디 전 나의 문제 풀이

우선, 재귀할 때마다 정해진 문자열을 재귀한 횟수만큼 들여쓰기 후 출력하기 위해 아래와 같은 방식의 코드를 잤다.

  • 재귀 횟수 nn을 입력값으로 받는다.
  • 입력값 n×4n \times 4 만큼 "_"를 출력한 후 정해진 문자열을 출력한다.
  • (n1)(n−1)을 입력값으로 받는 스스로를 호출한다.

이후 반복되는 않은 두 문자열을 각각 순서에 맞게 한 번만 출력되도록 조건을 만들어 주려고 했다.

"입력값 n=0n=0일 때,"라는 조건에서 한 번만 문자열을 출력하도록 하면 한 번만 출력되는 문자열 두 가지 중 하나는 해결할 수 있었다. 코드 진행 순서를 다르게 하면 다른 하나를 해결할 수 있었다.

그렇게 코드 진행 순서를 어떻게 하냐에 따라 두 가지 중 하나만 해결할 수 있었다.

함수 안에서 입력값으로 받은 nn만 보고 어떻게 두 가지 조건을 걸어야 할지 도무지 떠오르지가 않았다.

결국 함수 안에 중첩 함수로 2개의 재귀 함수를 만들었다.

각 함수가 한 번씩만 출력되는 문자열 하나씩을 담당하도록 한 것이다.

함수를 실행하면 그 안에 2개의 재귀 함수가 답을 이끌어 내는 것이다.

그렇게 억지스럽게 답은 만들어냈다.

스터디 시작 전 다른 분들은 어떻게 하나의 함수로 두 가지 모두 출력했을지가 가장 궁금했다.

스터디 조원들의 문제 풀이

놀랍기도 하고 민망하기도 했다.

다른 분들은 첫 줄에 한 번만 출력되는 문장을 미리 출력시킨 후에 재귀함수를 호출했고 해당 재귀함수는 반복되는 문자열을 출력하다 특정 조건을 만족하자 한 번만 출력되는 두 번째 문장을 출력했다.

이렇게나 간단했다.

재귀함수라는 틀 안에서만 모든 동작이 이루어져야 한다고 갇힌 사고를 했다니 민망했다.

그리고 또 재미난 점도 있었다.

재귀 횟수로 주어진 nn 값을 다르게 활용하는 방법도 있었다.

  • 재귀 횟수 nn을 전역변수로 두고 함수는 0을 입력 값으로 받아 실행.
  • ((입력값+1)+1)을 입력값으로 받는 스스로를 호출
  • (n=(n=입력값))일 때, 특정 작업을 수행

생각해 보니 문제에서 재귀 횟수 nn을 입력값으로 받는 함수를 만들라고 요구한 것은 아니었다.

결국 나의 고정관념으로 인해 사고의 폭이 좁았던 것이다.

나의 실책

이번에 푼 문제는 재귀함수 문제였다.

재귀함수의 사전적 정의
"재귀함수 (Recursive Function)"란 어떤 함수 안에서 자기 자신을 호출하여 함수 스스로가 반복되는(Recursive) 함수(Function)를 말한다.

그래서 "재귀함수"라는 단어에 너무 집중한 나머지 재귀함수의 사전적 정의에 매몰되어 어떻게든 함수 안에서 스스로를 반복 호출하여 제시된 문제를 풀고자 했다.

굳이 함수 안에서 해결해야 하지 않아도 되는 것까지 함수 안에서 해결하려고 하는 바람에 메모리와 런타임을 낭비했던 것이다. 또한, 함수 안만 보는 편협한 시야로 인해 (전역 변수 등과 같이) 함수 밖에 있는 것을 활용할 생각을 하지 못했다.

어떠한 문제를 해결하기 위해 재귀함수를 활용하는 것인데 이를 간과하고 재귀함수로 모든 것을 해결하려 했다.

결론

젓가락이 없으면 숟가락이라도 써야겠지만, 젓가락이 있으면 젓가락을 쓰면 된다.
굳이 숟가락을 들고 있다고 해서 숟가락으로 국수를 퍼먹을 이유는 없다.

내 머릿속에 있는 "재귀함수"라는 단어를 재정의해야겠다.

  • "재귀함수"란 같은 구조의 함수를 반복해서 사용할 필요가 있을 때 사용하는 것

지금이야 재귀함수를 공부하느라 어떻게든 재귀함수 안에서 최대한 해결하려고 하는 노력도 도움이 된다고 볼 수 있겠지만, 업무를 하면서도 이런 비효율적인 방식을 써서는 안 될 테니 말이다.

시야를 넓게 보고 다양하게 효율적으로 활용하자.

비단 재귀함수뿐 아니라 어떤 문제를 해결하는 데에 있어서 그 필요에 의해 활용하는 것들이 있다.

그게 모듈이든 뭐가 됐든, 그 필요에 의해서만 사용하면 된다는 걸 명심하자.

0개의 댓글