如果您的数字范围为1-49,可以选择6个数字,则将有近1400万个组合。使用当前的脚本,我目前仅剩下720万个组合。在剩余的720万个组合中,我要消除所有3、4、5、6,双和三连贯数字。 示例:
注意:还必须消除诸如1、2、12、13、14、15之类的组合,否则它们将与要消除双重和三重连续组合的规则相冲突。
我正在寻找720万个剩余组合中有多少个组合具有连续的零个数字(全部混合)和只有一对连续的双子。
谢谢!
import functools
_MIN_SUM = 120
_MAX_SUM = 180
_MIN_NUM = 1
_MAX_NUM = 49
_NUM_CHOICES = 6
_MIN_ODDS = 2
_MAX_ODDS = 4
@functools.lru_cache(maxsize=None)
def f(n, l, s = 0, odds = 0):
if s > _MAX_SUM or odds > _MAX_ODDS:
return 0
if n == 0 :
return int(s >= _MIN_SUM and odds >= _MIN_ODDS)
return sum(f(n-1, i+1, s+i, odds + i % 2) for i in range(l, _MAX_NUM+1))
result = f(_NUM_CHOICES, _MIN_NUM)
print('Number of choices = {}'.format(result))
答案 0 :(得分:0)
虽然我的回答应该起作用,但我认为有人可能能够提供更快的解决方案。
考虑以下代码:
not_allowed = []
for x in range(48):
not_allowed.append([x, x+1, x+2])
# not_allowed = [ [0,1,2], [1,2,3], ... [11,12,13], ... [47,48,49] ]
my_numbers = [[1, 2, 5, 9, 11, 33], [1, 3, 7, 8, 9, 31], [12, 13, 14, 15, 23, 43]]
for x in my_numbers:
for y in not_allowed:
if set(y) <= set(x): # if [1,2,3] is a subset of [1,2,5,9,11,33], etc.
# drop x
此代码将删除所有包含双连续号的实例,这是您真正需要检查的所有内容,因为三倍,四倍等均表示双连续。尝试实现这一点,让我知道它是如何工作的。
答案 1 :(得分:0)
最简单的方法可能是生成和过滤。我使用numpy尝试向量化尽可能多的向量:
np.subtract(combos[:, :-1], combos[:, 1:])
打破那条“魔术”线
itertools.combinations
一次拍摄整个组合。请注意,np.abs(...)
产生 sorted 组合,这取决于它们。1
的数字之间的正距离。np.where(... == 1)[0]
(连续数字)与np.where
之间的差异。请注意,np.bincount(...)
返回一个元组,其中第一个项目是所有行,第二个项目是我们条件的所有对应列。这很重要,因为任何显示多次的行值都告诉我们该行中有多个连续数字![5, 4, 4, 4, 3, 2, 1, 0]
计算出每一行出现在结果中的次数,这将返回类似np.where(... <= 1)[0]
的信息,指示组合数据集的每一行中有多少对连续。'tags'
抓取连续0或1个连续值的行号。我正在返回的 way 组合比您似乎要显示的要多,但是我对此很有信心。一定要在评论中戳一下它,然后看看是否可以找到修复程序!
奖金,因为它们都是矢量化的,所以超级快!