练习4、有10个球分别为3红、3蓝、4白,球与球之间只有颜色的差别,现需要将这10个球放入3个盒子,要求每个盒子至少有一个白球,其余的球全部随机放,要求输出三个盒子里所有球的颜色,请用程序实现。
当时看到这道题,我的第一反应是要输出所有结果。然后我就拿笔算了一下,因为同种类球是相同的,所以白球共有3种可能性,红球和蓝球都是10种,那么总共是3*10*10=300种可能性。
考虑到电脑干活的特性,使用枚举法进行输出是最方便的,直接根据球数量枚举所有可能性,然后把数量对的输出即可。由于蓝球和红球相互独立,而且枚举的算法相同,所以定义了一个函数来完成这项工作,函数用枚举法工作,函数接受上一次三个框中球的数量,返回值是更新后三个框里球的数量,从第三个框开始加,加到最大数量就向前进1。然后程序外部进行三次循环,分别表示白球、蓝球和红球。最后可以在控制台看到300种不同的结果。
做完以后,问了一下同学才知道,用随机数输出一种情况就行了,好像多费了很多时间,不过这样确实学到了很多别的东西,也算有舍有得把。源程序在最后附上。
源程序如下:
def ball(number, color, *i, print_res = False):
"""枚举法输出每个框里球的数量
:param number: 某种颜色求的数量
:param color: 球的颜色
:param i: 传入刚刚三个篮子里球的数量,防止每次都出来第一个结果
:param print_res: 是否需要打印,只有在处理完红球以后才会打印
:return: 球在三个篮子中的数量,在下一次调用的时候要重新输入
"""
# 收上一次球的数量,因为后续循环里要+1,所以一开始要额外-1
i1, i2, i3 = i
i1 -= 1
i2 -= 1
while i1 < number:
i1 += 1
while i2 < number:
i2 += 1
while i3 < number:
i3 += 1
if (i1 + i2 + i3) == number:
dic[1][color] += i1
dic[2][color] += i2
dic[3][color] += i3
if print_res:
print(dic)
return i1, i2, i3
i3 = -1
i2 = -1
i1 = 0
# 如果i2、i3写0就会死循环,i1写-1就会多出球的个数为-1的情况
# 在所有数都到最大以后还要返回一个值,否则外部会报错
return i1, i2, i3
i_white = 0 # 唯一白球在哪个框里
i_blue = 0 # 蓝球在第一个框里的数量
i_red = 0 # 红球在第一个框里的数量
while i_white < 3:
# 每循环完一次大循环以后要重置字典、和中间变量的值
dic = {1: {"white": 1, "blue": 0, "red": 0},
2: {"white": 1, "blue": 0, "red": 0},
3: {"white": 1, "blue": 0, "red": 0}}
blue_mid = (0, 0, 0)
red_mid = (0, 0, 0)
i_blue = 0
i_white += 1 # 把白球放到下一个框里
dic[i_white]["white"] += 1
while i_blue < 3:
# 循环完一个整红球循环以后,重置字典里蓝球的数量
dic[1]["blue"] = 0
dic[2]["blue"] = 0
dic[3]["blue"] = 0
i_red = 0
blue_mid = ball(3, "blue", *blue_mid)
i_blue = blue_mid[0] # 调用传回的第一个框里蓝球的数量,用于判断
while i_red < 3:
# 输出一次以后,要重置字典里红球的数量
dic[1]["red"] = 0
dic[2]["red"] = 0
dic[3]["red"] = 0
red_mid = ball(3, "red", *red_mid, print_res=True)
i_red = red_mid[0] # 调用传回的第一个框里红球的数量,用于判断
|
|