Skip to main content
 首页 » 编程设计

python之在 Python 中高效地生成词典系列

2025年05月04日20lidabo

我想生成一个字典序列的数字,这样每个数字的数字总和就是一个给定的常量。它有点类似于“子集和问题”。例如,如果我希望生成 sum = 3 的 4 位数字,那么我有一个类似的系列:

[3 0 0 0]

[2 1 0 0]

[2 0 1 0]

[2 0 0 1]

[1 2 0 0] ...等等。

我能够使用以下代码在 Python 中成功完成:

import numpy as np 
 
M = 4 # No. of digits 
N = 3 # Target sum 
 
a = np.zeros((1,M), int) 
b = np.zeros((1,M), int) 
 
a[0][0] = N 
jj = 0 
 
while a[jj][M-1] != N: 
    ii = M-2 
    while a[jj][ii] == 0: 
          ii = ii-1 
    kk = ii 
    if kk > 0: 
       b[0][0:kk-1] = a[jj][0:kk-1] 
    b[0][kk] = a[jj][kk]-1 
    b[0][kk+1] = N - sum(b[0][0:kk+1]) 
    b[0][kk+2:] = 0 
    a = np.concatenate((a,b), axis=0) 
    jj += 1 
 
for ii in range(0,len(a)): 
    print a[ii] 
 
print len(a) 

我认为这不是一种非常有效的方法(因为我是 Python 新手)。它适用于较小的 M 和 N (<10) 值,但超过此值就非常慢。我希望将它用于 M ~ 100 和 N ~ 6。我怎样才能使我的代码更高效或者是否有更好的编码方式?

请您参考如下方法:

改编自 Jorg Arndt 的书“Matters Computational”的非常有效的算法
(第 7.2 部分的组合字典顺序)

n = 4 
k = 3 
 
x = [0] * n 
x[0] = k 
 
while True: 
    print(x) 
    v = x[-1] 
    if (k==v ): 
        break 
    x[-1] = 0 
    j = -2 
    while (0==x[j]): 
        j -= 1 
    x[j] -= 1 
    x[j+1] = 1 + v 
 
[3, 0, 0, 0] 
[2, 1, 0, 0] 
[2, 0, 1, 0] 
[2, 0, 0, 1] 
[1, 2, 0, 0] 
[1, 1, 1, 0] 
[1, 1, 0, 1] 
[1, 0, 2, 0] 
[1, 0, 1, 1] 
[1, 0, 0, 2] 
[0, 3, 0, 0] 
[0, 2, 1, 0] 
[0, 2, 0, 1] 
[0, 1, 2, 0] 
[0, 1, 1, 1] 
[0, 1, 0, 2] 
[0, 0, 3, 0] 
[0, 0, 2, 1] 
[0, 0, 1, 2] 
[0, 0, 0, 3] 

n=100 和 k = 2,3,4,5 (2.8 ghz Cel-1840) 的纯 Python(也许 numpy 数组更快)的组合数和秒数

2  5050 0.040000200271606445 
3  171700 0.9900014400482178 
4  4421275 20.02204465866089 
5  91962520 372.03577995300293 
I expect time  2 hours for 100/6 generation 

与 numpy 数组相同 (x = np.zeros((n,), dtype=int)) 给出更差的结果 - 但也许是因为我不知道如何正确使用它们

2  5050 0.07999992370605469 
3  171700 2.390003204345703 
4  4421275 54.74532389640808 

native 代码(这是 Delphi,C/C++ 编译器可能优化得更好)生成 100/6 在 21 秒内

3  171700  0.012 
4  4421275  0.125 
5  91962520  1.544 
6  1609344100 20.748 

在所有测量都没有完成之前无法休眠:)

MSVS VC++:18 秒! (O2优化)

5  91962520 1.466 
6  1609344100 18.283 

所以每秒有 1 亿个变体。 大量时间浪费在检查空单元格上(因为填充率很小)。 Arndt 描述的速度是在更高的 k/n 比率下达到的,大约每秒 300-5 亿个变体:

n=25, k=15 25140840660 60.981  400 millions per second