Python練習:趣味百題
今天發現了一個學習編程的網站:奇貓學院
網站中列出了一百道適合練習編程思維的小題目:趣味百題-奇貓學院
第一題:不重複的三位數
0~9這10個數字可以組成多少不重複的3位數?
程序思路:
思路1.用range()函數窮舉所有三位數,然後過濾其中有兩位或者三位相同的數
思路2.運用排列組合的思想直接計算出個數
嘗試解題:
#-*-coding:utf-8-*-#0~9這10個數字可以組成多少不重複的3位數?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] != list_x[1] and list_x[0] != list_x[2] and list_x[1] != list_x[2]: #判斷是否重複 list_num.append(i) else: passlen_list = len(list_num) #得到list的長度,即有多少個滿足的數print(list_num)print(可以組成,len_list,個不重複的數字)
思路2方法就不做了,那就是純粹的數學計算
官方解題參考代碼:
#coding:utf-8# a:1-9, b:0-9, c:0-9l = range(10)count = 0for 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 += 1print 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 pythondef 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]) == nfor 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 < b: if n % a == 0: s += a + b a += 1 b = n / a if a == b and a * b == n: s += a return s - n == nfor k in range(2, 10000): if isPerfectNumber(k): print k
思路相似,但用列表推導更簡單
第四題:相親數
220的真因數之和為1+2+4+5+10+11+20+22+44+55+110=284284的真因數之和為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 = {i,x} list_num.append(m)print(list_num)#[{220, 284}, {220, 284}, {1184, 1210}, {1184, 1210}, {2924, 2620}, {2924, 2620}, {5564, 5020}, {5020, 5564}, {6232, 6368}, {6368, 6232}][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_maxfor 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 reducedef 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)
不知道怎麼老是出問題好氣啊
推薦閱讀:
※Python 家族有多龐大
※python字典如何:按值排序,在值相等的情況下再按鍵排序?
※史上最全的python滲透測試工具合集
※python 中try except 中如果出錯了。怎麼重新執行?
※哪些技術讓你有一種 「Orz, 還有這種操作」 ?