O módulo estándar de matemáticas para funcións matemáticas en Python pódese usar para calcular factoriais. SciPy tamén ten funcións para calcular o número total de permutacións/combinacións.
O módulo itertools tamén se pode usar para xerar permutacións e combinacións a partir de listas (matrices), etc., e enumeralas.
Aquí explícase o seguinte, xunto co código de mostra.
- factorial:
math.factorial()
- Calcula o número total de permutacións
math.factorial()
scipy.special.perm()
- Xerar e enumerar permutacións a partir dunha lista:
itertools.permutations()
- Calcula o número total de combinacións
math.factorial()
scipy.special.comb()
- Como non usar math.factorial()
- Xerar e enumerar combinacións a partir de listas:
itertools.combinations()
- Calcula o número total de combinacións duplicadas
- Xerar e enumerar combinacións duplicadas a partir dunha lista:
itertools.combinations_with_replacement()
Como exemplo de utilización de permutacións, tamén se explica o seguinte.
- Crea anagramas a partir de cadeas
Se queres xerar unha combinación de elementos de varias listas en lugar dunha única lista, usa itertools.product() no módulo itertools.
- factorial:math.factorial()
- Calcula o número total de permutacións
- Xerar e enumerar permutacións a partir dunha lista:itertools.permutations()
- Calcula o número total de combinacións
- Xerar e enumerar combinacións a partir de listas:itertools.combinations()
- Calcula o número total de combinacións duplicadas
- Xerar e enumerar combinacións duplicadas a partir dunha lista:itertools.combinations_with_replacement()
- Crea anagramas a partir de cadeas
factorial:math.factorial()
O módulo matemático proporciona unha función factorial() que devolve o factorial.
import math
print(math.factorial(5))
# 120
print(math.factorial(0))
# 1
Os valores negativos non enteiros darán lugar a un ValueError.
# print(math.factorial(1.5))
# ValueError: factorial() only accepts integral values
# print(math.factorial(-1))
# ValueError: factorial() not defined for negative values
Calcula o número total de permutacións
math.factorial()
As permutacións son o número de casos nos que r son escollidos entre n diferentes e colocados nunha fila.
O número total de permutacións, p, obtense mediante a seguinte ecuación utilizando factoriais.
p = n! / (n - r)!
Pódese calcular do seguinte xeito usando a función math.factorial(), que devolve o factorial. O operador ⌘, que realiza a división de enteiros, úsase para devolver un tipo de enteiro.
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 proporciona unha función scipy.special.perm() que devolve o número total de permutacións. Requírese unha instalación de SciPy separada. Dispoñible desde a versión 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
O terceiro argumento establécese como anteriormente e devolve un número de coma flotante. Teña en conta que se queres obtelo como un número enteiro, debes configuralo como segue.exact=True
Teña en conta que só “import scipy” non cargará o módulo scipy.special.
Execute perm() como “de scipy.special import perm” como no exemplo anterior, ou executa scipy.special.perm() como “import scipy.special”.
Xerar e enumerar permutacións a partir dunha lista:itertools.permutations()
Non só se poden xerar e enumerar números totais, senón tamén permutacións a partir de listas (matrices), etc.
Use a función permutations() do módulo itertools.
Pasar un iterable (tipo de lista ou conxunto) como primeiro argumento e o número de pezas que se seleccionarán como segundo argumento devolve un iterador para esa permutación.
import itertools
l = ['a', 'b', 'c', 'd']
p = itertools.permutations(l, 2)
print(type(p))
# <class 'itertools.permutations'>
Para enumeralos todos, pode usar un bucle 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')
Dado que é un iterador finito, tamén se pode converter nun tipo de lista con list().
Cando o número de elementos da lista se obtén con len(), pódese confirmar que coincide co número total de permutacións calculadas a partir do 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
Se se omite o segundo argumento, devólvese a permutación para seleccionar todos os elementos.
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
En itertools.permutations(), os elementos trátanse en función da posición, non do valor. Non se teñen en conta os valores duplicados.
l = ['a', 'a']
for v in itertools.permutations(l, 2):
print(v)
# ('a', 'a')
# ('a', 'a')
O mesmo aplícase ás seguintes funcións, descritas a continuación.
itertools.combinations()
itertools.combinations_with_replacement()
Calcula o número total de combinacións
math.factorial()
O número de combinacións é o número de r pezas para escoller entre n pezas diferentes. A orde non se considera como nas permutacións.
O número total de combinacións c obtense coa seguinte ecuación.
c = n! / (r! * (n - r)!)
Pódese calcular do seguinte xeito usando a función math.factorial(), que devolve o factorial. O operador ⌘, que realiza a división de enteiros, úsase para devolver un tipo de enteiro.
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 proporciona unha función scipy.special.comb() que devolve o número total de permutacións. Requírese unha instalación de SciPy separada. Dispoñible desde a versión 0.14.0. Teña en conta que scipy.misc.comb() non implementa a repetición de argumentos descrita a continuación.
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
Do mesmo xeito que con scipy.special.perm(), o terceiro argumento establécese como anteriormente e devolve un número de coma flotante. Teña en conta que se queres obtelo como un número enteiro, debes configuralo como segue.exact=True
O número total de combinacións duplicadas tamén se pode obter co cuarto argumento, a repetición. Isto descríbese a continuación.
De novo, teña en conta que só “import scipy” non cargará o módulo scipy.special.
Como no exemplo anterior, executa comb() como “de scipy.special import comb” ou executa scipy.special.comb() como “import scipy.special”. O mesmo aplícase a “scipy.misc”.
Como non usar math.factorial()
Outro método que usa só a biblioteca estándar e é máis rápido que o método que usa math.factorial() é o seguinte método.
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
Xerar e enumerar combinacións a partir de listas:itertools.combinations()
É posible xerar e enumerar todas as combinacións a partir de listas (matrices), etc., así como os números totais.
Use a función combinaisons() do módulo itertools.
Ao pasar un iterable (tipo de lista ou conxunto) como primeiro argumento e o número de pezas a seleccionar como segundo argumento devolve o iterador para esa combinación.
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
Calcula o número total de combinacións duplicadas
O número de combinacións duplicadas é o número de casos nos que r son escollidos entre n diferentes, permitindo duplicados.
O número total de combinacións duplicadas é igual ao número de combinacións para escoller (r) entre (n + r – 1) diferentes.
Polo tanto, podemos utilizar a función definida anteriormente para calcular o número total de combinacións.
def combinations_with_replacement_count(n, r):
return combinations_count(n + r - 1, r)
print(combinations_with_replacement_count(4, 2))
# 10
En “scipy.special.comb()” descrito anteriormente, pódese obter o número total de combinacións duplicadas configurando o cuarto argumento “repetition=True.
Teña en conta que o argumento “repetición” non está implementado en “scipy.misc.comb()” nas versións anteriores a “SciPy0.14.0”.
from scipy.special import comb
print(comb(4, 2, exact=True, repetition=True))
# 10
Xerar e enumerar combinacións duplicadas a partir dunha lista:itertools.combinations_with_replacement()
É posible xerar e enumerar todas as combinacións duplicadas a partir de listas (matrices), etc., así como os números totais.
Use a función combinaisons_with_replacement() no módulo itertools.
Ao pasar un iterable (tipo de lista ou conxunto) como primeiro argumento e o número de pezas a seleccionar como segundo argumento, devolve un iterador para esa combinación superposta.
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
Crea anagramas a partir de cadeas
Itertools.permutations() facilita a creación de permutacións de cadeas (anagramas).
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')
Para combinar unha tupla dun carácter á vez nunha cadea e convertela nunha lista, faga o seguinte
anagram_list = [''.join(v) for v in itertools.permutations(s)]
print(anagram_list)
# ['arc', 'acr', 'rac', 'rca', 'car', 'cra']
Emprégase o método join(), que concatena elementos dunha lista ou tupla nunha cadea, e a notación de comprensión da lista.
- RELACIONADO:Concatenación (unión) de cadeas en Python
- RELACIONADO:Como usar as listas de comprensión de Python