Python 总和为 1 的特定值的所有订单

Python for all orders of specific values that sum to 1

我正在编写一个处理一些音乐理论的应用程序,需要以编程方式确定可以在单个小节中排列各种特定音符值的每种方式,其中这些音符值的每种排列加起来恰好为 1。

最简单的情况是小节内的值为 1 的单个音符。但我至少需要考虑以下每个值:

1

0.5

0.25

0.125

我正在寻找的结果可以让我确定以下可能的顺序,每个顺序加起来为 1。这些情况:

| 1 |

|.25, .5, .25 |

|.25, .25., .5 |

| .5, .25, .125, .125 |

|.125, .125, .125, .125, .125, .125, .125, .125 |

等....

注意:我在此处找到的至少一个 post 为我提供了一个解决方案,但它删除了加起来为 1 的重复值——例如,结果没有给出这种情况|.125, .125, .125, .125, .125, .125, .125, .125 |

我最初试图使用我在下面的代码中注释掉的变量来获取列表,并希望解决方案看起来更像这样(尽管我为这个例子编了这个顺序):

[w, hh, hqh, qeqqe, eeqqee, qeqeq...]

我不知道该怎么做。

总的来说,我认为应该有 44 种可能性,但我不知道用代码生成这些可能性的最佳方法。

我什至不知道尝试解决问题的最佳方法,因为看起来可能有一种数学上更有趣、更有效的方法来解决这个问题。

我现在所拥有的是使用代表每个值排序的字符串排列,它让我朝着正确的方向前进。但非常感谢任何有关更好解决方案的帮助和想法!!

from itertools import permutations

### Note values ###

'''
w = 1
h = 0.5
q = 0.25
e = 0.125
'''

e8 = ['eeeeeeee']
eq7 = [''.join(p) for p in permutations('eeeeeeq')]
eq6 = [''.join(p) for p in permutations('eeeeqq')]
eq5 = [''.join(p) for p in permutations('qqqee')]
eh5 = [''.join(p) for p in permutations('eeeeh')]
q4 = ['qqqq']
qh3 = [''.join(p) for p in permutations('qqh')]
h2 = ['hh']
w1 = ['w']

allPossible = list(set.union(*map(set, [e8, eq7, eq6, eq5, eh5, q4, qh3, h2, w1])))

print(len(allPossible))
print(allPossible)

由于我还没有准备好所有关于排列和东西的知识,我可以帮助你解决问题的第一部分。即,所有可能等于1的组合有哪些?

我建议将所有音符值放在一个列表中。然后遍历这个列表,这样所有的组合都被覆盖了。

举例说明:

# Note values
values_list = [1, 0.5, 0.25, 0.125]

# Threshold to deal with floats. Or use the fractions package.
threshold = 0.01

result = []

for i in range(round(1 / values_list[0]) + 1):
    for j in range(round(1 / values_list[1]) + 1):
        for k in range(round(1 / values_list[2]) + 1):
            for l in range(round(1 / values_list[3]) + 1):
                if abs(i * values_list[0] + j * values_list[1] + k * values_list[2] + l * values_list[3] - 1) < threshold:
                    result.append([i,j,k,l])

print(result)
>>> [[0, 0, 0, 8], [0, 0, 1, 6], [0, 0, 2, 4], [0, 0, 3, 2], [0, 0, 4, 0], [0, 1, 0, 4], [0, 1, 1, 2], [0, 1, 2, 0], [0, 2, 0, 0], [1, 0, 0, 0]]

通过这种方式,您可以将所有可能的组合存储在 result 中,其中 i * values_list[0] + j * values_list[1] + k * values_list[2] + l * values_list[3] == 1。对于第一个结果我们可以看到例如0 * 1 + 0 * 0.5 + 0 * 0.25 + 8 * 0.125 == 1,确实如此。 正如@TomKarzes 所说,您也可以使用 fractions 包而不是阈值。

此外,我认为您足够聪明,可以找到一种方法来使用可变数量的 for 循环来使 values_list 变量中的值的数量。 祝你答对问题的第二部分。