簡體   English   中英

列表中所有可能的數字組合

[英]All posible combinations of numbers on a list

我需要找到具有已定義長度和已定義大小數字的列表的所有可能組合,但受制於不允許在列表中具有相同重復數字(0 除外)的限制。 目前我有一個生成所有組合的遞歸代碼,但是在嘗試創建約束時,我失去了很多選項。 我已經嘗試了出現評論的選項來解決它,但它仍然對我不起作用。 預先感謝您的幫助。

size=3
l=[0 for x in range(size)]

def recursive(l, index, num, final):
    if index == len(l) or num == final:
        return
#     if num!=0 and num in l:
#         return
    l[index]=num
    print(l)
    recursive(l, index+1, 0, final)
    recursive(l, index, num+1, final)
recursive(l, 0, 0, 4)

對於大小為 3 和最終數字為 3 的列表,預期的 output 將是這樣的

[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 0, 3]
[0, 1, 0]
[0, 1, 2]
[0, 1, 3]
[0, 2, 0]
[0, 2, 1]
[0, 2, 3]
[0, 3, 0]
[0, 3, 1]
[0, 3, 2]
[1, 0, 0]
[1, 0, 2]
[1, 0, 3]
[1, 2, 0]
[1, 2, 3]
[1, 3, 0]
[1, 3, 2]
[2, 0, 0]
[2, 0, 1]
[2, 0, 3]
[2, 1, 0]
[2, 1, 3]
[2, 3, 0]
[2, 3, 1]
[3, 0, 0]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]

從非零值的冪集開始(可以在itertools文檔中找到用於計算列表的冪集的 function。)

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

>>> list(powerset([1,2,3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

(您可以計算包括 0 的冪集,但您仍然需要對較短的元素進行零填充,並丟棄(0,1,2,3) )。

冪集的每個元素接下來應該用零填充,以使它們的長度都相同。

最后,您需要原始輸入的每個 0 填充排列的排列列表(使用itertools.permutations )。

使用itertools.combinations_with_replacement() ,然后過濾掉重復的元素。

def has_duplicates(l):
    '''Return True if list has duplicate elements other than 0'''
    l = [x in l if x != 0]
    return len(l) != len(set(l))

result = [comb for comb in itertools.combinations_with_replacement(l, 3) if not has_duplicates(comb)]

你可以通過使用itertools.filterfalse()使它變得懶惰; 這樣你就不會用一個大列表的所有組合來填充 memory 。

result = itertools.filterfalse(has_duplicates, itertools.combinations_with_replacement(l, 3))

這是一個基於計數器的解決方案,我使用的是 4 進制計數器:

def charcnt(s, a):
    ctr = [1 if x == a else 0 for x in s ]
    return sum(ctr)
    

def my_range(start,end,base,step=1):
    def Convert(n,base):
       string = "0123"
       if n < base:
          return string[n]
       else:
          return Convert(n//base,base) + string[n%base]
    return (Convert(i,base) for i in range(start,end,step))

# base-10 58 will produce base-4 321
counter = [x.zfill(3) for x in my_range(0, 58, 4)]

result = []
for s in counter:
    if charcnt(s, '1') > 1 or charcnt(s, '2') > 1 or charcnt(s, '3') > 1:
        continue
    else:
        result.append(s)

result = [[int(n) for n in list(s)] for s in result]
#print(len(result))
for i in result:
    print(i)

將產生:

[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 0, 3]
[0, 1, 0]
[0, 1, 2]
[0, 1, 3]
[0, 2, 0]
[0, 2, 1]
[0, 2, 3]
[0, 3, 0]
[0, 3, 1]
[0, 3, 2]
[1, 0, 0]
[1, 0, 2]
[1, 0, 3]
[1, 2, 0]
[1, 2, 3]
[1, 3, 0]
[1, 3, 2]
[2, 0, 0]
[2, 0, 1]
[2, 0, 3]
[2, 1, 0]
[2, 1, 3]
[2, 3, 0]
[2, 3, 1]
[3, 0, 0]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM