조합 combination
일반적으로 알고리즘 문제를 풀때 보면 조합을 쓰는 경우가 종종 생긴다. 이에 조합을 함수형 프로그래밍으로 구현하는 법과 라이브러리를 사용해서 구하는 법 각각 사용해서 한번 진행해 보겠다.
python 라이브러리 itertools combinations
python에서 제공하는 라이브러리 중 itertools라는 것이 있다. 이 tool를 사용하면 쉽게 조합을 구할 수 있다. 우선 조합이란 순서와 관계 없이 차례로 나열 되는 데이터를 구하는 것임을 명심해야 한다. 이제 예제 코드를 보자
from itertools import permutations, combinations
arr = [1,2,3,4]
nPr = combinations(arr,2)
print(list(nPr))
nPr = combinations(arr,3)
print(list(nPr))
nPr = combinations(arr,4)
print(list(nPr))
'''
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
[(1, 2, 3, 4)]
'''
예제 결과를 보면 combination( list, n ) 으로 사용되는 것을 확인 할 수 있다. 넣는 값과 몇개의 수로 표현되는지 가지 수를 알려주고 있다.
함수형 프로그래밍으로 재귀를 사용해 combination 구하기
재귀로 combination을 만들어 보자.
def combination (numbers) :
if len(numbers) == 0 :
return [[ ]]
first = numbers[0]
rest = numbers[1:]
com_without_first = combination(rest)
com_with_first = []
for cwf in com_without_first:
_com_with_first = [ *cwf, first]
com_with_first.append( _com_with_first )
print( "combination :", *com_with_first)
return [ *com_without_first, *com_with_first ]
print(combination([1,2,3,4]))
'''
combination : [4]
combination : [3]
combination : [3] [4, 3]
combination : [2]
combination : [2] [4, 2]
combination : [2] [4, 2] [3, 2]
combination : [2] [4, 2] [3, 2] [4, 3, 2]
combination : [1]
combination : [1] [4, 1]
combination : [1] [4, 1] [3, 1]
combination : [1] [4, 1] [3, 1] [4, 3, 1]
combination : [1] [4, 1] [3, 1] [4, 3, 1] [2, 1]
combination : [1] [4, 1] [3, 1] [4, 3, 1] [2, 1] [4, 2, 1]
combination : [1] [4, 1] [3, 1] [4, 3, 1] [2, 1] [4, 2, 1] [3, 2, 1]
combination : [1] [4, 1] [3, 1] [4, 3, 1] [2, 1] [4, 2, 1] [3, 2, 1] [4, 3, 2, 1]
[[], [4], [3], [4, 3], [2], [4, 2], [3, 2], [4, 3, 2], [1], [4, 1], [3, 1], [4, 3, 1], [2, 1], [4, 2, 1], [3, 2, 1], [4, 3, 2, 1]]
'''
코드를 보면 생각보다 복잡해 보이는데 구획을 나누어서 살펴보자
if len(numbers) == 0 :
return [[ ]]
first = numbers[0]
rest = numbers[1:]
com_without_first = combination(rest)
우선 먼저 눈여겨 봐야할 부분은 값을 분리하는 부분이다. first라는 값을 뺀 나머지를 다시 combination함수에 넣는 것을 볼 수 있다. 그리고 이 combination 함수의 처음 if 조건을 보면 값이 없다면 빈 값을 return 해주는 것을 볼 수 있다. 그 다음 코드를 살펴보면
com_with_first = []
for cwf in com_without_first:
_com_with_first = [ *cwf, first]
com_with_first.append( _com_with_first )
print( "combination :", *com_with_first)
위에서 combination(rest)에 나온 값을 for문을 통해 돌리고 이 값들을 first와 합치는 것을 볼 수 있다. 이 것이 의미하는 바는 만약 combination(rest) 가 [ [], [1] ] 이라면 여기에 각각 [2]를 추가하여 [ [2], [1,2] ] 를 만든 다는 것이다.
return [ *com_without_first, *com_with_first ]
그리고 마지막을 보면 그렇게 만든 [ [2], [1,2] ] 와 [ [], [1] ] 를 합쳐 최종적으로 [ [], [1], [2], [1,2]] 가 만들어 지게 된다.
combination(n) = combination(n-1) +
combination(n-1) * n ( combination(n-1)의 모든 자료에 n을 더한다는 의미이다)
이런 식으로 조합을 만들어 낸다는 뜻이다.
물론 필자는 위와 같은 방식보다는 라이브러리를 사용하는 것을 추천한다. 그러나 만약 라이브러리를 사용하지 못한다면 위와 같은 방법도 좋은 방법이 될 거 같다. 그래서 최종적으로
def combination (numbers) :
if len(numbers) == 0 :
return [[ ]]
first = numbers[0]
rest = numbers[1:]
com_without_first = combination(rest)
print( "com_without_first" , com_without_first )
com_with_first = []
com_with_first = map( lambda x : [*x, first], com_without_first)
return [ *com_without_first, *com_with_first ]
map을 활용하여 좀 더 축약하면 다음과 같은 형식으로 만들어 사용 할 수 있다.
'함수형 프로그래밍 > python' 카테고리의 다른 글
수열 문제 N과 M (0) | 2021.08.01 |
---|---|
permutation 순열 만들기 (0) | 2021.07.28 |
파이썬 객체 속성 확인 및 사용 가능 함수 확인 (0) | 2021.07.26 |
일반적인 숨바꼭질 문제 (0) | 2021.07.22 |
curry, reduce를 사용하여 함수 열거형 go 만들기 (0) | 2021.07.20 |
댓글