Python 趣味百题

看到这个非常好的资源, 分享一下
这些题是跟语言无关的,你可以用任何其他语言实现。

声明: 源地址 : http://www.cheemoedu.com/exercise_list/

趣味整数

1) 不重复的3位数 ->易

  1. 问题描述:
    0 ~ 9这10个数字可以组成多少不重复的3位数?
  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

2) 水仙花数 ->易

1. 问题描述:
水仙花数是指一个n位数(n≥3),它的每个位上的数字的n次幂之和等于它本身。
例如:1 ^ 3+5 ^ 3+3 ^ 3=153。

求100 ~ 999之间所有的水仙花数。

2.参考源码:

#!/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

3) 完全数 ->中

1.问题描述:
完全数(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以内的完全数。

2.参考源码:

#!/usr/bin/env python

def 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 == n

for k in range(2, 10000):
    if isPerfectNumber(k):
        print k

4) 相亲数 ->中

1.问题描述:
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以内的相亲数。

2.参考源码:

#!/usr/bin/env python

def sumOfFactors(k):
    p = 1 
    q = k 
    s = 0 
    while p < q:
        if k % p == 0:
            s += p + q 
        p += 1
        q = k / p 

    if k == p * q and p == q:
        s += p

    return s - k 

def fun(start, end):
    for x in range(start, end):
        y = sumOfFactors(x)
        if x < y and sumOfFactors(y) == x:
            print x, y

fun(2, 100000)

5) 黑洞数 ->中

1.问题描述:
黑洞数又称陷阱数,是类具有奇特转换特性的整数。任何一个数字不全相同的整数,经有限“重排求差”操作,总会得到某一
个或一些数,这些数即为黑洞数。“重排求差”操作即把组成该数的数字重排后得到的最大数减去重排后得到的最小数。
举个例子,3位数的黑洞数为495.
简易推导过程:随便找个数,如297,3个位上的数从小到大和从大到小各排一次,为972和279,相减得693。按上面做法再做一次,得到594,再做一次,得到495,之后反复都得到495。

验证4位数的黑洞数为6174。

2.参考源码:

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

6) 勾股数 ->易

1.问题描述:
所谓勾股数,一般是指能够构成直角三角形3条边的3个正整数(a,b,c)。
即a²+b²=c²,a,b,cΣN

求1000以内的勾股数。

2.参考源码:

import math

for a in range(1, 1000):
    for b in range(a + 1, 1000):
        c = math.sqrt(a * a + b * b)
        if c > 1000:
            break
        if c.is_integer():
            print a, b, int(c)

7) 自守数 ->易

1.问题描述:
如果某个数的平方的末尾几位等于这个数,那么就称这个数为自守数。显然,5和6是一位自守数(5 * 5=25,6 * 6=36)。 25 * 25=625,76 * 76=5776,所以25和76是两位自守数。

求10000以内的自守数。

2.参考源码:

#coding:utf-8

# 1. 计算 n 的长度 l
# 2. 取n * n的后 l 位 t 
# 3. n == t ? 

for n in range(1, 10000):
    l = len(str(n))
    t = n * n % (10 ** l)
    if t == n:
        print n
#[n for n in range(1, 10000) if n * n % (10 ** len(str(n))) == n]

8) 3位反序数 ->中

1.问题描述:
所谓反序数,即有这样成对的数,其特点是其中一个数的数字排列顺序完全颠倒过来,就变成另一个数,如102和201,36和63等,简单的理解就是顺序相反的两个数,我们把这种成对的数互称为反序数。反序数唯一不可能出现以0结尾的数。

一个3位数各位上的数字都不相同,它和它的反序数的乘积是280021,这个3位数应是多少?

2.参考源码:

# a:(1-9), b:(0-9), c:(1-9)
# a != b != c
# a < c
for b in range(10):
    for a in range(1, 10):
        if a == b: continue
        for c in range(a + 1, 10):
            if c == b: continue
            t1 = 100 * a + 10 * b + c
            t2 = 100 * c + 10 * b + a
            if t1 * t2 == 280021: print t1, t2

趣味素数

1) 素数 ->中

1.问题描述:
素数(质数)指的是不能被分解的数,除了1和它本身之外就没有其他数能够整除。

求100以内的所有素数。

2.参考源码:

def isPrimeNumber(n, s):
    for k in s:
        if k * k > n: break
        if n % k == 0: return None
    return n

prime = []
for n in range(2, 100):
    res = isPrimeNumber(n, prime)
    if res: prime.append(res)

print prime

2) 孪生素数 ->中

1.问题描述:
若两个素数之差为2,则这两个素数就是孪生素数。

编写程序找出1 ~ 100之间的所有孪生素数。

2.参考源码:

#coding:utf-8

#筛法找素数: 
# 1. 建立一张表,用True,False标识一个数是否是素数。
# 2. 找到一个素数p,然后把p的倍数都标记成非素数。
# 3. 查表检测p + 1, 如果非素数检测下一个, 是素数执行1的操作

pt = [True] * 100
res = []

for p in range(2, 100):
    if not pt[p]: continue
    res.append(p)
    for i in range(p * p, 100, p):
        pt[i] = False

for i in range(1, len(res)):
    if res[i] - res[i-1] == 2:
        print res[i-1], res[i]

3) 金蝉素数 ->中

1.问题描述:
某古寺的一块石碑上依稀刻有一些神秘的自然数。
专家研究发现:这些数是由1,3,5,7,9这5个奇数字排列组成的5位素数,同时去掉它的最高位与最低位数字后的3位数还是素数,同时去掉它的高二位与低二位数字后的一位数还是素数。因此人们把这些神秘的素数称为金蝉素数,喻意金蝉脱壳之后仍为美丽的金蝉。

试求出石碑上的金蝉素数。

2.参考源码:

#coding:utf-8

# 1. 生成 1,3,5,7,9 全排列, 每种排列是一个元组
# 2. 元组转换成数字 (例: 13579,357,159)
# 3. 检测3个数字是素数,如全是素数则是金蝉数

import math
def isPrimeNum(n):
    for k in range(2, int(math.sqrt(n) + 1)):
        if n % k == 0: 
            return False
    return True

from itertools import permutations
for p in permutations([1,3,5,7,9], 5):
    # (3,5,7), (1,5,9), (1,3,5,7,9) 
    for l in (p[1:-1], p[::2], p):
        s = reduce(lambda x, y: 10 * x + y, l)
        if not isPrimeNum(s): 
            break
    else:
        print p 

4) 可逆素数 ->中

1.问题描述:
编写程序找出1 ~ 900之间的所有可逆素数(可逆素数是指一个素数的各位数值顺序颠倒后得到的数仍为素数,如113、311)。

2.参考源码:

#coding:utf-8

# 解题步骤:
#    1. 用筛法找到900以内素数表
#    2. 迭代表内所有数,是素数的检测它的反序数是否是素数。
#    3. 2条件为真,打印这俩个素数。

def getPrimeTable(n):
    pt = [True] * n

    for p in range(2, n):
        if not pt[p]: continue
        for i in range(p * p, n, p):
            pt[i] = False

    return pt

pt = getPrimeTable(900)
for p in range(10, 900):
    if not pt[p]: continue
    q = int(str(p)[::-1])
    if p != q < 900 and pt[q]:
        pt[q] = False 
        print p, q

5) 回文素数 ->中

1.问题描述:
所谓回文素数是指,对一个整数n从左向右和从右向左读结果值相同且是素数,即称为回文素数。

求不超过1000的回文素数。

2.参考源码:

#!/usr/bin/env python

import math
def isPrimeNumber(num):
    i = 2
    x = math.sqrt(num)
    while i < x:
        if num%i == 0:
            return False
        i += 1
    return True

def Reverse(num):
    rNum = 0
    while num:
        rNum = rNum*10 + num%10
        num /= 10
    return rNum

def RPrimeNumber(num):
    arr = []
    i = 2
    while i < num:
        if isPrimeNumber(i) and i == Reverse(i):
            arr.append(i)
        i += 1
    return arr

print RPrimeNumber(1000)

6) 平方回文素数 ->中

1.问题描述:
素数的平方是回文,比如11 * 11=121。

求不超过1000的平方回文素数。

2.参考源码:

#!/usr/bin/env python

import math
def isPrimeNumber(num):
    i = 2
    x = math.sqrt(num)
    while i < x:
        if num%i == 0:
            return False
        i += 1
    return True

def Reverse(num):
    rNum = 0
    while num:
        rNum = rNum*10 + num%10
        num /= 10
    return rNum

def RPrimeNumber(num):
    arr = []
    i = 2
    while i < num:
        if isPrimeNumber(i) and i**2 == Reverse(i**2):
            arr.append(i)
        i += 1
    return arr

print RPrimeNumber(1000)

7) 梅森尼数 ->中

1.问题描述:
法国数学家梅森尼对这类形如2 ^ n-1的素数特别感兴趣,做过很多有意义的工作,后人把此类数命名为梅森尼数。
已经证明了,如果2 ^ n-1是素数,则幂指数n必须是素数,然而,反过来并不对,当n是素数时,2 ^ n-1不一定是素数。例如,人们已经找出2 ^ 11-1是一个合数,23可以除尽它,2 ^ 23-1是一个合数,47可以除尽它。

编程找出指数n在(2,50)中的梅森尼数。

2.参考源码:

#!/usr/bin/env python

import math
def isPrimeNumber(num):
    i = 2
    x = math.sqrt(num)
    while i < x:
        if num%i == 0:
            return False
        i += 1
    return True

def masonNumber(num):
    arr = []
    for i in xrange(2, num + 1):
        if isPrimeNumber(i) and isPrimeNumber(2**i - 1):
            arr.append(2**i - 1)
    return arr

print masonNumber(50)

8) 哥德巴赫猜想 ->中

1.问题描述:
众所周知,哥德巴赫猜想的证明是一个世界性的数学难题,至今未能完全解决。我国著名数学家陈景润为哥德巴赫猜想的证明作出过杰出的贡献。
所谓哥德巴赫猜想是说任何一个大于2的偶数都能表示成为两个素数之和。

编写程序,验证指定范围内哥德巴赫猜想的正确性,也就是近似证明哥德巴赫猜想。

2.参考源码:

#!/usr/bin/env python

def isPrimeNumber(n, s):
    for k in s: 
        if k ** 2 > n: break
        if n % k == 0: return False
    return True

def fun():
    s = [3]
    for n in xrange(6, 100000, 2):
        f = False
        for k in s:  
            t = n - k
            if t < k:
                break
            if isPrimeNumber(t, s):
                #print '%s = %s + %s' % (n, k, t)
                if t > s[-1]: s.append(t)
                f = True
                break
        if not f: raise Exception

fun()

9) 等差素数数列 ->中

1.问题描述:
类似7、37、67、97、107、137、167、197,这样由素数组成的数列叫做等差素数数列。素数数列具有项数的限制,一般指素数数列的项数有多少个连续项,最多可以存在多少个连续项。

编程找出100以内的等差素数数列。

2.参考源码:

#coding:utf-8

# 解题步骤:
#    1. 筛法找到100所有素数
#    2. 对于素数list内素有俩两组合,构造等差数列a0, a1项
#    3. 计算出a2, 查表判断a2是否是素数,是素数则能构成素数等差序列, 计算a3...

def findAllPrime(n):
    pt = [True] * n
    prime = []

    for p in range(2, n):
        if not pt[p]: continue
        prime.append(p)
        for i in range(p * p, n, p):
            pt[i] = False

    return prime, pt

prime, pt = findAllPrime(100)
print prime

for i in range(len(prime)):
    for j in range(i + 1, len(prime)):
        a0, a1 = prime[i], prime[j]
        an = a1 + a1 - a0
        s = []
        while an < 100 and pt[an]:
            s.append(an)
            an += a1 - a0
        if s:
            print [a0, a1] + s

趣味图形

1) 回型矩阵 ->中

1.问题描述:

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值