반복으로 순열 생성


84

itertools에 대해 알고 있지만 반복없이 순열 만 생성 할 수있는 것 같습니다.

예를 들어, 2 개의 주사위에 대해 가능한 모든 주사위 굴림을 생성하고 싶습니다. 따라서 반복을 포함하여 [1, 2, 3, 4, 5, 6] 크기 2의 모든 순열이 필요합니다 : (1, 1), (1, 2), (2, 1) ... 등

가능하다면 처음부터 구현하고 싶지 않습니다.

답변:


144

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)

8
이것은 2 개의 주사위를 굴리는 매우 비효율적 인 방법입니다. 두 번의 호출 random.randint이 더 간단하고 효율적입니다.
에릭 O Lebigot

[(2) xrange의 난에 대한 random.randint (1,6)] : 임의의 주사위 롤은 훨씬 더 빨리 당신이 모든 가능한 쌍을 생성하지 않는 경우가 될 것이다
liori

13
나는 실제로 무작위 롤을 생성하려고 시도한 것이 아니라 가능한 모든 롤을 나열하기 위해 노력했습니다.
Bwmat 2010-06-23


7

파이썬 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)]

12
이 솔루션은 , 및 유사 조합 (2, 1)에서 풀 립니다. 일반적으로 두 번째 롤이 첫 번째 롤보다 낮은 모든 조합은 제외됩니다. (3, 2)(3, 1)
holroy

1

이 경우 목록 이해력은 특별히 필요하지 않습니다.

주어진

import itertools as it


seq = range(1, 7)
r = 2

암호

list(it.product(seq, repeat=r))

세부

당연히 데카르트 곱은 순열의 하위 집합을 생성 할 수 있습니다. 그러나 다음과 같습니다.

  • 여분으로 모든 순열 생성 N 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.


-1

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)), [])

-2

먼저 itertools.permutations (list)에서 반환 한 생성기를 목록으로 먼저 전환해야합니다. 그런 다음 두 번째로 set ()를 사용하여 중복을 제거 할 수 있습니다.

def permutate(a_list):
    import itertools
    return set(list(itertools.permutations(a_list)))

1
중복은 포함되지 않습니다.
Björn Lindqvist

1
영업 이익은 명시 적으로 중복을 원
레위 Lesches
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.