Python에서 계승, 순열 및 조합 계산 및 생성

사업

Python의 수학 함수에 대한 표준 모듈 수학을 사용하여 계승을 계산할 수 있습니다. SciPy에는 순열/조합의 총 수를 계산하는 기능도 있습니다.

itertools 모듈을 사용하여 목록(배열) 등에서 순열과 조합을 생성하고 열거할 수도 있습니다.

다음은 샘플 코드와 함께 여기에 설명되어 있습니다.

  • 계승:math.factorial()
  • 순열의 총 수 계산
    • math.factorial()
    • scipy.special.perm()
  • 목록에서 순열 생성 및 열거:itertools.permutations()
  • 총 조합 수 계산
    • math.factorial()
    • scipy.special.comb()
    • math.factorial()을 사용하지 않는 방법
  • 목록에서 조합 생성 및 열거:itertools.combinations()
  • 중복 조합의 총 수 계산
  • 목록에서 중복 조합 생성 및 열거:itertools.combinations_with_replacement()

순열을 활용하는 예로서 다음도 설명됩니다.

  • 문자열에서 아나그램 만들기

단일 목록 대신 여러 목록의 요소 조합을 생성하려면 itertools 모듈에서 itertools.product()를 사용하십시오.

계승:math.factorial()

수학 모듈은 계승을 반환하는 factorial() 함수를 제공합니다.

import math

print(math.factorial(5))
# 120

print(math.factorial(0))
# 1

정수가 아닌 음수 값은 ValueError가 발생합니다.

# print(math.factorial(1.5))
# ValueError: factorial() only accepts integral values

# print(math.factorial(-1))
# ValueError: factorial() not defined for negative values

순열의 총 수 계산

math.factorial()

순열은 r이 n개의 서로 다른 것 중에서 선택되어 행에 배치되는 경우의 수입니다.

순열의 총 수 p는 계승을 사용하여 다음 방정식으로 구합니다.

p = n! / (n - r)!

계승을 반환하는 함수 math.factorial()을 사용하여 다음과 같이 계산할 수 있습니다. 정수 나누기를 수행하는 ⌘ 연산자는 정수 형식을 반환하는 데 사용됩니다.

def permutations_count(n, r):
    return math.factorial(n) // math.factorial(n - r)

print(permutations_count(4, 2))
# 12

print(permutations_count(4, 4))
# 24

scipy.special.perm()

SciPy는 순열의 총 수를 반환하는 scipy.special.perm() 함수를 제공합니다. 별도의 SciPy 설치가 필요합니다. 버전 0.14.0부터 사용 가능합니다.

from scipy.special import perm

print(perm(4, 2))
# 12.0

print(perm(4, 2, exact=True))
# 12

print(perm(4, 4, exact=True))
# 24

exact=False
세 번째 인수는 기본적으로 위와 같이 설정되며 부동 소수점 숫자를 반환합니다. 정수로 받고 싶다면 다음과 같이 설정해야 합니다.
exact=True

“import scipy”만 scipy.special 모듈을 로드하지 않습니다.

위의 예와 같이 “from scipy.special import perm”으로 perm()을 실행하거나 “import scipy.special”로 scipy.special.perm()을 실행합니다.

목록에서 순열 생성 및 열거:itertools.permutations()

총 수뿐만 아니라 순열도 생성하고 목록(배열) 등에서 열거할 수 있습니다.

itertools 모듈의 permutations() 함수를 사용하십시오.

iterable(목록 또는 집합 유형)을 첫 번째 인수로 전달하고 두 번째 인수로 선택할 조각 수를 전달하면 해당 순열에 대한 반복자가 반환됩니다.

import itertools

l = ['a', 'b', 'c', 'd']

p = itertools.permutations(l, 2)

print(type(p))
# <class 'itertools.permutations'>

모두 열거하려면 for 루프를 사용할 수 있습니다.

for v in itertools.permutations(l, 2):
    print(v)
# ('a', 'b')
# ('a', 'c')
# ('a', 'd')
# ('b', 'a')
# ('b', 'c')
# ('b', 'd')
# ('c', 'a')
# ('c', 'b')
# ('c', 'd')
# ('d', 'a')
# ('d', 'b')
# ('d', 'c')

유한 반복자이기 때문에 list()를 사용하여 목록 유형으로 변환할 수도 있습니다.

len()으로 리스트의 원소 개수를 구하면 factorial에서 계산한 총 순열 개수와 일치함을 확인할 수 있다.

p_list = list(itertools.permutations(l, 2))

print(p_list)
# [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'a'), ('b', 'c'), ('b', 'd'), ('c', 'a'), ('c', 'b'), ('c', 'd'), ('d', 'a'), ('d', 'b'), ('d', 'c')]

print(len(p_list))
# 12

두 번째 인수가 생략되면 모든 요소를 ​​선택하기 위한 순열이 반환됩니다.

for v in itertools.permutations(l):
    print(v)
# ('a', 'b', 'c', 'd')
# ('a', 'b', 'd', 'c')
# ('a', 'c', 'b', 'd')
# ('a', 'c', 'd', 'b')
# ('a', 'd', 'b', 'c')
# ('a', 'd', 'c', 'b')
# ('b', 'a', 'c', 'd')
# ('b', 'a', 'd', 'c')
# ('b', 'c', 'a', 'd')
# ('b', 'c', 'd', 'a')
# ('b', 'd', 'a', 'c')
# ('b', 'd', 'c', 'a')
# ('c', 'a', 'b', 'd')
# ('c', 'a', 'd', 'b')
# ('c', 'b', 'a', 'd')
# ('c', 'b', 'd', 'a')
# ('c', 'd', 'a', 'b')
# ('c', 'd', 'b', 'a')
# ('d', 'a', 'b', 'c')
# ('d', 'a', 'c', 'b')
# ('d', 'b', 'a', 'c')
# ('d', 'b', 'c', 'a')
# ('d', 'c', 'a', 'b')
# ('d', 'c', 'b', 'a')

print(len(list(itertools.permutations(l))))
# 24

itertools.permutations()에서 요소는 값이 아닌 위치를 기준으로 처리됩니다. 중복 값은 고려되지 않습니다.

l = ['a', 'a']

for v in itertools.permutations(l, 2):
    print(v)
# ('a', 'a')
# ('a', 'a')

아래에서 설명하는 다음 기능에도 동일하게 적용됩니다.

  • itertools.combinations()
  • itertools.combinations_with_replacement()

총 조합 수 계산

math.factorial()

조합의 수는 n개의 다른 조각에서 선택할 r개의 조각의 수입니다. 순서는 순열로 간주되지 않습니다.

총 조합 수 c는 다음 식에 의해 구합니다.

c = n! / (r! * (n - r)!)

계승을 반환하는 함수 math.factorial()을 사용하여 다음과 같이 계산할 수 있습니다. 정수 나누기를 수행하는 ⌘ 연산자는 정수 형식을 반환하는 데 사용됩니다.

def combinations_count(n, r):
    return math.factorial(n) // (math.factorial(n - r) * math.factorial(r))

print(combinations_count(4, 2))
# 6

scipy.special.comb()

SciPy는 순열의 총 수를 반환하는 scipy.special.comb() 함수를 제공합니다. 별도의 SciPy 설치가 필요합니다. 버전 0.14.0부터 사용 가능합니다. scipy.misc.comb()는 아래에 설명된 반복 인수를 구현하지 않습니다.

from scipy.special import comb

print(comb(4, 2))
# 6.0

print(comb(4, 2, exact=True))
# 6

print(comb(4, 0, exact=True))
# 1

exact=False
scipy.special.perm()과 마찬가지로 세 번째 인수는 기본적으로 위와 같이 설정되며 부동 소수점 숫자를 반환합니다. 정수로 받고 싶다면 다음과 같이 설정해야 합니다.
exact=True
중복 조합의 총 수는 네 번째 인수인 반복으로도 얻을 수 있습니다. 이것은 아래에 설명되어 있습니다.

다시 말하지만 “import scipy”는 scipy.special 모듈을 로드하지 않습니다.

위의 예와 같이 “from scipy.special import comb”로 comb()을 실행하거나 “import scipy.special”로 scipy.special.comb()를 실행합니다. “scipy.misc”에도 동일하게 적용됩니다.

math.factorial()을 사용하지 않는 방법

표준 라이브러리만 사용하며 math.factorial()을 사용하는 방법보다 빠른 또 다른 방법은 다음과 같습니다.

from operator import mul
from functools import reduce

def combinations_count(n, r):
    r = min(r, n - r)
    numer = reduce(mul, range(n, n - r, -1), 1)
    denom = reduce(mul, range(1, r + 1), 1)
    return numer // denom

print(combinations_count(4, 2))
# 6

print(combinations_count(4, 0))
# 1

목록에서 조합 생성 및 열거:itertools.combinations()

목록(배열) 등의 모든 조합과 총 수를 생성하고 열거하는 것이 가능합니다.

itertools 모듈의 조합() 함수를 사용하십시오.

iterable(목록 또는 집합 유형)을 첫 번째 인수로 전달하고 두 번째 인수로 선택할 조각 수를 전달하면 해당 조합에 대한 반복자가 반환됩니다.

l = ['a', 'b', 'c', 'd']

c = itertools.combinations(l, 2)

print(type(c))
# <class 'itertools.combinations'>

for v in itertools.combinations(l, 2):
    print(v)
# ('a', 'b')
# ('a', 'c')
# ('a', 'd')
# ('b', 'c')
# ('b', 'd')
# ('c', 'd')

c_list = list(itertools.combinations(l, 2))

print(c_list)
# [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]

print(len(c_list))
# 6

중복 조합의 총 수 계산

중복 조합의 수는 r이 n개의 다른 조합 중에서 선택되어 중복을 허용하는 경우의 수입니다.

중복 조합의 총 수는 (n + r – 1)개의 다른 조합 중에서 (r)을 선택하는 조합의 수와 같습니다.

따라서 위에서 정의한 함수를 사용하여 총 조합 수를 계산할 수 있습니다.

def combinations_with_replacement_count(n, r):
    return combinations_count(n + r - 1, r)

print(combinations_with_replacement_count(4, 2))
# 10

위에서 설명한 “scipy.special.comb()”에서 네 번째 인수인 “repetition=True”를 설정하면 중복 조합의 총 개수를 얻을 수 있습니다.
“반복” 인수는 “SciPy0.14.0” 이전 버전의 “scipy.misc.comb()”에서 구현되지 않습니다.

from scipy.special import comb
print(comb(4, 2, exact=True, repetition=True))
# 10

목록에서 중복 조합 생성 및 열거:itertools.combinations_with_replacement()

목록(배열) 등의 모든 중복 조합과 총 수를 생성하고 열거하는 것이 가능합니다.

itertools 모듈에서 Combines_with_replacement() 함수를 사용하십시오.

iterable(목록 또는 집합 유형)을 첫 번째 인수로 전달하고 두 번째 인수로 선택할 조각 수를 전달하면 겹치는 조합에 대한 반복자가 반환됩니다.

h = itertools.combinations_with_replacement(l, 2)

print(type(h))
# <class 'itertools.combinations_with_replacement'>

for v in itertools.combinations_with_replacement(l, 2):
    print(v)
# ('a', 'a')
# ('a', 'b')
# ('a', 'c')
# ('a', 'd')
# ('b', 'b')
# ('b', 'c')
# ('b', 'd')
# ('c', 'c')
# ('c', 'd')
# ('d', 'd')

h_list = list(itertools.combinations_with_replacement(l, 2))

print(h_list)
# [('a', 'a'), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'b'), ('b', 'c'), ('b', 'd'), ('c', 'c'), ('c', 'd'), ('d', 'd')]

print(len(h_list))
# 10

문자열에서 아나그램 만들기

Itertools.permutations()를 사용하면 문자열 순열(anagram)을 쉽게 만들 수 있습니다.

s = 'arc'

for v in itertools.permutations(s):
    print(v)
# ('a', 'r', 'c')
# ('a', 'c', 'r')
# ('r', 'a', 'c')
# ('r', 'c', 'a')
# ('c', 'a', 'r')
# ('c', 'r', 'a')

한 번에 한 문자의 튜플을 문자열로 결합하고 목록으로 만들려면 다음을 수행하십시오.

anagram_list = [''.join(v) for v in itertools.permutations(s)]

print(anagram_list)
# ['arc', 'acr', 'rac', 'rca', 'car', 'cra']

목록 또는 튜플의 요소를 문자열로 연결하는 join() 메서드와 목록 이해 표기법이 사용됩니다.

Copied title and URL