Python中如何生成忽略颜色类排列的小球颜色分配组合?
解决方法
核心思路是:我们要的不是具体颜色的组合,而是颜色出现频次的模式等价类——比如“1个某颜色+4个另一颜色”这种模式,不管具体是哪两种颜色,都算同一类。所以先找出所有可能的频次模式,再基于模式生成唯一的代表即可,完全避免重复。
步骤1:生成所有频次模式
先找出把5拆分成最多3个非负整数的所有非递增组合,每个组合对应三种颜色的出现次数,这样每个模式只代表一类等价组合:
- (5,0,0):单颜色全分配
- (4,1,0):一种颜色4次,另一种1次
- (3,2,0):一种颜色3次,另一种2次
- (3,1,1):一种颜色3次,另外两种各1次
- (2,2,1):两种颜色各2次,一种1次
用Python代码生成这些模式:
import itertools def get_frequency_patterns(total_balls, color_count): # 生成所有和为total_balls的非递减频次组合,长度为color_count for counts in itertools.combinations_with_replacement(range(total_balls + 1), color_count): if sum(counts) == total_balls: # 转换成非递增顺序,更直观展示频次差异 yield tuple(sorted(counts, reverse=True)) # 针对5个球、3种颜色的场景 patterns = list(get_frequency_patterns(5, 3))
步骤2:生成每个模式的唯一代表
如果需要直观的颜色组合代表,可以按固定颜色顺序(比如r→b→g)分配频次,这样每个等价类只会生成一个唯一的组合:
color_list = ['r', 'b', 'g'] def generate_unique_combinations(patterns, colors): unique_combs = [] for pattern in patterns: combo = [] for color, cnt in zip(colors, pattern): combo.extend([color] * cnt) unique_combs.append(tuple(combo)) return unique_combs unique_combs = generate_unique_combinations(patterns, color_list) for comb in unique_combs: print(comb)
运行后会输出5个唯一组合,正好对应所有等价类,完全没有重复。
补充说明
如果你的需求是要遍历每个等价类下的所有实际颜色分配(比如(4,1,0)模式下的(rrrrb)、(rrrrg)、(bbbb r)等),但又不想重复统计等价类,那可以基于每个频次模式,生成所有不同的颜色映射组合,但仅保留每个等价类的一个代表用于计数即可。
内容的提问来源于stack exchange,提问作者Trailblazer
相关产品推荐
相关产品推荐

