我基本上有這個問題Get all numbers that add up to a number,但我也需要包含0。
我已經嘗試了接受的答案并使其從0開始,基本上就像
def sum_to_n(n, size, limit=None):
"""Produce all lists of `size` positive integers in decreasing order
that add up to `n`."""
if size == 1:
yield [n]
return
if limit is None:
limit = n
start = 0
stop = min(limit, n - size 1) 1
for i in range(start, stop):
for tail in sum_to_n(n - i, size - 1, i):
yield [i] tail
它適用于較小的數字,但是當我將較大的數字作為目標時,它開始表現得很奇怪。例如:
for partition in sum_to_n(10,7):
print(partition)
輸出就像
0 0 0 0 0 0 10
1 0 0 0 0 0 9
1 1 0 0 0 0 8
1 1 1 0 0 0 7
1 1 1 1 0 0 6
1 1 1 1 1 0 5
1 1 1 1 1 1 4
2 0 0 0 0 0 8
2 1 0 0 0 0 7
2 1 1 0 0 0 6
2 1 1 1 0 0 5
2 1 1 1 1 0 4
2 1 1 1 1 1 3
2 2 0 0 0 0 6
2 2 1 0 0 0 5
2 2 1 1 0 0 4
2 2 1 1 1 0 3
2 2 1 1 1 1 2
2 2 2 0 0 0 4
2 2 2 1 0 0 3
2 2 2 1 1 0 2
2 2 2 1 1 1 1
3 0 0 0 0 0 7
3 1 0 0 0 0 6
3 1 1 0 0 0 5
3 1 1 1 0 0 4
3 1 1 1 1 0 3
3 1 1 1 1 1 2
3 2 0 0 0 0 5
3 2 1 0 0 0 4
3 2 1 1 0 0 3
3 2 1 1 1 0 2
3 2 1 1 1 1 1
4 0 0 0 0 0 6
4 1 0 0 0 0 5
4 1 1 0 0 0 4
4 1 1 1 0 0 3
4 1 1 1 1 0 2
4 1 1 1 1 1 1
在這里,它顯然不包括 5 5 0 0 0 0 0 的情況。它也有重復的情況,如 1 1 1 1 1 1 4 和 4 1 1 1 1 1 1 ,這是我不想要的。這段代碼有什么問題?我該如何修改它或關于如何解決問題的任何其他想法?謝謝!
uj5u.com熱心網友回復:
我想這就是你想要的:
def sum_to_n2(n, size, limit=None):
if limit is None:
limit = n
if size == 1:
if n <= limit:
yield[n]
else:
for i in range(0, limit 1):
for tail in sum_to_n2(n - i, size - 1, min(i, n-i)):
yield[i] tail
print(list(sum_to_n2(10, 7)))
與您的代碼的區別:
- 在開始時檢查
limit is None該功能是否更簡單if .. else(主要是裝飾性的,我覺得更容易理解,不需要return離開那里); - 你總是讓步
[n]ifsize == 1,但只有在n <= limit; - 您將范圍的限制計算為
min(limit, n - size 1) 1,但這很難在心理上跟蹤(更是如此,因為范圍在它附近停止);我只是說限制是i(我們添加到序列中的數字,因此不再允許更大的數字)和n-i(其余的,我們不再需要比這更大的數字)的最小值,并將其傳遞給遞回呼叫min(i, n-i)。
我還沒有對代碼中計算錯誤的位置進行完整的邏輯處理,但是如果我將n <= limit條件添加到代碼中,它就不再包含零。我敢肯定,在將值與我的演算法實作進行比較時,你可以弄清楚,但我認為無論如何我的更干凈一些,所以更可取。
的輸出6, 3已經顯示您的代碼存在問題,該代碼比10, 7. 您的輸出sum_to_n(5, 3):
[[0, 0, 5], [1, 0, 4], [1, 1, 3], [2, 0, 3], [2, 1, 2], [2, 2, 1], [3, 0, 2], [3, 1, 1]]
請注意其中的重復項,[2, 1, 2]例如[2, 2, 1]。
我的輸出sum_to_n2(5, 3):
[[2, 2, 1], [3, 1, 1], [3, 2, 0], [4, 1, 0], [5, 0, 0]]
就個人而言,但這純粹是風格,我更喜歡這個修改后的實作的輸出:
def sum_to_n2(n, size, limit=None):
if limit is None:
limit = n
if size == 1:
if n <= limit:
yield[n]
else:
for i in range(limit, -1, -1):
for tail in sum_to_n2(n - i, size - 1, min(i, n - i)):
yield[i] tail
這導致(對于sum_to_n2(5, 3)):
[[5, 0, 0], [4, 1, 0], [3, 2, 0], [3, 1, 1], [2, 2, 1]]
它通過反轉for回圈中的范圍來做到這一點。
順便說一句,這是一個非遞回的單線器,但它像泥巴一樣慢:):
def sum_to_n_one_liner (n, sized):
set(tuple(sorted(t)) for t in filter(lambda s: sum(s) == n, product(*[range(n)]*size)))
它通過天真地做需要做的事情來作業:
- 取從 0 到
n,size次的數字 - 計算笛卡爾積,因此您可以獲得這些數字的所有可能組合
- 只保留總和的那些
n - 對結果元組進行排序并僅保留唯一的元組
uj5u.com熱心網友回復:
為了不產生重復的磁區,您可以定義該函式,使其僅生成非降序的結果。
def partition(N,size):
if size == 1 :
yield (N,) # base case, only 1 part
return
for a in range(N//size 1): # smaller part followed by
for p in partition(N-a*size,size-1): # equal or larger ones
yield (a, *(n a for n in p)) # recursing on delta only
輸出:
for p in partition(10,7): print(p)
(0, 0, 0, 0, 0, 0, 10)
(0, 0, 0, 0, 0, 1, 9)
(0, 0, 0, 0, 0, 2, 8)
(0, 0, 0, 0, 0, 3, 7)
(0, 0, 0, 0, 0, 4, 6)
(0, 0, 0, 0, 0, 5, 5)
(0, 0, 0, 0, 1, 1, 8)
(0, 0, 0, 0, 1, 2, 7)
(0, 0, 0, 0, 1, 3, 6)
(0, 0, 0, 0, 1, 4, 5)
(0, 0, 0, 0, 2, 2, 6)
(0, 0, 0, 0, 2, 3, 5)
(0, 0, 0, 0, 2, 4, 4)
(0, 0, 0, 0, 3, 3, 4)
(0, 0, 0, 1, 1, 1, 7)
(0, 0, 0, 1, 1, 2, 6)
(0, 0, 0, 1, 1, 3, 5)
(0, 0, 0, 1, 1, 4, 4)
(0, 0, 0, 1, 2, 2, 5)
(0, 0, 0, 1, 2, 3, 4)
(0, 0, 0, 1, 3, 3, 3)
(0, 0, 0, 2, 2, 2, 4)
(0, 0, 0, 2, 2, 3, 3)
(0, 0, 1, 1, 1, 1, 6)
(0, 0, 1, 1, 1, 2, 5)
(0, 0, 1, 1, 1, 3, 4)
(0, 0, 1, 1, 2, 2, 4)
(0, 0, 1, 1, 2, 3, 3)
(0, 0, 1, 2, 2, 2, 3)
(0, 0, 2, 2, 2, 2, 2)
(0, 1, 1, 1, 1, 1, 5)
(0, 1, 1, 1, 1, 2, 4)
(0, 1, 1, 1, 1, 3, 3)
(0, 1, 1, 1, 2, 2, 3)
(0, 1, 1, 2, 2, 2, 2)
(1, 1, 1, 1, 1, 1, 4)
(1, 1, 1, 1, 1, 2, 3)
(1, 1, 1, 1, 2, 2, 2)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/412187.html
標籤:
下一篇:找到一個矩形和一個圓的交點
