如何实现不枚举的排列组合问题正确答案数量计算函数?
问题描述
需要实现一个Python函数get_combinations,无需枚举所有可能(保证计算效率),计算符合条件的正确组合数量。函数结构参考:
from itertools import combinations_with_replacement from itertools import permutations def get_combinations(event, population): # "calculate number of answers" return nr_correct_answers
参数示例
纯颜色列表形式:
# event参数 event_1 = ["Red", "Blue", "Black"] event_2 = ["Red", "Red", "Blue"] # population参数 population = ["Red", "Red", "Blue", "Blue", "Black", "Black"]预期结果:
event_1返回8,event_2返回2。(数量,颜色)元组形式:
event_1 = [(1,"Red"), (1,"Blue"), (1,"Black")] event_2 = [(2,"Red"), (1,"Blue")] population = [(2,"Red"), (2,"Blue"), (2,"Black")]预期结果同上。
需求补充
- 不考虑选球顺序,但种群中每个元素是唯一带编号的球,仅关注颜色匹配;
- 需支持两种参数输入格式;
- 已尝试
itertools.permutations和product但未成功,寻求正确实现方式。
解决方案
核心思路是通过组合数公式直接计算,避免枚举所有可能,大幅提升计算效率。
1. 统一输入格式
先把两种输入格式转换为颜色计数字典,方便后续统一计算:
from collections import defaultdict import math def _to_count_dict(items): count_dict = defaultdict(int) for item in items: if isinstance(item, tuple): # 处理(数量,颜色)格式 cnt, color = item count_dict[color] += cnt else: # 处理纯颜色列表格式 count_dict[item] += 1 return count_dict
2. 完整函数实现
对每个颜色,计算从种群中选取对应数量的组合数,再将所有颜色的组合数相乘得到最终结果:
from collections import defaultdict import math def _to_count_dict(items): count_dict = defaultdict(int) for item in items: if isinstance(item, tuple): cnt, color = item count_dict[color] += cnt else: count_dict[item] += 1 return count_dict def get_combinations(event, population): event_counts = _to_count_dict(event) pop_counts = _to_count_dict(population) total = 1 for color, needed in event_counts.items(): available = pop_counts.get(color, 0) if available < needed: return 0 # 计算组合数C(available, needed):从available个元素中选needed个的组合数 total *= math.comb(available, needed) return total
3. 验证效果
# 测试列表格式参数 event_1 = ["Red", "Blue", "Black"] event_2 = ["Red", "Red", "Blue"] population = ["Red", "Red", "Blue", "Blue", "Black", "Black"] print(get_combinations(event_1, population)) # 输出8 print(get_combinations(event_2, population)) # 输出2 # 测试元组格式参数 event_1_t = [(1,"Red"), (1,"Blue"), (1,"Black")] event_2_t = [(2,"Red"), (1,"Blue")] population_t = [(2,"Red"), (2,"Blue"), (2,"Black")] print(get_combinations(event_1_t, population_t)) # 输出8 print(get_combinations(event_2_t, population_t)) # 输出2
关键说明
- 使用
math.comb(Python 3.10+支持)直接计算组合数,无需枚举所有可能,效率极高; - 兼容两种输入格式,通过
_to_count_dict做统一转换; - 若任意颜色的需求数量超过种群中该颜色的存量,直接返回0,逻辑严谨。
内容的提问来源于stack exchange,提问作者B.abba
相关产品推荐
相关产品推荐

