지난 포스팅에서는 itertools.zip_longest 이라는 파이썬 표준 라이브러리에 대해 공부해 보았습니다.
이번 포스팅에서는 itertools.permutation 표준 라이브러리에 대해 공부해 보도록 하겠습니다.
파이썬 표준 라이브러리
itertools.permutations
itertools.permutations 함수는 itertools.permutations(iterable, r) 의 형태로 작성되어 사용되는데 반복 가능한 iterable 객체 중에서 r 개를 선택한 순열을 반복 가능한 객체(이터레이터)로 리턴을 해주는 함수 입니다.
1, 2, 3 의 숫자가 적힌 3 장의 카드가 있다고 했을 때 두 개의 카드를 꺼내서 만들 수 있는 2 자리 숫자를 모두 구하려면 어떻게 하는게 좋을까요?
[1, 2, 3] 3장의 카드 중에서 순서에 상관 없이 2 장을 뽑는 경우의 수는 모두 3 가지가 됩니다(조합)
- 1, 2
- 2, 3
- 1, 3
그러나 위에 제시한 문제에서는 2 자리 숫자이므로 위의 3 가지에 순서를 더해 6 가지를 만들 수가 있습니다(순열)
- 1, 2
- 2, 1
- 2, 3
- 3, 2
- 1, 3
- 3, 1
이렇게 만들어지는 순열은 itertools.permutations 함수를 사용해서 간단하게 구할 수가 있습니다.
>>> import itertools
>>> list(itertools.permutations(['1', '2', '3'], 2))
[('1', '2'), ('1', '3'), ('2', '1'), ('2', '3'), ('3', '1'), ('3', '2')]
>>>
위 코드처럼 6 가지의 경우를 만들 수 있고 여기에 아래 코드처럼 추가해서 2 자리 숫자를 만들어 볼 수 있습니다.
>>> for a, b in itertools.permutations(['1', '2', '3'], 2):
... print(a + b)
...
12
13
21
23
31
32
>>>
itertools.combinations
앞서 진행했던 예제에서 3 장의 카드에서 순서에 상관없이 2 장을 고르는 조합은 아래와 같이 itertools.combinations() 함수를 사용을 하면 됩니다.
>>> import itertools
>>> list(itertools.combinations(['1', '2', '3'], 2))
[('1', '2'), ('1', '3'), ('2', '3')]
>>>
위 코드에서 보는 것 처럼 itertools.combinations 함수는 itertools.combinations(iterable, r) 의 형태로 작성이 되며 반복 가능한 객체 iterable 중에서 r 개를 선택한 조합을 반복 가능한 객체(이터레이터) 로 리턴을 해 주는 함수 입니다.
그럼 1 에서 45 까지의 숫자 중 서로 다른 숫자 6 개를 뽑는 로또 번호 처럼 모든 경우의 수(조합)을 구하고 그 개수를 출력하려면 어떻게 하면 될까요?
아래와 같이 itertools.combinations(range(1, 46), 6) 이라고 하게 되면 로또 번호를 뽑는 것처럼 1에서 45까지의 숫자 중 서로 다른 숫자 6개를 뽑는 경우의 수를 이터레이터로 리턴을 하게 됩니다.
직접 실행해 보게 되면 언제 끝날지 모르는 결과가 쭉 나올 것입니다.
>>> import itertools
>>> lotto = itertools.combinations(range(1, 46), 6)
>>> for number in lotto:
... print(number)
...
(1, 2, 3, 4, 5, 6)
(1, 2, 3, 4, 5, 7)
(1, 2, 3, 4, 5, 8)
(1, 2, 3, 4, 5, 9)
(1, 2, 3, 4, 5, 10)
...
...
...
...
...
만약 이렇게 순환하여 출력을 하지 않고 개수가 몇 개 인지만 확인하려면 아래와 같이 할 수도 있습니다.
>>> len(list(itertools.combinations(range(1, 46), 6)))
8145060
>>>
위 결과처럼 로또 번호의 경우의 수는 8,145,060 개 입니다.
itertools.combinations_with_replacement
만약의 그냥 로또번호 와는 틀리게 중복이 허용이 된다면 경우의 수가 몇 개가 될까요?
[1, 2, 3, 4, 5, 5] 나 [1, 2, 3, 3, 4, 4] 처럼 같은 숫자가 여러번 나와도 상관이 없다는 의미인데 이럴 경우에는 itertools.combinations_with_replacement() 를 사용하면 됩니다.
>>> len(list(itertools.combinations_with_replacement(range(1, 46), 6)))
15890700
>>>
중복이 허용이 될 경우 에는 경우의 수가 15,890,700 으로 많이 늘어나는 것을 확인 할 수 있습니다.
- 이 포스팅은 ‘위키독스’ 의 ‘점프 투 파이썬‘ 전자책을 구매하여 독학하기 위한 자료로 작성했습니다.
