python reduce 함수는 functools에 있어요. 제가 최근에 출제한 코딩테스트 문제에서 꽤 유용하게 쓰일 수 있는데요. 간략하게 알아보도록 하겠습니다.
reduce 함수
먼저, 설명을 간단하게 보도록 합시다.
인자를 2개 받아요.
- function
- iterable
잘 읽어보면, 1번째 인자로 넘겨진 함수를 적용한다고 되어 있어요. 어떻게? cumulatively. 누적시켜서요. from left to right. 좌에서 우로 적용한다는 의미에요. 요약하면, iterable에 있는 원소들을 좌에서 우의 순서로 특정한 연산을 누적 적용한다는 의미입니다. 이 특정한 연산은 2개의 인자를 받아서 하나의 결과를 리턴해야 합니다.
좌에서 우로 특정한 연산을 누적 적용한다는 점을 기억하고 아래 그림을 봅시다.
operator의 mul 함수는 두 수를 받아, 곱한 결과를 돌려줍니다. 두 수를 받았다는 의미는 두 개의 인자를 받았다는 의미입니다. 그리고, 결과 하나를 돌려줍니다. 그러면 operator.mul은 위에서 말한 특정한 연산의 조건을 만족합니다.
이제 아래 예제 코드를 보겠습니다.
reduce의 1번째 인자로 operator.mul을, 2번째 인자로 range(1, 11)을 넣었어요. 어떻게 동작할까요?
가장 먼저 나오는 1과 2가 operator.mul의 인자에 들어갑니다. 1과 2를 곱한 결과는 2입니다. 이 결과가 어느 것과 또 다시 누적 연산이 될까요?
그 다음에 오는 3과 연산이 됩니다. 2와 3을 operator.mul에 넘겨주면 그 결과는 6이 나와요. 이것과 4와 mul 연산을 합니다. 이런 식으로 10까지 돌아가겠지요? 최종 결과는 10!이 나올 거라고 예상할 수 있어요.
결과를 출력해 보니, 3628800이 나옵니다. 이 값과 10!은 동일합니다.
쓸 만한 python reduce 함수 예제
이제, 쓸만한 예제 중 하나를 가지고 오겠습니다. 먼저 combination 입니다. n개 중 r개를 택하는 가짓수와 같지요.
n개 중 r개를 택하는 가짓수는 어떻게 구할까요? n!에 (n-r)!을 나누고, 다시 r!을 나누면 됩니다. 이는, n-r+1부터 n까지 곱한 결과에, r!을 나눈 결과와 같습니다. 따라서 먼저 11번째 줄에, range(n, n-r, -1)을 넣어줍니다. 이는 n부터 n-r+1까지 1씩 감소하는 range 객체를 의미합니다. operator.mul을 해당 객체를 돌면서 누적 적용했기 때문에 n-r+1부터 n까지 곱한 결과가 t에 저장됩니다.
다음에, range(1, r+1)은 1부터 r까지 1씩 증가하는 range 객체를 의미합니다. 이 객체에 operator.mul을 누적 적용했기 때문에 d에는 r!이 저장되게 됩니다. 따라서, t에 d를 나누면 combination의 결과가 나오게 됩니다.
이제, 구현된 combi 함수를 호출하는 코드를 작성해 보겠습니다. c1의 결과는 1, c2의 결과는 120이 나와야 합니다. 그렇게 나오는지 볼까요?
1과 120이 나왔습니다. 예상했던 결과입니다. 정리하면, functools의 reduce는 아래 상황에서 쓴다는 것만 알고 가시면 좋습니다.
- list 등에 있는 객체들의 원소들에 연산을 누적 적용해서
- 하나의 값으로 리턴한다.
우리에게 익숙한 누적합 배열은 이 함수를 적용할 수 없습니다. 누적합 배열은 하나의 값으로 리턴되는 것이 아니기 때문입니다. 이 점을 주의하시면 됩니다.