鱼C论坛

 找回密码
 立即注册
查看: 9050|回复: 35

[技术交流] 02 - 借玩具的组合

[复制链接]
发表于 2021-3-5 18:44:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 不二如是 于 2022-4-17 22:22 编辑

在线视频:



找到女神的手机号了吗?

小师妹做了什么,让这么多童鞋发弹幕:

2021-03-05_18-29-11.jpg

哈哈哈,不告诉你们,自己去看啦~

这讲咱们来解决一个借玩具问题,小由鱼到手了 5 个新玩具,准备借给 3 位鱼油,并且一人只能借一个玩具。

请问:

有多少种不同的借法?

这种题目一看就是属于数学中常见的排列组合问题。

抛开题目场景,就是从 5 个数中取 3 个不同数的排列组合的总数。

我们可以将 5 个玩具用 1~5 编号,A、B、C 三个人每次都可以从 5 个玩具中中任选 1 个。

即每人都有 5 种选择,由于 1 个玩具不可能同时借给一个以上的人。

因此只要这三个人所选玩具的编号不同,则即为一次有效的借用次数。

对于每个人所选玩具号,还是采用穷举循环来实现。

即从每个人在玩具号(1、2、3、4、5)范围内进行穷举,从而得到可行的结果。

对于第一个人的选择,可以用循环将其列出,在上一节已经说过,while 循环的优化方案:for ... in range() 。

同理,对于第二个人、第三个人可以用同样的方法。

由于一个玩具只能借给一个人,故第二个人的选择会受到第一个人的限制,最后一个人的选择会受到第二个人的限制。

即后面的选择都是在前面选择的前提下进行的,所以可采用循环的嵌套来解决问题。

利用循环解决问题的时候,其实都会涉及循环三要素

之前一直只是带大家用,这次来总结下。

何为循环三要素呢?

就是这三件事:

  • 循环变量的初值
  • 循环的控制条件
  • 使循环趋于结束的循环变量值的改变

找到这 3 要素是进行编程的关键。

本题的输出结果有一个条件限制:

游客,如果您要查看本帖隐藏内容请回复

对于听过师妹小讲堂前几讲的童鞋,将上面条件写成代码应该不难。

一个 if 语句搞定:
if a != b and a != c and c != b

剩下就是不同号码的判断。

最简单粗暴还是穷举法,因为是 3 个人就用 a,b,c 代表。

玩具范围就用数字 1,2,3,4,5 表示。

分别给 a,b,c 赋值来模拟借玩具的过程,初值就都是 1。

使循环趋于结束的循环变量值的改变就是每层 a,b,c 值都要小于 6 。

流程图就是这样:

送玩具.png

在上节课的最后教给童鞋们,像这种 while 循环都可以用 for in range() 来实现。

还是那句话:

做好流程图,程序立刻出~


直接撸代码:
# A、B、C三人,5个玩具,每人每次只能借一个
# 用a、b、c分别表示三人所选玩具的编号
if __name__ == "__main__":
    print("A, B, C三人所选玩具方案:")
    # 用来控制A借玩具编号
    for a in range(1, 6):
        # 用来控制B借玩具编号
        for b in range(1, 6):
            # 用来控制C借玩具编号
            for c in range(1, 6):
                if a != b and a != c and c != b:
                    print("A: %2d  B: %2d  C: %2d" % (a, b, c),  end='')
                    print()
来看下结果:

2021-03-09_17-51-27.jpg

出来是出来了,但是好长好长,看起来很麻烦!

如果还想知道总共有多少个方案,貌似也没办法,难道一个一个去数吗??

怎么可能?!

对于程序员来说:能让机器干的活,绝不自己来哈!

我们可以创建一个变量 i 用来计数,输出方案的时候就加 1。

另外这种计数值还有个作用,就是用来换行!

例如我们想一排显示 4 组数据,就可以判断 i 这个整除 4 是否有余数。

余数为 0 说明是 4 个倍数,就可以来换行,简单修改下代码:
if __name__ == "__main__":
    # i用来计数
    i = 0
    print("A, B, C三人所选玩具方案:")
    for a in range(1, 6):
        for b in range(1, 6):
            for c in range(1, 6):
                if a != b and a != c and c != b:
                    print("A: %2d  B: %2d  C: %2d" % (a, b, c),  end='')
                    # 输出时i计数加1
                    i += 1
                    # 一行4个数据
                    if i % 4 == 0:
                        print()
    # 采用更符合Python规范的打印
    print('共有{}种组合'.format(i))
输出:

2021-03-09_18-23-18.jpg

本节课的重点除了上面的循环三要素外,另一个就是打印

代码中的这种打印:
 print("A: %2d  B: %2d  C: %2d" % (a, b, c),  end='')
是属于 Python2 遗留下来的 C 语言风格打印方式,在 Python3 中已规定不推荐。

要使用 str.format() 方法:
print('共有{}种组合'.format(i))
小甲鱼老师在最新版的 Python 教程中已讲过,自行学习:

2021-03-10_09-00-33.jpg

文字版在这里:字符串格式化语法参考

以后再遇到这种组合问题,都是大同小异,不许说不会啦~

这次不拖堂啦,下课!

源码(不推荐下载 ):
游客,如果您要查看本帖隐藏内容请回复

评分

参与人数 1荣誉 +2 鱼币 +3 贡献 +3 收起 理由
睦ちゃん她爹 + 2 + 3 + 3 鱼C有你更精彩^_^

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-3-5 18:49:16 | 显示全部楼层
沙发
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-3-5 19:47:35 From FishC Mobile | 显示全部楼层
我觉得可以用 itertools
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-3-5 19:51:18 From FishC Mobile | 显示全部楼层
学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-3-5 19:59:39 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-4-22 08:05:36 | 显示全部楼层
学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-4-22 16:12:14 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-21 11:33:01 | 显示全部楼层
k = 0
for x in range(5):
    for y in range(5):
        for z in range(5):
            if x != y and y != z and z != x:
                print(f'A: {x}, B: {y}, C: {z}', end = '    ')
                k += 1
                if k % 4 == 0:
                    print()
print(f'共有{k}种分法')
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-7-6 20:24:14 | 显示全部楼层
count=0
for i in range(5):
    for j in range(5):
        for z in range(5):
            if i != j and j != z and i != z:
                count+=1
                print(i,j,z,' count:', count)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-18 11:11:10 | 显示全部楼层
学习中...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-8-13 10:15:31 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-8-13 10:24:57 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-10-13 12:29:40 | 显示全部楼层
xixi
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-10-13 13:06:57 | 显示全部楼层
if __name__ == "__main__":
    print("A, B, C三人所选玩具方案:")
    [print(f"A: {a:2d}  B: {b:2d}  C: {c:2d}") for a in range(1, 6) for b in range(1, 6) for c in range(1, 6) if a != b != c != a]

# f"A: {a:2d}  B: {b:2d}  C: {c:2d}" f-string 字符串格式化
# a != b != c != a 如同 a != b and a != c and b != c
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-13 15:03:47 From FishC Mobile | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-10-21 11:35:22 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-10-21 18:16:47 | 显示全部楼层
看看学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-21 18:21:46 | 显示全部楼层
if __name__ == "__main__":
这句话的作用是什么?只是为了返回ture,执行下面的语句吗?那不加不是一样吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-5 17:20:29 | 显示全部楼层
for a in range(1,6):
    for b in range(1,6):
        for c in range(1,6):
            if a != b and b != c and a != c:
                print(a,b,c)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-21 14:50:03 | 显示全部楼层
1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-15 01:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表