第一题:不重复的三位数
0~9这10个数字可以组成多少不重复的3位数?
程序思路:
思路1.用range()函数穷举所有三位数,然后过滤其中有两位或者三位相同的数
思路2.运用排列组合的思想直接计算出个数
尝试解题:
#-*-coding:utf-8-*-#0~9这10个数字可以组成多少不重复的3位数?#方法1list_num = [a*100+b*10+c for a in range(1,10) for b in range(0,10) if b!=a for c in range(0,10) if c!=b and c!=a]#方法2list_num = [i for i in range(100,1000) if i//100 != i//10%10 and i//100!= i%10 and i//10%10 != i%10]print(list_num)print(len(list_num))
思路2方法就不做了,那就是纯粹的数学计算了。
官方解题参考代码:
#coding:utf-8 # a:1-9, b:0-9, c:0-9 l = range(10) count = 0 for a in l[1:]: for b in l: if a == b: continue #过滤a == b for c in l: if c != a and c != b: #过滤a == c, b == c print a, b, c count += 1 print 'count:', count
给出的参考答案就是通过排列组合的思想解题的,不过不是和我一样想的直接计算出符合要求的数量。
第二题:水仙花数(自幂数)
水仙花数是指一个n位数(n≥3),它的每个位上的数字的n次幂之和等于它本身。
例如:1^3+5^3+3^3=153。
求100~999之间所有的水仙花数。
水仙花数-百度百科
解题思路:
和上一题自己的解法相似,穷举所有三位数,然后对三位数进行分解,然后计算是否符合要求。
第一题代码稍行改造即可:
list_num = []for i in range(100,1000): list_x = [] x = i while x > 0 : a = x % 10 list_x.append(a) x = int(x/10) if list_x[0] ** 3 + list_x[1] ** 3 + list_x[2] ** 3 == i: list_num.append(i) else: passlist_len = len(list_num)print(list_num)
官方参考源码:
#!/usr/bin/env python def isArmstrongNumber(n): a = [] t = n while t > 0: a.append(t % 10) t /= 10 k = len(a) return sum([x ** k for x in a]) == n for x in range(100, 10000): if isArmstrongNumber(x): print x
思路相同,使用了一个列表推导使代码更加简洁易读,值得学习
#-*-coding:utf-8-*-list_num = []for i in range(100,1000): list_x = [] x = i while x > 0 : a = x % 10 list_x.append(a) x = int(x/10) k = len(list_x) if sum(m ** k for m in list_x) == i: #if list_x[0] ** 3 + list_x[1] ** 3 + list_x[2] ** 3 == i: list_num.append(i) else: passlist_len = len(list_num)print(list_num)
第三题:完全数
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。例如,第一个完全数是6,它有约数1、2、3、6,除去它本身6外,其余3个数相加,1+2+3=6。第二个完全数是28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。
编程求10000以内的完全数。
啊完全数,我感觉我与欧拉,梅森等数学大师又近了一步。
解题思路:
思考五分钟后完全没有思路,怎么确定一个数的所有真因子呢?百度一下看看是不是有什么模块有类似的函数吧....
没找到模块,不过找到了三行代码
shu=10000result=[a for a in range(1,shu+1) if shu%a==0]print(result)
(要不说Python牛逼,用c的话没有现成函数怎么也得几十行吧。)
好那现在可以尝试编写代码了
list_num = []for i in range(1,10000): if sum([ a for a in range(1,i) if i % a == 0]) == i: list_num.append(i)print(list_num)
五行代码....py天下第一!!!py天下第一!!!py天下第一!!!
#!/usr/bin/env pythondef isPerfectNumber(n): a = 1 b = n s = 0 while a
思路相似,但用列表推导更简单
第四题:相亲数
220的真因数之和为1+2+4+5+10+11+20+22+44+55+110=284
284的真因数之和为1+2+4+71+142=220
毕达哥拉斯把这样的数对A、B称为相亲数:A的真因数之和为B,而B的真因数之和为A。
求100000以内的相亲数。
解题思路:
构建列表,遍历列表,求x的真因数并求和记作a,然后对a求真因数之和b,判断x?=b。
尝试解题:
list_num = []for i in range(2,10000): x = sum([a for a in range(1,i) if i % a == 0]) y = sum([b for b in range(1,x) if x % b == 0]) if i == y: list_num.append((i,x))print(list_num)#运行结果:[(6, 6), (28, 28), (220, 284), (284, 220), (496, 496), (1184, 1210), (1210, 1184), (2620, 2924), (2924, 2620), (5020, 5564), (5564, 5020), (6232, 6368), (6368, 6232), (8128, 8128)]
可以看出有重复的,有完全数和本身的
可以考虑用集合,集合是无序的而且重复元素不出现
list_num = []for i in range(2,10000): x = sum([a for a in range(1,i) if i % a == 0]) y = sum([b for b in range(1,x) if x % b == 0]) if i == y and x != y and (i,x) : m = list_num.append(m)print(list_num)#[, , , , , , , , , ][Finished in 7.7s]
列表还是有重复,等回头再学习一下再修改
第五题:黑洞数
黑洞数又称陷阱数,是类具有奇特转换特性的整数。任何一个数字不全相同的整数,经限“重排求差”操作,总会得到某一个或一些数,这些数即为黑洞数。“重排求差”操作即把组成该数的数字重排后得到的最大数减去重排后得到的最小数。
举个例子,3位数的黑洞数为495.
简易推导过程:随便找个数,如297,3个位上的数从小到大和从大到小各排一次,为972和279,相减得693。按上面做法再做一次,得到594,再做一次,得到495,之后反复都得到495。
验证4位数的黑洞数为6174。
解题思路:
对所有四位数进行如下操作:将数字分解存入列表,列表排序,组合成数字,然后大小相减,对比6174相等则验证成功
列表排序相关函数:
#将列表中元素反转排序 >>> x = [1,5,2,3,4] >>> x.reverse() >>> x [4, 3, 2, 5, 1] #此函数方法对列表内容进行正向排序,排序后的新列表会覆盖原列表(id不变),也就是sort排序方法是直接修改原列表list排序方法。 >>> a = [5,7,6,3,4,1,2] >>> a.sort() >>> a [1, 2, 3, 4, 5, 6, 7] #即可以保留原列表,又能得到已经排序好的列表sorted()操作方法如下: >>> a = [5,7,6,3,4,1,2] >>> b = sorted(a) >>> a [5, 7, 6, 3, 4, 1, 2] >>> b [1, 2, 3, 4, 5, 6, 7]
本来根据我的思路大致写了一下代码如下
def number_x(num,other): list_num = [] while num > 0: a = num % 10 num = int( num / 10 ) list_num.append(a) if other == 'min': list_min = sorted(list_num) num_min = list_min[0] + list_min[1] * 10 + list_min[2] * 100 + list_min[3] * 1000 return num_min elif other == 'max': list_min = sorted(list_num) list_max = sorted(list_min) num_max = list_max[0] + list_max[1] * 10 + list_max[2] * 100 + list_max[3] * 1000 return num_max for i in range(1000,10000): x = i a = 0 while x != 6174: x_min = number_x(x,'min') x_max = number_x(x,'max') x = x_max - x_min a += 1 if a == 1000: print('fail',i) break print('success')
运行出错先不说,发现自己思路很死,想到一个用while取各位的数字存到列表就用到死,重排列数字之后组合成一个数字的时候用的竟然只想到了最蠢的方法,简直愚蠢之极。
然后报错问题,报错是列表超出范围了,重新走一下流程之后发现第一个数1000重组之后的数字是1000和1,1只有1位数可不超范围了,再相减之后成了999,变成一个三位数了???成了求三位数的黑洞数了?而且999三个数字完全相同没有黑洞数。只能说明题意有问题。百度一下发现应该是相减之后不足四位前面应该添零,大致意思是这样
1000-0001 = 0999
9990-0999 = 8991
9981-1899 = 8082
8820-0288 = 8532
8532-2358 = 6174
问题变得复杂了好多,得考虑0的问题。作为练习的前几个题不应该这么麻烦才是,先看看官方给出的解题思路。
def fun(n): a = [int(c) for c in str(n)] a.sort() s1 = reduce(lambda x, y: 10 * x + y, a[::-1]) s2 = reduce(lambda x, y: 10 * x + y, a) return n if s1 - s2 == n else fun(s1 - s2) res = fun(6294) print 'res : ', res #这是python2.x版本的代码 #查了一下3.x好像是reduce()从全局函数移除了,添加到了fucntools模块里引用要用 from functools import reduce
好吧,老师解题也不走心,完全没考虑我这么多,,,
题意是要验证四位数的黑洞数,这个只能验证一个数不说还没考虑0的情况。
不过老师用的方法就比我好多了,这就参考老师的代码修改一下我的程序吧
突然灵光一闪,将整数操作变为字符串操作,需要相减时再int,相减之后再与6174比较,如果不同再返回字符串,如果返回的字符串长度不到4在用字符串'0'+'返回的字符串',这样循环操作不就比直接操作整数型数字简单了么。
from functools import reduce def fun(str_n): x = ['1111','2222','3333','4444','5555','6666','7777','8888','9999'] if str_n in x: return str_n elif str_n == '6174': return 'succes' else: a = [int(c) for c in str_n] a.sort() s1 = reduce(lambda x, y: 10 * x + y, a[::-1]) s2 = reduce(lambda x, y: 10 * x + y, a) m = s1 - s2 s = '0' * (4 - len(str(m))) + str(m) fun(s) list_fail = [] for i in range(1000,10000): if fun(str(i)) == 'succes': pass else: list_fail.append(i) print (list_fail)
不知道怎么老是出问题好气啊
领取专属 10元无门槛券
私享最新 技术干货