itertools에 대해 알고 있지만 반복없이 순열 만 생성 할 수있는 것 같습니다.
예를 들어, 2 개의 주사위에 대해 가능한 모든 주사위 굴림을 생성하고 싶습니다. 따라서 반복을 포함하여 [1, 2, 3, 4, 5, 6] 크기 2의 모든 순열이 필요합니다 : (1, 1), (1, 2), (2, 1) ... 등
가능하다면 처음부터 구현하고 싶지 않습니다.
답변:
Cartesian Product를 찾고 있습니다.
수학에서 데카르트 곱 (또는 제품 세트)은 두 세트의 직접 곱입니다.
귀하의 경우 이것은 {1, 2, 3, 4, 5, 6}
x {1, 2, 3, 4, 5, 6}
입니다.
itertools
거기에서 당신을 도울 수 있습니다 :
import itertools
x = [1, 2, 3, 4, 5, 6]
[p for p in itertools.product(x, repeat=2)]
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 2), (2, 3),
(2, 4), (2, 5), (2, 6), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6),
(4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (5, 1), (5, 2), (5, 3),
(5, 4), (5, 5), (5, 6), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6)]
무작위 주사위 굴림을 얻으려면 ( 완전히 비효율적 인 방식으로 ) :
import random
random.choice([p for p in itertools.product(x, repeat=2)])
(6, 3)
순열을 찾는 것이 아니라 Cartesian Product 를 원합니다 . 이 사용 제품 의 경우 itertools :
from itertools import product
for roll in product([1, 2, 3, 4, 5, 6], repeat = 2):
print(roll)
파이썬 2.7과 3.1에는 itertools.combinations_with_replacement
함수가 있습니다 :
>>> list(itertools.combinations_with_replacement([1, 2, 3, 4, 5, 6], 2))
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 2), (2, 3), (2, 4),
(2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6), (4, 4), (4, 5), (4, 6),
(5, 5), (5, 6), (6, 6)]
(2, 1)
에서 풀 립니다. 일반적으로 두 번째 롤이 첫 번째 롤보다 낮은 모든 조합은 제외됩니다. (3, 2)
(3, 1)
이 경우 목록 이해력은 특별히 필요하지 않습니다.
주어진
import itertools as it
seq = range(1, 7)
r = 2
암호
list(it.product(seq, repeat=r))
세부
당연히 데카르트 곱은 순열의 하위 집합을 생성 할 수 있습니다. 그러나 다음과 같습니다.
product
치환이있는 순열, n r
[x for x in it.product(seq, repeat=r)]
대체없는 순열, n!
[x for x in it.product(seq, repeat=r) if len(set(x)) == r]
# Equivalent
list(it.permutations(seq, r))
결과적으로 모든 조합 함수는 다음에서 구현할 수 있습니다 product
.
combinations_with_replacement
구현 product
combinations
로 구현할 permutations
수있는에서 구현 됨 product
(위 참조)lambdas
, map
및을 사용하여 해결책을 찾은 것 같습니다 reduce
.
product_function = lambda n: reduce(lambda x, y: x+y, map(lambda i: list(map(lambda j: (i, j), np.arange(n))), np.arange(n)), [])
기본적으로 행을 제공하고 열을 반복하는 첫 번째 람다 함수를 매핑하고 있습니다.
list(map(lambda j: (i, j), np.arange(n)))
그러면 이것은 새로운 람다 함수의 출력으로 사용됩니다.
lambda i:list(map(lambda j: (i, j), np.arange(n)))
가능한 모든 행에 매핑됩니다.
map(lambda i: list(map(lambda j: (i, j), np.arange(n))), np.arange(m))
그런 다음 모든 결과 목록을 하나로 줄입니다.
두 개의 다른 숫자를 사용할 수도 있습니다.
prod= lambda n, m: reduce(lambda x, y: x+y, map(lambda i: list(map(lambda j: (i, j), np.arange(m))), np.arange(n)), [])
먼저 itertools.permutations (list)에서 반환 한 생성기를 목록으로 먼저 전환해야합니다. 그런 다음 두 번째로 set ()를 사용하여 중복을 제거 할 수 있습니다.
def permutate(a_list):
import itertools
return set(list(itertools.permutations(a_list)))
random.randint
이 더 간단하고 효율적입니다.