다음은 콜백 함수를 사용하는 상당히 기본적인 반복적 인 순서 조합 제조업체입니다. BrenBarn의 솔루션만큼 다용도는 아니지만 질문에 지정된대로 제품 생성을 건너 뜁니다. seq
을 전달할 때 콜백이 실패하고 False
(또는 false-ish)을 반환하면 combo
은 다음으로 시작하는 다른 하위 시퀀스를 생성하지 않습니다. seq[:-1]
. 당신이 if not ok: i -= 1
줄을 주석으로 경우
def combo(n, k, callback):
a = list(range(k))
ok = callback(a)
k -= 1
while True:
i = k
if not ok: i -= 1
while True:
a[i] += 1
if a[i] == (n + i - k):
i -= 1
if i < 0:
return
else:
break
v = a[i] + 1
a[i+1:] = range(v, v + k - i)
ok = callback(a)
# test
n = 8
k = 4
def do_something(seq):
s = sum(seq)
ok = s <= seq[-2] * 3
print(seq, s, ok)
return ok
combo(n, k, do_something)
출력
[0, 1, 2, 3] 6 True
[0, 1, 2, 4] 7 False
[0, 1, 3, 4] 8 True
[0, 1, 3, 5] 9 True
[0, 1, 3, 6] 10 False
[0, 1, 4, 5] 10 True
[0, 1, 4, 6] 11 True
[0, 1, 4, 7] 12 True
[0, 1, 5, 6] 12 True
[0, 1, 5, 7] 13 True
[0, 1, 6, 7] 14 True
[0, 2, 3, 4] 9 True
[0, 2, 3, 5] 10 False
[0, 2, 4, 5] 11 True
[0, 2, 4, 6] 12 True
[0, 2, 4, 7] 13 False
[0, 2, 5, 6] 13 True
[0, 2, 5, 7] 14 True
[0, 2, 6, 7] 15 True
[0, 3, 4, 5] 12 True
[0, 3, 4, 6] 13 False
[0, 3, 5, 6] 14 True
[0, 3, 5, 7] 15 True
[0, 3, 6, 7] 16 True
[0, 4, 5, 6] 15 True
[0, 4, 5, 7] 16 False
[0, 4, 6, 7] 17 True
[0, 5, 6, 7] 18 True
[1, 2, 3, 4] 10 False
[1, 2, 4, 5] 12 True
[1, 2, 4, 6] 13 False
[1, 2, 5, 6] 14 True
[1, 2, 5, 7] 15 True
[1, 2, 6, 7] 16 True
[1, 3, 4, 5] 13 False
[1, 3, 5, 6] 15 True
[1, 3, 5, 7] 16 False
[1, 3, 6, 7] 17 True
[1, 4, 5, 6] 16 False
[1, 4, 6, 7] 18 True
[1, 5, 6, 7] 19 False
[2, 3, 4, 5] 14 False
[2, 3, 5, 6] 16 False
[2, 3, 6, 7] 18 True
[2, 4, 5, 6] 17 False
[2, 4, 6, 7] 19 False
[2, 5, 6, 7] 20 False
[3, 4, 5, 6] 18 False
[3, 4, 6, 7] 20 False
[3, 5, 6, 7] 21 False
[4, 5, 6, 7] 22 False
하면 모든 조합을 생성합니다.
이 코드는 더 쉽게 건너 뛸 수 있도록 쉽게 수정할 수 있습니다. 콜백에서 부울 반환 값을 사용하는 대신 원하는 건너 뛰기 레벨을 반환합니다. 0을 반환하면 건너 뛰지 않습니다. 1을 반환하면 위 버전 에서처럼 seq[:-1]
으로 시작하는 하위 시퀀스를 건너 뜁니다. `... 생략`list` : 콜백 2를 반환하면 우리는 ((* 세트) 제품을)
이
def combo(n, k, callback):
a = list(range(k))
skips = callback(a)
k -= 1
while True:
i = k - skips
while True:
a[i] += 1
if a[i] == (n + i - k):
i -= 1
if i < 0:
return
else:
break
v = a[i] + 1
a[i+1:] = range(v, v + k - i)
skips = callback(a)
목록에서 하위 집합'하지 말라 등
seq[:-2]
와 함께 시작 서브 시퀀스를 건너 이는 전체 '제품'을 메모리로 구체화하고 '제품'을 지연 반복하는 메모리 효율성을 피하게합니다. 당신이 그것을 주변에두고 있지 않기 때문에, 그것은 단지 무의미하게 비효율적입니다. –itertools를'product' 또는'combination'과 같이 사용하면 항상 모든 조합을 생성하게됩니다. 내부의 '중단'을 할 수 없습니다. * 당신은 * "실패한"사례를 저장하고, 마지막 요소를 검사하고, 다음 요소로 이동하기 위해'continue'를 사용하여 조합을 건너 뛸 수 있지만, 여전히 모든 요소를 얻습니다. – BrenBarn
'제품'을 사용하는 것이 전혀 도움이되지 않는다는 것을 나는 아직도 이해하지 못한다. –