首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >组合组合

组合组合
EN

Stack Overflow用户
提问于 2019-06-03 20:49:49
回答 2查看 102关注 0票数 1

在1-49的范围内,从6个数字中选出了近1400万个组合。从1400万,我已经削减到890万的组合,只选择那些6的数字组合之和必须等于120到180之间。

例: 5,10,20,27,29,40 = 131

在剩下的890万个组合中,我试图删除所有包含小于2个和4个以上奇数的组合。

基本上,我想让Python向我展示这890万个组合中有多少个组合中有2-4个奇数。所有只有1个或更少奇数和5个或更多奇数的组合将被排除在结果之外。

例子: 5,10,20,27,32,40 =2个奇数(它将包含在组合的数量中)。

谢谢!

代码语言:javascript
复制
import functools

_MIN_SUM     = 120
_MAX_SUM     = 180
_MIN_NUM     = 1
_MAX_NUM     = 49
_NUM_CHOICES = 6

@functools.lru_cache(maxsize=None)
def f(n, l, s):
    assert(all(isinstance(v, int) and v >= 0 for v in (n, l, s)))
    return 0 if s > _MAX_SUM else (
        int(s >= _MIN_SUM) if n == 0 else (
            sum(f(n-1, i+1, s+i) for i in range(l, _MAX_NUM+1))
        )
    )

result = f(_NUM_CHOICES, _MIN_NUM, 0)

print('Number of choices = {}'.format(result))
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-03 21:12:00

你可以和你现在做的几乎完全一样。只需添加一个参数来计算有多少个奇数,并在添加一个奇数时增加它。然后,您可以相应地调整测试:

代码语言:javascript
复制
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))

因为它是回忆录和修剪树枝,所以它运行得很快:

代码语言:javascript
复制
150 ns ± 13 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

以更可管理的方式运行它:

代码语言:javascript
复制
_MIN_SUM     = 1
_MAX_SUM     = 8
_MIN_NUM     = 1
_MAX_NUM     = 8
_NUM_CHOICES = 2
_MIN_ODDS    = 2
_MAX_ODDS    = 4

返回4,它对应于集合:

代码语言:javascript
复制
(1, 3),
(1, 5),
(1, 7),
(3, 5)
票数 0
EN

Stack Overflow用户

发布于 2019-06-03 21:06:17

您可以使用itertools中的组合()函数,只需对符合条件的组合进行残酷的计数:

代码语言:javascript
复制
from itertools import combinations

eligible = 0
for combo in combinations(range(1,50),6):
    total = sum(combo)
    if total < 120 or total > 180:
        continue
    odds = sum(n&1 for n in combo)
    if odds < 2 or odds > 4:
        continue
    eligible += 1

print(eligible) # 7221936

它只需要几秒钟(10-12)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56434378

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档