【Pyhon 009讲心得体会】【摸球和水仙花数 】
本帖最后由 heidern0612 于 2019-7-28 10:59 编辑写的内容都是自我思考的过程,难免有疏漏,有错误的地方欢迎广大鱼油给予指正!
学到这一课,眼前一黑,wakao,这么难,有木有?
1、学到了for循环:for i in range(0,10,2)
0到10是循环的范围,不包括10,所以其实是0到9循环的范围。
2表示的是步进,表示隔一个一计算。就像上楼梯,10层的楼梯,如果你两个两个(步进2)的上,五次就上完了。
2、break 和continue
break是跳出整个的大循环,而continue跳出的是当次循环剩余的语句,不影响后面的继续循环。
所以continue我理解为更像是一个过滤器,类比filter,他把不能执行的东西continue了,把能执行的东西留了下来。
例:
#coding=gbk
var = "Apython"
for i in var:
if i == "A" :
continue
else:
print(i,end = "")
输出的结果是python,把"A"过滤掉了,好神奇,有木有?
break和continue相同点都在于不执行下面的语句,区别是break就像是癌症,坏了就没办法循环再开始,而continue就像小感冒类似,当前坏了还可以再从头循环。
3、密码验证问题:
1、小甲鱼老师小立了一个flag,用来判断密码输入次数;
2、in 成员操作符,用于关键字判断'*'是否在密码内,是的话,continue过滤掉,跳回循环开始输入密码阶段;
3、密码输入正确,程序break跳出。
此题主要就是考察in成员操作符和continue的作用,很多同学学了却始终没用过continue或in成员操作符(例如我),不是不懂,而是不知道该什么时候用,想办法跟游戏关联一下,你就会发现很多用途咯。
4、摸球的问题:(此球非彼球……)
卧槽,看着好复杂有木有?一点也不明白有木有?谁第一眼看着这种for循环套for循环的语句都懵逼。
其实按照正常人思维推导一下,感觉似乎没有想象的那么难。
只是简单的嵌套三层的for循环,一起分析一下:
首先是red的for循环:
红球数量是0的时候,有几种组合呢?
红球*0 + 黄球*2 + 绿球*6
红球*0 + 黄球*3 + 绿球*5
红球为零的情况下,为了达到摸出的球有8只,只有这两种组合。
红球数量为1的时候呢?
红球*1 + 黄球*1 + 绿球*6
红球*1 + 黄球*2 + 绿球*5
红球*1 + 黄球*3 + 绿球*4
可以从上面看出来,在红球是1的时候,黄球就已经几乎循环了一个遍了,继续:
红球*2 +黄球*0 + 绿球*6
红球*2 + 黄球*1 + 绿球*5
红球*2 + 黄球*2 + 绿球*4
红球*2 + 黄球*3 + 绿球*3
可以看出,红球是2的时候,为了达到8个球的总数,黄球已经可以为零了,话说就是摸出两个红球的时候,黄球就已经从0到3遍历了一遍了。继续:
红球*3 + 黄球*0 + 绿球*5
红球*3 + 黄球*1 + 绿球*4
红球*3 + 黄球*2 + 绿球*3
红球*3 + 黄球*3 +绿球*2
至此,红球和黄球都完成了自身的遍历。红球和黄球的方式推完了,下面我们算绿球的:
绿球为零的时候,红球和黄球都算上(红球、黄球都各只有三个),为了摸出8个球,不够,差俩。
绿球为一的时候,红球和黄球都算上,不够,差一个。
绿球为二的时候呢?,好熟悉,不就是推导黄球遍历的时候 红球*3 + 黄球*3 + 绿球*2 的时候嘛!
绿球为三呢?也找到了,绿球一直到为六(只有六个),也都在上面找到了。
所以,算一算方法,一共是13种,是不是跟答案一样呢?
实际上我不推荐这种笨方法,但是这种笨方法对理解此题有效果。
可以从推算中看出,实际上我们先遍历了红球的从零到3的变化,也就是for i in range(0,4)
其次,红球遍历完了,我们遍历的是黄球(0,4),然后是绿球(2,7)。
所以大循环上,先套上red,red循环0的时候,下面yellow循环2,再下面绿的循环6.
后套上yellow,再套上green.(I don't have any green...)
就把这个题理解了。
5、水仙花数
为啥最后说捏?因为我当时理解这个很费劲。。虽然自己用别的方法做出来了,但是感觉没老师那么精简,另外这个或许也是这节课程里面最难的,分析不易。
先贴上我自己的做法
for i in range(1,10):
for j in range(0,10):
for k in range(0,10):
if i*100+j*10+k==i*i*i+j*j*j+k*k*k:
print(i*100+j*10+k)
类似还有以下这种:
for i in range(100,999):
a=i//100
b=(i%100)//10
c=i%10
if i==a**3+b**3+c**3:
print(i)
小甲鱼老师的办法现在我用带入法仔细分析下:
for i in range(100, 1000):
sum = 0
temp = i
while temp:
sum = sum + (temp%10) ** 3
temp //= 10 # 注意这里要使用地板除哦~
if sum == i:
print(i)
首先第一行,for i in range(100,1000)这个基本都比较好理解吧?
0 赋值给sum,(sum后面其实就是水仙花三者平方相加的和;);temp = i ,也就是for 循环后100到999所有的值
while这里:
第一次循环:
我们首先拿153测试下,当 i循环到153时,temp 也是153.
sum = 0+(153%10)**3;153%10余数是3,也就是3的3次方,结果是27,也就是此时的sum = 27;
temp // 10 = 153//10 = 15 ; 地板除,不要余,其实就相等150 /10 的结果。
此时temp == 15,不满足temp == 0时while跳出循环,所以循环继续;
第二次循环:
sum = 27(上个sum的值) +(15%10)**3 ;15%10的余数是5,也就是5的3次方,结果是125;此时sum = 125 +27 =152;
temp //10 , 也就是15//10;地板除,不要余数;相等于10//10 = 1
此时temp == 1,不满足temp ==0时while跳出循环,循环继续。
第三次循环:
sum = 152(上个sum的值) +(1%10)**3 ;1%10的余数是1,也就是1的3次方,结果是1;此时sum = 152+1 = 153;
temp //10 , 也就是1//10;地板除,不要余数; 数值为0。
此时temp == 0,满足temp ==0时while跳出循环,循环中断。
此时判断if语句,如果sum和值相等,就打印i。此时sum=153, temp在未开始循环时也是153,i的值一开始我们测试的就是153.所以两者相等,打印出来。
这种简单的利用地板除和求余除的办法我脑子愚笨,没想出来,只有大神才用这种简单的办法,我用上面那两种方法就挺好,不过能近距离接触大神的用法,分析下也挺好的。
简单用370再验证一下:
1、370%10 余0 ,sum = 0, temp =370//10 = 37 ;
2、37%10 余7,sum =0+ 7**3 =343, temp = 37//10 = 3
3、3%10 余3, sum =343+ 3**3 = 370, temp = 3//10 = 0
temp为False(即temp为0)跳出循环。
sum = i =370,所以370也是个水仙花数。
至于为什么 1%10余1,或1//10余0,请自行百度或者拿壳自己做下记住就可以了。
print(1//10)
print(1%10)
数学实在太差了,看的还是云里雾里 temp123为例开始;sum为零,然后第一次运行
sum=sum+-----temp为123%余数相当于3**3
temp=地板除那行变成12
返回sum行,3**3加2**3
再回到地板除变成1
再返回sum 结果就是3**3+2**3+1**3
然后返回temp=each,数字增大一个序数直至153
运行的结果其实就是3**3+5**3+1**3
然后进入打印第一次,然后再返回到temp=each--------------
摸球的问题一直没看懂,结果看下你的解题思路,哇靠,原来这么简单的啊~~ 做练习时也感受到了这章的难度:
1. 密码验证程序,没意识到 in 是个操作符可以灵活运用,以为只能搭配for使用,走了弯路
2. 水仙花数写得和楼主第二个程序一样,范例代码中也没意识到temp//= 10以后不为零继续循环,所以完全没看懂整个程序
3. 三色球自己还往排列组合上去想,审题不清?绿球是range(2,7)也是自己要绕一圈才能想明白的点 可以说是很详细的解析了,
虽然办法笨, 一步一步分析, 一步一步验证,但是真的很管用
谢谢楼主大大
也谢谢楼主大大回复解答我的求助帖 Judie 发表于 2019-2-16 09:03
可以说是很详细的解析了,
虽然办法笨, 一步一步分析, 一步一步验证,但是真的很管用
谢谢楼主大大
表示 虽然能看懂解析,但是小甲鱼的方法我还是用不出来啊/捂脸 感谢分享!之前这里也卡住了半天 感谢分享! 感谢分享 想问一下为什么要把 i 的值赋给 temp 变量, 不能直接用 i 进行运算吗 小甲鱼老师为什么这么大神 哪里设定有temp ==0时while跳出循环,循环中断啊?
Judie 发表于 2019-2-16 09:03
可以说是很详细的解析了,
虽然办法笨, 一步一步分析, 一步一步验证,但是真的很管用
谢谢楼主大大
这里看到大佬了哈哈哈哈{:10_256:} 西瓜板栗 发表于 2020-3-22 14:30
这里看到大佬了哈哈哈哈
哈哈哈哈哈 你好啊呀~
你可以去看看我的学习笔记呀!
这是淘帖
朱迪的Python学习笔记
https://fishc.com.cn/forum.php?mod=collection&action=view&ctid=1618 看大神笔记一下子就理解了
作为真·零基础学员,正打算上来问这节课的作业的时候就看到课代表heidern0612的答疑,真的超感动耶!
摸球问题课代表说得非常详细,本零很容易就理解了;但水仙花数那道题,本零看课代表的笔记还是有些吃力。
我水仙花数那道题就是用的100*a + 10*b + c的笨办法。
小甲鱼老师的答案对我来说其实有3个难点:
第一个是不知道temp //= 10的含义。对,我零基础到完全不知道有这个用法,并且没跟+= 1或-= 1联系起来。
第二个是while temp有个隐藏含义,就是temp == 0时,while循环会停止。因为while 0和while False是一个效果,这个小甲鱼老师其实讲过,我给忘了。
第三个就是sum的意思。经课代表分析,才明白sum就是“个”“十”“百”这三位上的3个数字的立方和。
可是第三个问题实在是知其然不知其所以然。为什么用sum可以表示3个数字的立方和?前面的i = 100到152的时候,sum到底发生了什么?
对于这个问题,大佬们可能不屑于了解,反正for循环每轮开头sum就归零了管那么多干啥。
但是对于本零基础学员来说,这么流弊的写法的诞生过程太令人好奇了。
于是本零就决定,吸取三色球的穷举精神,从故事的源头开始探究……
for循环的第一轮循环开始,i = 100,sum = 0,temp = 100:
①sum = sum + (100%10) ** 3,所以新sum == 0,新temp == 10,即temp != 0,因此while循环继续(值得注意的是,外层的for循环仍在第一轮,此时i仍然是100);
②sum = sum + (10%10) ** 3,所以新新sum依然== 0,新新temp == 1,仍!= 0,因此while循环继续(此时i仍然是100);
③sum = sum + (1%10) ** 3,1%10 == 1(1除以10商0余1这个大家应该都知道),最新sum == 1啦,最新temp由于1//10 == 0(地板除法嘛,0.1向下取整可不就是0),while循环就此结束。
所以这个时候,i = 100的情况就讨论完了。
for循环的第一轮循环也告一段落,现在开始第二轮咯,i = 101,sum = 0,temp = 101:
①sum = sum + (101%10) ** 3,所以新sum == 1,新temp == 10,即temp != 0,因此while循环继续;
②sum = sum + (10%10) ** 3,所以新新sum依然== 1,新新temp == 1,仍有!= 0,因此while循环继续;
③sum = sum + (1%10) ** 3,最新sum == 2,最新temp == 0,while循环就此结束。
i = 101的情况就讨论完了。
这两轮for循环考察完,我们应该就能比较容易理解sum为什么是三个数字的立方和了:
①i是三位数,每轮for循环的temp都是取的i的值,因此每轮for循环最开始的temp也都是三位数;
②每轮for循环下的while循环都不止一次;
③第一轮while循环得到得到的新sum,其实是三位数temp的个位数的立方,毕竟新temp(即temp%10)就是取原temp这个三位数除以10的余数嘛,三位数除以10,余数当然就是这个三位数的个位数啦;
④第一轮while循环最后对原temp做的地板除法,其实是在个位数确定之后,为了刨除个位数的影响,在下一轮循环中进一步对原temp的十位数做讨论进行的准备(这句话不好理解,可以直接跳到下一条);
⑤这个地板除法得到的新temp就是取原temp的百位数和十位数组成的两位数,即原temp的百位数变成了新temp的十位数,原temp的十位数则变成了新temp的个位数,所以第二轮while循环中(新temp%10)是取新temp这个两位数除以10的余数,得到的余数是新temp的个位数,也就是原temp的十位数了;
⑥因此,第二轮while循环中得到的新新sum,则是第一轮得到的新sum(原temp个位数的立方)与原temp的十位数的立方的和;
⑦同理,第三轮while循环中得到的最新sum,就是新sum+新新sum+原temp的百位数的立方== temp的个位数、十位数、百位数的立方和;
⑧while循环到第三轮的时候,到temp //= 10这一步,都会成为原temp的百位数对10做地板除法,百位数是1到9的数字,对10做地板除法必然为0,意思就是while循环到第三轮的时候一定会结束,不会有第四轮;
⑨至此,我们明白每轮for循环下面的while循环一定且仅会循环三轮,这三轮的成果就是第三轮得到的最新的sum值,它是原temp的百位数、十位数、个位数的立方和;
⑩原temp是不是水仙花数,就是靠小甲鱼老师代码的第7、8行判断的,是水仙花数,那依照概念,原temp(也就是本轮for循环的i)的百位数、十位数、个位数的立方和与原temp自身相等,也就应该有最新sum==原temp==i,满足这个条件,i就被打印出来;不满足,本轮for循环的i就不是水仙花数,就应该开始下一轮for循环,根据range序列开始对新的i进行判断。遍历(本零其实不知道“遍历”能不能这么用哈)完了range里的所有i,所有的水仙花数就被找出来了。
以上就是本零总结的学渣笔记,啊写的时候觉得很清楚,怎么写完了自己读一遍还是觉得好难懂QAQ
唉不管了,希望能给其他学渣带来帮助吧,大佬们请一笑而过啦~ 谢谢,因为你提供了其他的思路可以解决这个问题 楼主可以的{:10_257:} 本帖最后由 老西医学煸橙 于 2020-5-27 00:04 编辑
不看老哥的笔记,我还在水仙花里卡着,现在懂了,非常感谢!
还有中间回帖的“dgfzyr”兄,也把甲鱼佬的代码与数学算式的联系清楚写出了,感谢
页:
[1]
2