Python 趣味百题

  • 趣味整数
    • 1 不重复的3位数 -易
    • 2 水仙花数 -易
    • 3 完全数 -中
    • 4 相亲数 -中
    • 5 黑洞数 -中
    • 6 勾股数 -易
    • 7 自守数 -易
    • 8 3位反序数 -中
  • 趣味素数
    • 1 素数 -中
    • 2 孪生素数 -中
    • 3 金蝉素数 -中
    • 4 可逆素数 -中
    • 5 回文素数 -中
    • 6 平方回文素数 -中
    • 7 梅森尼数 -中
    • 8 哥德巴赫猜想 -中
    • 9 等差素数数列 -中
  • 趣味图形
    • 1 回型矩阵 -中
    • 2 九九乘法表 -易
    • 3 杨辉三角 -易
  • 数学问题
    • 1 天平秤物 -难
    • 2 黑色星期五 -易
    • 3 存钱问题 -中
    • 4 赛场统分 -中
    • 5 肇事车辆 -中
    • 6 分糖果 -中
    • 7 平分七框鱼 -中
  • 趣味方程
    • 1 百鸡百钱 -中
    • 2 楼梯台阶 -中
    • 3 换硬币 -中
    • 4 求saaaaaaaaa的值 -中
    • 5 鸡兔同笼 -中
    • 6 巧算年龄 -易
    • 7 五家共井 -中
    • 8 三色球问题 -中
  • 趣味分数
    • 1 最大公约数 -易
    • 2 最小公倍数 -易
    • 3 分数比较 -中
    • 4 分数求和 -中
    • 5 埃及分数式 -中
    • 6 分数数列 -中
    • 7 猴子分桃 -中
  • 趣味猜想
    • 1 角谷猜想 -易
    • 2 回文数 -易
    • 3 卡布列克常数 -易
    • 4 剩余定理 -中
    • 5 尼科彻斯定理 -中
    • 6 马踏棋盘 -难
  • 逻辑推理
    • 1 斐波那契数列 -易
    • 2 汉诺塔问题 -难
    • 3 年龄问题 -易
    • 4 谁在说谎 -中
    • 5 谁家孩子跑得最慢 -中
    • 6 猴子爬山 -中
    • 7 兔子产仔 -中
    • 8 舍罕王赏麦 -中
  • 趣味变幻
    • 1 分解质因数 -易
    • 2 乘式还原 -易
    • 3 除式还原 -易
    • 4 奇数幻方 -中
    • 5 泊松分酒 -中
    • 6 猜牌术 -中
    • 7 邮票组合 -中
    • 8 整数拆分 -中
  • 趣味游戏
    • 1 掷筛子 -中
    • 2 发扑克牌 -中
    • 3 24点 -难
    • 4 常胜将军 -中
    • 5 抢30 -中
    • 6 过桥游戏 -中
    • 7 生命游戏 -中
  • 趣味问题
    • 1 双色球 -易
    • 2 金额转换 -中
    • 3 尾数前移 -易
    • 4 高斯八皇后 -难
    • 5 找假币 -中
    • 6 窃贼问题 -中
    • 7 三色棋 -中

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

声明: 源地址 : 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.问题描述:
打印回型矩阵如图:
1 2 3 4 5 6 7 8
28 29 30 31 32 33 34 9
27 48 49 50 51 52 35 10
26 47 60 61 62 53 36 11
25 46 59 64 63 54 37 12
24 45 58 57 56 55 38 13
23 44 43 42 41 40 39 14
22 21 20 19 18 17 16 15

2.参考源码:

#!/usr/bin/env python

def snakeNum(n):
    a = [[0 for i in range(n)] for j in range(n)]

    p = 0
    q = n - 1
    t = 1
    while p < q:
        for i in xrange(p, q):
            a[p][i] = t
            t += 1
        for i in xrange(p, q):
            a[i][q] = t
            t += 1
        for i in xrange(q, p, -1):
            a[q][i] = t
            t += 1
        for i in xrange(q, p, -1):
            a[i][p] = t
            t += 1
        p += 1
        q -= 1
    if p == q: a[p][p] = t
    for i in range(n):
        print a[i]

snakeNum(8)

2) 九九乘法表 ->易

1.问题描述:

打印乘法表如图:
1*1=1
2*1=2   2*2=4
3*1=3   3*2=6      3*3=9
4*1=4   4*2=8      4*3=12    4*4=16
5*1=5   5*2=10    5*3=15    5*4=20     5*5=25
6*1=6   6*2=12    6*3=18    6*4=24     6*5=30    6*6=36
7*1=7   7*2=14    7*3=21    7*4=28     7*5=35    7*6=42    7*7=49
8*1=8   8*2=16    8*3=24    8*4=32     8*5=40    8*6=48    8*7=56    8*8=64
9*1=9   9*2=18    9*3=27    9*4=36     9*5=45    9*6=54    9*7=63    9*8=72    9*9=81

2.参考源码:

 def fun():
     for line in xrange(1,10):
         for row in xrange(1,line + 1):
           s=str(line) + ' * ' + str(row) + ' = ' + str(line * row)
         print s.ljust(12),'|',
     print ''

 fun()

3) 杨辉三角 ->易

1.问题描述:

根据输入行数,打印出杨辉三角,如图所示。
1
1    1
1    2    1
1    3    3     1
1    4    6     4   1
1    5    10   10   5   1
1    6    15   20   15  6   1

2.参考源码:

#!/user/bin/python

def yang(floor):
    now = []
    for x in xrange(floor):
        now.append(1)
        for index in xrange(len(now) - 2,0,-1):
            now[index] = now[index - 1] + now[index]
        print now

yang(5)

数学问题

1) 天平秤物 ->难

1.问题描述:
有4个砝码,总重量是40克,砝码的质量是整数,且各不相等。请确定它们的质量,使之能称出1 ~ 40克任何整数质量的物体。

2.参考源码:

def fun(m, n):
    a = []
    while n > 1:
        k = 2 * sum(a) + 1
        a.append(k)
        n -= 1

    k = m - sum(a)
    if k - 2 * sum(a) < 2:
        a.append(k)
        return a

    return None

print fun(40, 4)

2) 黑色星期五 ->易

1.问题描述:
黑色星期五源于西方的宗教信仰与迷信:耶稣基督死在星期五,而13是不吉利的数字。两者的结合令人相信当天会发生不幸的事情。星期五和数字13都代表着坏运气,两个不幸的个体最后结合成超级不幸的一天。所以,不管哪个月的13日又恰逢星期五就叫“黑色星期五”。找出未来几年哪些天是“黑色星期五”。

2.参考源码:

#!/usr/bin/env python

3) 存钱问题 ->中

1.问题描述:
父亲准备为小龙的四年大学生活一次性储蓄一笔钱,使用整存零取的方式,控制小龙每月月初取1000元准备这个月使用。假设银行整存零取的年利息1.71%,请算出父亲至少需要存入多少钱才行。

2.参考源码:

a = 1000

for i in xrange(47,0,-1):
    a /= (0.0171 / 12) + 1
    a += 1000

a = round(a,2)
print a

4) 赛场统分 ->中

1.问题描述:
在编程竞赛中,有10个评委为参赛的选手打分,分数为0 ~ 100分。选手最后得分为:去掉一个最高分和一个最低分后其余8个分数的平均值。

请编写一个程序实现。

2.参考源码:

import random

score = [random.randint(1,100) for x in xrange(10)]

print scoure

score.remove(max(scoure))
score.remove(min(scoure))

result = sum(score) / len(score)

print result

5) 肇事车辆 ->中

1.问题描述:
有一个卡车司机肇事后想逃跑,但是被三个人看见了其车牌号,但是都没看全,甲说:车牌的前两位是一样的;乙说:车牌的后两位一样的,但与前两位不一样;丙说:车牌是一个数字的平方。

请编写一个程序计算该车牌号是多少(车牌号4位数)。

2.参考源码:

import math
def FindHim():
    for x in xrange(10):
        for y in xrange(10):
        if x != y:
        result = x * 1100 + y * 11
        test = math.sqrt(result) 
        if test.is_integer():
            return result

print FindHim()

6) 分糖果 ->中

1.问题描述:
10个小孩围城一圈分糖果,老师分给第1个小孩10块,第2个小孩2块,第3个小孩8块,第4个小孩22块,第5个小孩16块,第6个小孩4块,第7个小孩10块,第8个小孩6块,第9个小孩14块,第10个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩;糖块数为奇数的人可向老师要一块。

问经过这样几次后大家手中的糖的块数一样多? 每人各有多少块糖?

2.参考源码:

#coding:utf-8

#解题思路:
#    1.用列表存储当前小朋友的糖果数.
#    2.模拟糖果传递过程, (s[i-1] + s[i]) / 2
#    3.判断是否全相等

def fun():
    s = [10, 2, 8, 22, 16, 4, 10, 6, 14, 20]

    count = 0
    while not all([x == s[0] for x in s]):
        s = [(s[i-1] + s[i]) / 2 for i in range(10)]
        s = [x + x % 2 for x in s]
        count += 1

    print count, s

fun()

7) 平分七框鱼 ->中

1.问题描述:
甲、乙、丙三位渔夫出海打鱼,他们随船带了21只箩筐。当晚返航时,他们发现有7筐装满了鱼,还有7筐只装了半筐鱼,另外7筐则是空的。由于他们没有秤,只好通过目测认为7个满筐鱼的重量是相等的,7个半筐鱼的重量也是相等的。

在不将鱼倒出来的前提下,怎么将鱼和筐平分三份?

2.参考源码:

#coding:utf-8

#解题思路:
#    1.我们可以计算得知,每人应得3.5框鱼
#    2.穷举每人拿到整框数,a, b, c
#    3.计算每人应拿半框数,ah, bh, ch, 
#    4.ah + bh + ch == 7 ?

for a in range(4):
    for b in range(min(4, 7 - a + 1, a + 1)):
        c = 7 - a - b
        if c >= 4 or c > b:
            continue
        h = map(lambda x: int((3.5 - x) / 0.5), (a, b, c))
        if sum(h) == 7:
            print '-' * 20
            for x, y in zip((a, b, c), h):
                print x, y, 7 - x - y

趣味方程

1) 百鸡百钱 ->中

1.问题描述:
我国古代数学家张丘建在《张丘建算经》一书中提出了“百鸡问题”:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?这个问题的大致意思是这样的:公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱。

如果用100文钱买100只鸡,那么公鸡、母鸡和小鸡各应该买多少只呢?

2.参考源码:

#!/usr/bin/env python
#coding:utf-8
def fun():
    for i in xrange(0, 100, 3):
        for j in xrange(100):
            if 100 - i - j >= 0 and 5*(100 - i - j) + i/3 + j == 100 and (i/3 + j)%5 == 0:
                print '小鸡%d只,母鸡%d只,公鸡%d只'%(i, j, 100 - i - j)

fun()

2) 楼梯台阶 ->中

1.问题描述:
一个共有10个台阶的楼梯,从下面走到上面,一次只能迈一个台阶或两个台阶,并且不能后退,走完这个楼梯共有多少种方法。

2.参考源码:

#coding:utf-8

def fun(n):
    res = fun.cache.get(n, None)
    if res:
        return res

    res = []
    for step in (1, 2):
        if n < step: break
        for p in fun(n - step):
            res.append([step] + p)

    fun.cache[n] = res
    return res
fun.cache = {0:[[]]}

3) 换硬币 ->中

1.问题描述:
设有n种不同面值的硬币,各硬币的面值存于数组w[i]中。现要用这些面值的硬币来找钱,可以使用的各种面值的硬币个数存于数组S[i]中。

对任意钱数0≤m,设计一个用最少硬币找钱m的方法。

2.参考源码:

def  fun(value,money):

    times = value / money[0]

    if len(money) == 1:
        if value % money[0] == 0:
            return times,[times]
        else:
            return None

    result = (value + 1,0)
    for i in xrange(times + 1):

        residue = value - money[0] * i
        get = fun(residue,money[1:])

       if get != None and get[0] + i< result[0]:
           result = (get[0] + i,[i] + get[1])

    if result[1] == 0:
        return None
    else:
        return result

4) 求s=a+aa+aaa+aa…a的值 ->中

1.问题描述:
求表达式s=a+aa+aaa+aa…a的值,要求a从键盘接收,表达式的长度也从键盘接受。

2.参考源码:

#!/usr/bin/python

def fun(a, n):
   s = 0
   for i in xrange(1, 2*n, 2):
      s = s*10 + i*a
   return s

a = input()
n = input()
print fun(a, n)

5) 鸡兔同笼 ->中

1.问题描述:
鸡兔同笼问题最早记载于1500年前的《孙子算经》,这是我国古代一个非常有名的问题。鸡兔同笼的原文如下:
今有鸡兔同笼,上有三十五头,下有九十四足,问鸡兔各几何?
这个问题的大致意思是:在一个笼子里关着若干只鸡和若干只兔,从上面数共有35个头,从下面数共有94只脚。

问笼中鸡和兔的数量各是多少?

2.参考源码:

#!/usr/bin/env python
#coding:utf-8
def fun():
    for i in xrange(36):
            if 35 - i >= 0 and 2*i + 4*(35 - i) == 94:
                print '有鸡%d只, 有兔%d只'%(i, 35 - i)

fun()

6) 巧算年龄 ->易

1.问题描述:
有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人大2岁。问最后1个人,他说是10岁。

请问第5个人多大?

2.参考源码:

#!/usr/bin/env python

  def age(idx):
       return 10 if idx == 1 else age(idx-1) + 2

  print age(5)

7) 五家共井 ->中

1.问题描述:
五家共井记载于中国古代的数学专著《九章算术》。五家共井问题的原文如下:
今有五家共井,甲二绠不足如乙一绠,乙三绠不足如丙一绠,丙四绠不足如丁一绠,丁五绠不足如戌一绠,戌六绠不足如甲一绠。如各得所不足一绠,皆逮。问井深、绠长各几何?
这里,“绠”就是汲水桶上的绳索,“逮”就是到达井底水面的意思。这个问题大致意思是这样的,现在五家共用一口井,甲、乙、丙、丁、戌五家各有一个绳子汲水:
甲绳 * 2+乙绳=井深,
乙绳 * 3+丙绳=井深,
丙绳 * 4+丁绳=井深,
丁绳 * 5+戌绳=井深,
戌绳 * 6+甲绳=井深。

求甲、乙、丙、丁、戌的长度和井深。

2.参考源码:

#!/usr/bin/env python
'''
2a + b = deep
3b + c = deep
4c + d = deep
5d + e = deep
6e + a = deep
---->
a = b + c/2
b = c + d/3
c = d + e/4
d = e + a/5
---->
c % 2 = 0
d % 3 = 0
e % 4 = 0
a % 5 = 0

'''

def fun():
    e = 0
    while True:
        e += 4
        a = 0
        while True:
            a += 5
            d = e + a / 5
            c = d + e / 4
            if c % 2 != 0 or d % 3 != 0:
                continue
            b = c + d / 3
            if b + c / 2 < a:
                break
            if b + c / 2 == a:
                deep = 2 * a + b
                print 'a--> %d, b--> %d, c--> %d, d--> %d, e--> %d, deep--> %d' % (a, b, c, d, e, deep)
                return a, b, c, d, e, deep
print fun()

8) 三色球问题 ->中

1.问题描述:
若一个口袋中放有12个球,其中有3个红色的,3个黄色的,6个绿色的,从中任取8个球。

问共有多少种不同的颜色搭配?

2.参考源码:

def fun():
    count = 0
    for i in range(4):
        for j in range(4):
            if 8 - i - j <= 6:
                print i, j, 8 - i - j
                count += 1
    print count

fun()

趣味分数

1) 最大公约数 ->易

1.问题描述:
求任意两个整数的最大公约数。

2.参考源码:

#!/usr/bin/env python

def fun(m, n):
    if n > m: m, n = n, m

    while True:
        m, n = n, m % n
        if n == 0: break

    return m

fun(27, 18)

2) 最小公倍数 ->易

1.问题描述:
求任意3个整数的最小公倍数。

2.参考源码:

#!/usr/bin/env python

a, b, c = (input() for i in range(3))

if b > a: a, b = b, a
if c > a: a, c = c, a

ans = a
while ans % b or ans % c:
   ans += a
print ans

3) 分数比较 ->中

1.问题描述:
比较两个分数的大小。a/b, c/d。

2.参考源码:

#!/usr/bin/env python
#coding:utf-8

def fun(x, y):
    a, b = x
    c, d = y
    return a * d - b * c

res = fun((2,3), (2, 5))
if res > 0:
    print u'大于'
elif res < 0:
    print u'小于'
else:
    print u'等于'

4) 分数求和 ->中

1.问题描述:
求这样的4个自然数p、q、r、s(p<=q<=r<=s),使得一下等式成立:1/p+1/q+1/r+1/s=1。

2.参考源码:

#!/usr/bin/env python
#coding:utf-8

def fun():
    a = 2
    # 刻画循环条件:
    # 1) 4/a > 1/a + 1/b + 1/c + 1/d = 1 (因a
    while a < 4:
        b = a + 1
        # 刻画循环条件:
        # 1) 1/a + 1/b < 1, 1/a + 1/b最大为 1/2+1/3, 此条件恒成立
        # 2) 1/a + 3/b > 1/a + 1/b + 1/c + 1/d = 1 (因a ab
        while b+3*a > a*b:
            c = b + 1
            # 刻画循环条件:
            # 1) 1/a + 1/b + 1/c < 1, 通分得 bc + ac + ab < abc
            # 2) 1/a + 1/b + 2/c > 1/a + 1/b + 1/c + 1/d = 1 (因a 1
            while b*c+a*c+a*b*b*c and b*c+a*c+2*a*b > a*b*c:
                d = c + 1
                # 刻画循环条件:
                # 1) 1/a + 1/b + 1/c + 1/d > 1
                while True:
                    k = b*c*d+a*c*d+a*b*d+a*b*c 
                    if k == a*b*c*d: print 'find:', a, b, c, d
                    if k <= a*b*c*d: break
                    d += 1
                c += 1
            b += 1
        a += 1
fun()

5) 埃及分数式 ->中

1.问题描述:
分子是1的分数,叫单位分数。古代埃及人在进行分数运算时,只使用分子是1的分数,因此这种分数也叫做埃及分数式,或者叫单分子分数。要求随便输入一个真分数,将该分数分解为埃及分数式,如3/7=1/3+1/11+1/231.

2.参考源码:

#coding:utf-8

#解题思路:
#   1. 对于一个真分数b分之a, 找最接近的1/k
#   2. 如果a % b == 0, 找到k = b/a
#   3. 如果a % b != 0, 找到k = b/a + 1

def fun(a, b):
    k = b / a
    if b % a == 0:
        res = '1/%s' % k
    else:
        k += 1
        res = '1/%s + %s' % (k, fun(a * k - b, b * k))
    return res

print fun(4, 7)

6) 分数数列 ->中

1.问题描述:
有一分数序列:2/1,3/2 ,5/3, 8/5,13/8 ,21/13,…,求出这个数列的前20项之和。

2.参考源码:

#/usr/bin/env python

def fun():
    a = 2.0
    b = 1.0
    s = 0.0

    for i in xrange(20):
        s += a / b
        a, b = a + b, a

    print s

fun()

7) 猴子分桃 ->中

1.问题描述:
1979年,李政道博士给中国科技大学少年班出过一道知趣题:5只猴子分一堆桃子,怎么也分不成5等分,只好先去睡觉,准备第二天分。夜里1只猴子偷偷爬起来,先吃掉一个桃子,然后将其分为5等份,藏起自己的一份就去睡觉了;第二只猴子又爬起来,吃掉一个桃子后,也将桃子分成5等份,藏起自己的一份睡觉去了;以后的3只猴子都先后照此办理。

问最初有多少个桃子?

2.参考源码:

#!/usr/bin/env python
#coding:utf-8

def show(n):
    for i in xrange(1,6):
        t = (n - 1) / 5
        print '%d. 总数%d个, 第%i只猴吃一个, 拿走%s个。' % (i, n, i, t)
        n = 4 * t

def fun():
    k = 1
    while True:
        t = k
        #当前猴子拿走tc,吃拿之前总量应为 5 * tc + 1
        #前个猴子拿走tp,则有 4 * tp = 5 * tc + 1  
        for i in xrange(4):
            t = 5 * t + 1
            if t % 4: break
            t /= 4
        else:
             print 5 * t + 1
             show(5 * t + 1)
             # 我们只找最小整数解
             break
        k += 1

fun()

趣味猜想

1) 角谷猜想 ->易

1.问题描述:
角谷猜想的内容为:任意给定一个自然数,若它为偶数则除以2,若它为奇术则乘3加1,得到一个新的自然数。按照这样的计算方法计算下去,若干次后得到的结果必然为1。

编写程序对角谷猜想的正确性加以验证。

2.参考源码:

#/usr/bin/env python

def fun(n):
    print n,
    while n != 1:
        n = 3 * n + 1 if n % 2 else n / 2

    print 'finished'

for i in xrange(2, 1000):
    fun(i)

2) 回文数 ->易

1.问题描述:
“回文数”是一种数字。如:98789,这个数字正读是98789,倒读也是98789,正读倒读一样,所以这个数字就是回文数。

编程判断一个数是否是回文数。

2.参考源码:

#!/usr/bin/env python
#coding:utf-8

def fun(n):
    a = []
    while n:
        a.append(n % 10)
        n /= 10

    for i in xrange(len(a)):
        if a[i] != a[-i-1]:
            break
    else: 
         print u'回文数'
         return True

    print u'非回文数'
    return False

fun(78987)

3) 卡布列克常数 ->易

1.问题描述:
任意一个不是用完全相同数字组成的四位数,如果对它们的每位数字重新排序,组成一个较大的数和一个较小的数,然后用较大的数减去较小数,不够四位数时补零,类推下去,最后将变成一个固定的数:6174,这就是卡布列克常数。
例如:
4321-1234=3087
8730-378=8352
8532-2358=6174
7641-1467=6174

编写程序验证卡布列克常数。

2.参考源码:

#!/usr/bin/env python

def fun(n):
    if n == 6174:
        print '6174'
        return

    a = []
    while n:
        a.append(n % 10)
        n /= 10
    a.sort()

    s = 0
    k1 = 1
    k2 = 1000
    for x in a:
        s += x * (k1 - k2)
        k1 *= 10
        k2 /= 10

    fun(s)

fun(1234)

4) 剩余定理 ->中

1.问题描述:
在一千多年的《孙子算经》中,有这样一道算术题:
“今有物不知其数,三三数之乘二,五五数之乘三,七七数之乘二,问物几何?”按照今天的话来说:一个数除以3余2,除以5余3,除以7余2。

求这个数。

2.参考源码:

#!/usr/bin/env python  
 def shengyu():
      for i in xrange(100):
          if i % (3*7) == 2 and i % 5 == 3 :
              print i

5) 尼科彻斯定理 ->中

1.问题描述:

验证尼克斯彻定理,即任何一个整数的立方都可以写成一串连续奇数的和,如下所示:
1³ =1
2³=3+5
3³=7+9+11
4³=13+15+17+19
……

2.参考源码:

#!/usr/bin/env python

def fun(n):
   k = n ** 3
   h = t = 1
   while True:
      k -= t
      while k < 0: 
         k += h
         h += 2
      if k == 0:
         break
      t += 2
   print h, t
   return range(h, t + 1, 2)

print fun(6)

6) 马踏棋盘 ->难

1.问题描述:
国际象棋的棋盘有8行8列共64个单元格,无论将马放于棋盘的哪个单元格,都可让马踏遍棋盘的每个单元格。

问马应该怎么走才可以踏遍棋盘的每个单元格?

2.参考源码:

#/usr/bin/env python

L = 8
M = [0] * (L * L)

def allEntry(x, y, m):
    t = [(x + i, y + k * 2 / i) for i in (-1, 1, -2, 2) for k in (-1, 1)]
    return [(ex, ey) for ex, ey in t if -1 < ex < L and -1 < ey < L and m[L * ex + ey] == 0]

def sortedEntryList(x, y, m):
    a = [8]
    res = []
    for ex, ey in allEntry(x, y, m):
        c = len(allEntry(ex, ey, m))
        for i, t in enumerate(a):
            if c <= t: break
        a.insert(i, c)
        res.insert(i, (ex, ey))
    return res

def show(m):
    print 'show:'
    for i in xrange(L):
        print m[i * L:i * L + L]
    print

def move(x, y, m, n):
    m[L * x + y] = n
    if n == L * L:
        show(m)
        return

    for ex, ey in sortedEntryList(x, y, m):
        move(ex, ey, m[:], n + 1)

move(0, 0, M, 1)

逻辑推理

1) 斐波那契数列 ->易

1.问题描述:
斐波那契数列(Fibonacci Sequence),又称黄金分割数列,指的是这样一个数列:1,1,2,3,5,8,13,21,…,这个数列从第三项开始,每一项都等于前两项之和。

求fibonacci 数列的前25项。

2.参考源码:

def fibonacci(n):
    a = [1] * n
    for i in range(2, n):
        a[i] = a[i-1] + a[i-2]
    return a

print fibonacci(25)

2) 汉诺塔问题 ->难

1.问题描述:

汉诺(Hanoi)塔源自于古印度,又称为河内塔。汉诺塔是非常著名的智力趣题,在很多算法书籍和智力竞赛中都有涉及。汉诺塔问题的大意如下:
勃拉玛是古印度的一个开天辟地的神,其在一个宇宙中留下了三根金刚石的棒,第一根上面套着64个大小不一的圆形金片(圆盘)。其中,最大的金片在最底下,其余的依次叠上去,且一个比一个小。勃拉玛要求众僧将该金刚石棒中的金片逐个地移到另一根棒上,规定一次只能移动一个金片,且金片在放到棒上时,大的只能放在小的下面,但是可以利用中间的一个棒作为辅助移动使用。

2.参考源码:

#!/usr/bin/env python

def move(a, b, c, n):
    if n == 1:
       print a, "->", c
       return
    move(a, c, b, n - 1)
    print a, "->" ,c
    move(b, a, c, n - 1)

n = input()
move('A','B','C', n)

3) 年龄问题 ->易

1.问题描述:
王二、张三、李四、刘五年龄成一等差数列,他们四人的年龄相加是28,相乘是585。

求以他们的年龄为前4项的等差数列的前15项。

2.参考源码:

#!/usr/bin/env python

def sum(a, k, n):
    s = a
    for i in xrange(1, n):
        s += a + i * k 
    return s

def mul(a, k, n):
    s = a  
    for i in xrange(1, n):
        s *= a + i * k 
    return s

for a in range(1, 28 / 4):
    find = False
    k = 1
    while True: 
        t = sum(a, k, 4)
        if t >= 28: 
            if t == 28 and mul(a, k, 4) == 585:
                find = True
            break
        k += 1
    if find:
        for i in xrange(4):
            print a + i * k, 

4) 谁在说谎 ->中

1.问题描述:
张三说李四在说谎,李四说王五在说谎,王五说张三和李四都在说谎。

现在问:这三人中到底谁说的是真话,谁说的是假话?

2.参考源码:

#!/usr/bin/env python

t = [True, False]

for a in t:
   for b in t:
      for c in t:
         a0 = not b
         b0 = not c
         c0 = not a and not b
         if a == a0 and b == b0 and c == c0:
            print a, b, c

5) 谁家孩子跑得最慢 ->中

1.问题描述:
张、王、李三家各有三个孩子。一天,三家的九个孩子在一起比赛短跑,规定不分年龄大小,跑第一得9分,跑第二得8分,依此类推。比赛结果各家的总分相同,且这些孩子没有同时到达终点,也没有一家的两个或三个孩子获得相连的名次。已知获得第一名的是李家的孩子,获得第二名的是王家的孩子。

问获得最后一名的是谁家的孩子?

2.参考源码:

#!/usr/bin/env python
#coding:utf-8

#每家的总分 (1+2+3...+9) / 3 = 15, 李家有孩子第一, 王家有孩子第二。穷举。
for li in [[x, 6 - x, 9] for x in xrange(1, 6) if 6 - x - x > 1]:
    tw = range(1, 10)
    map(tw.remove, li)
    for wang in [[x, 7 - x, 8] for x in tw if 7 - x in tw and 7 - x - x > 1]:
        zhang = tw[:]
        map(zhang.remove, wang) 
        if zhang[1] - zhang[0] > 1 and zhang[2] - zhang[1] > 1:
            print 'li:%s wang:%s zhang:%s' % (li, wang, zhang)

6) 猴子爬山 ->中

1.问题描述:
一只顽猴在一座有50级台阶的小山上爬山跳跃。上山时需从山脚至山顶往上跳50级台阶,一步可跳2级,或跳3级,或跳4级,求上山有多少种不同的跳法?下山时从山顶至山脚往下跳50级台阶,一步可跳1级,或跳2级,或跳3级,求下山有多少种不同的跳法?

2.参考源码:

#!/usr/bin/env python

def fun(n, a, x, y, z):
    a[0] = 1
    for i in xrange(50):
        a[i + x] += a[i]
        a[i + y] += a[i]
        a[i + z] += a[i]
    return a[n]


n = input()  
up = [0] * (n + 5)
down = [0] * (n + 5)

print fun(n, up, 2, 3, 4), fun(n, down, 1, 2, 3)

7) 兔子产仔 ->中

1.问题描述:
一般而言,兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?

2.参考源码:

#!/usr/bin/env python

#每月兔子总数是一个斐波那契数列, 请参看斐波那契数列求和代码。

8) 舍罕王赏麦 ->中

1.问题描述:
舍罕是古印度的国王,据说他十分好玩,宰相达依尔为讨好国王,发明了现今的国际象棋献给国王。舍罕非常喜欢这项游戏,于是决定嘉奖达依尔,许诺可以满足达依尔提出的任何要求。达依尔指着舍罕王前面的棋盘提出了要求:“陛下,请您按棋盘的格子赏赐我一点麦子吧,第1个小格赏我一粒麦子,第2个小格赏我两粒,第3个小格赏我四粒,以后每一小格都比前一个小格赏的麦粒数增加一倍,只要把棋盘上全部64个小格按这样的方法得到的麦粒都赏赐给我,我就心满意足了。”舍罕王听了达依尔这个“小小”的要求,想都没想就满口答应下来。

求舍罕王共赏了多少粒麦子?

2.参考源码:

#!/usr/bin/env python

s = 0
t = 1
for i in xrange(64):
    s += t
    t *= 2
print t

#列表解析解法:
sum([2 ** i for i in xrange(64)])

#函数式编程解法:
reduce(lambda x, y: x + 2 ** y, xrange(64))

趣味变幻

1) 分解质因数 ->易

1.问题描述:
将一个正整数分解质因数。例如,输入90,打印出90=2 * 3 * 3 * 5

2.参考源码:

def fun(n):
    res = []
    k = 2
    while k <= n:
        if n % k == 0:
            res.append(k)
            n /= k
        else:
            k += 1
    return res

2) 乘式还原 ->易

1.问题描述:
A代表数字0~9中的前5个数字,Z代表后5个数字,请还原下列乘式:

                      A  Z  A
                   x  A  A  Z
                  --------------
                   A  A  A  A
                A  A  Z  Z
                Z  A  A
               ---------------
                Z  A  Z  A  A

2.参考源码:

#!/usr/bin/env python

3) 除式还原 ->易

1.问题描述:

给定下列除式,其中包含5个7,其他打X的是任意数字,请加以还原。

                               X  7  X  -------------
                    ————————————————————— 
   除数-----   X X   X  X  X  X  X  ----------被除数
                      x  7 7
                          ----------------
                         X 7 X
                         X 7 X
                         ----------------
                             X X
                             X X
                          ----------------
                               0

2.参考源码:

#!/usr/bin/env python

def findHead():
   for x in xrange(10, 100):
      for y in xrange(1, 10):
         if str(x * y)[1:] == '77' and str(x * 7)[1] == '7':
            return x, y, x*y, x*7

def findTail(x):
   for y in xrange(1, 10):
      if x*y < 100:
         return y, x*y
def main():
   chu, shang1, ji1, ji2 = findHead()
   shang3, ji3 = findTail(chu)
   res = ji3 + ji2 * 10 + ji1 * 100
   return res, chu, int(str(shang1)+'7'+str(shang3))

print main()

4) 奇数幻方 ->中

1.问题描述:
在一个由若干个排列整齐的数组成的正方形中,图中任意一横行、一纵行及对角线的几个数之和都相等,具有这种性质的图表,称为“幻方”。我国古代称为“河图”、“洛书”,又叫“纵横图”。
8 1 6
3 5 7
4 9 2

2.参考源码:

#!/usr/bin/env python
#coding:utf-8

def fun(n):
    m = [[0] * n for i in xrange(n)]

    x, y = 0, n / 2
    m[x][y] = 1

    for k in xrange(2, n * n + 1):
        if x == 0 and y == n - 1:
            x1, y1 = x + 1, y
        elif x == 0:
            x1, y1 = n - 1, y + 1
        elif y == n - 1:
            x1, y1 = x - 1, 0
        else:
            x1, y1 = x - 1, y + 1

        x, y = (x + 1, y) if m[x1][y1] else (x1, y1)
        m[x][y] = k

    return m

fun(3)

5) 泊松分酒 ->中

1.问题描述:
有一个12品脱(pint)的酒瓶,里面装满葡萄酒,另有8品脱和5品脱的瓶子各一个。问如何从中分出6品脱的酒出来?
传说泊松年轻时成功解决了该问题,勾起了他对数学的兴趣而投身数学研究,因此该问题被称为泊松分酒问题。另外这个问题又被称为分油问题、分水问题等。

2.参考源码:

#!/usr/bin/env python

L = [12, 8, 5]
l = [12, 0, 0]
c = [lambda: l[1] == 0, lambda: l[1] != 0, lambda: l[2] == L[2]]

src = 0
while 6 not in l:
    dst = (src + 1) % 3
    if c[src]():
        t = min(L[dst] - l[dst], l[src])
        l[src] -= t
        l[dst] += t
        print l
    src = dst

6) 猜牌术 ->中

1.问题描述:
魔术师利用一副牌中的13张黑桃,预先将它们排好后迭在一起,牌面朝下。对观众说:我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?你们就看。魔术师将最上面的那张牌数为1,把它翻过来正好是黑桃A,将黑桃A放在桌子上,然后按顺序从上到下数手上的余牌;第二次数1、2,将第一张牌放在这迭牌的下面,将第二张牌翻过来,正好是黑桃2,也将它放在桌子上;第三次数1、2、3,将前面两张依次放在这迭牌的下面,再翻第三张牌正好是黑桃3。这样依次进行,将13张牌全翻出来,准确无误。

问魔术师手中的牌原始顺序是怎样安排的?

2.参考源码:

#!/usr/bin/env python

7) 邮票组合 ->中

1.问题描述:
某人有4张3分的邮票和3张5分的邮票,用这些邮票中的一张或若干张可以得到多少种不同的邮资?

2.参考源码:

#!/usr/bin/env python

len({3 * x + 5 * y for x in xrange(4 + 1) for y in xrange(3 + 1) if x + y > 0})

8) 整数拆分 ->中

1.问题描述:
将一个正整数拆分成若干个正整数的和,问有多少种分法。

2.参考源码:

#!/usr/bin/env python
d = {}

def fun(n, m):
    if (n, m) in d:
        return d[(n, m)]
    if m > n: m = n
    res = 1
    for i in xrange(m, 1, -1):
        res += f(n - i, i)
    d[(n, m)] = res
    return res

print f(100, 99)

趣味游戏

1) 掷筛子 ->中

1.问题描述:
一个简单的游戏,规则如下:玩家掷两个筛子,点数为1~6,如果第一次点数和为7或11,则玩家胜;如果点数和为2、3或12,则玩家输;如果和为其他点数,则记录第一次的点数和,然后继续掷筛,直至点数和等于第一次掷出的点数和,则玩家胜;如果在这之前掷出了点数和为7,则玩家输。

请编程实现。

2.参考源码:

import random

def fun():
    k = random.randint(1, 6) + random.randint(1, 6)
    if k in (7, 11):
        return True
    if k in (2, 3, 12):
        return False

    while True:
        kk = random.randint(1, 6) + random.randint(1, 6)
        if kk == k:
            return True
        if kk == 7:
            return False
print fun()

2) 发扑克牌 ->中

1.问题描述:
扑克牌是一种非常大众化的游戏,在计算机中有很多与扑克牌有关的游戏。例如,在Windows操作系统下自带的纸牌、红心大战等。在扑克牌类的游戏中,往往都需要执行洗牌操作,就是将一副牌完全打乱,使其排列没有规律。

请编程实现发扑克牌。

2.参考源码:

#coding:utf-8    
import random

def shuffle(n):
    a = range(n)

    for i in range(len(a) - 1, 0, -1):
        k = random.randint(0, i)
        a[i], a[k] = a[k], a[i]

    return a

print shuffle(10)

3) 24点 ->难

1.问题描述:
24点游戏是一个大众化的益智游戏。任意给4张扑克牌(不包括大小王),只能够用加、减、乘、除以及适当的括号连接这4张牌,无论顺序,使计算结果为24,或者宣布根本就是无解的。需要注意的是,每张牌必须运算,并且只能运算一次,J、Q、K可设置为11、12、13。

2.参考源码:

#!/usr/bin/env python
import random

exps = ('((%s %s %s) %s %s) %s %s',
        '(%s %s %s) %s (%s %s %s)', 
        '(%s %s (%s %s %s)) %s %s',
        '%s %s ((%s %s %s) %s %s)',
        '%s %s (%s %s (%s %s %s))',)

ops = ('+', '-', '*', '/')

def fun(a):
    def check(exp):
        try:
            return eval(exp) == 24
        except:
            return False

    return [exp % (a[0], op1, a[1], op2, a[2], op3, a[3]) for op1 in ops for op2 in ops for op3 in ops for exp in exps if check(exp % (a[0], op1, a[1], op2, a[2], op3, a[3]))]

l = [random.randrange(1, 10) for i in range(4)]
print fun(l)

4) 常胜将军 ->中

1.问题描述:
常胜将军是一个非常有意思的智力游戏趣题,常胜将军的大意如下:
甲和乙两人玩抽取火柴的游戏,共有21根火柴。每个人每次最多取4根火柴,最少取1根火柴。如果某个人取到最后一根火柴则输了。甲让乙先抽取,结果每次都是甲赢。这是为什么呢?

2.参考源码:

#!/usr/bin/env python
def fun(match):
   idx = 0
   while match > 1:
      idx += 1
      if idx % 2 == 1:
         gamer = 'A'  
         choice = random.choice(xrange(1,5)) if match >= 5 else random.choice(xrange(1, match+1))
      else:
         gamer = 'B'
         if match > 5:
            for x in xrange(1, 5):
               if (match - x) % 5 == 1:
                  choice = x
                  break
         else:
           choice = match - 1
      match -= choice
      print gamer, choice, match
   another = 'A' if gamer == 'B' else 'B'
   loser = gamer if match == 0 else another
   print '%s LOSE!' % loser
fun(21)

5) 抢30 ->中

1.问题描述:
这是中国民间的一个游戏。两人从1开始轮流报数,每人每次可报一个数或两个连续的数,谁先报到30,谁就为胜方。

2.参考源码:

#!/usr/bin/env python
 import random
   i = 0
   a = 0
   while True:
       i += 1
       s = 'B' if i % 2 == 0 else 'A'
       if a == 30 - 1:
           res = 30
      elif a == 30 - 2:
          res = (29, 30)
      else:
          res = random.choice((a+1, (a+1, a+2)))
      print s,res
      a = a+1 if res == a+1 else a+2
      if a == 30 :
          print '%s WIN!' % s
          break;

6) 过桥游戏 ->中

1.问题描述:
小明一家过一座桥,过桥的时候是黑夜,所以必须有灯。现在小明过桥要2分钟,小明的弟弟要5分钟,小明的爸爸要6分钟,小明的妈妈要9分钟,小明的爷爷要13分钟。每次此桥最多可以过两人,过桥的速度根据过桥最慢者而定,而且灯在点燃后40分钟就会熄灭。

问小明一家如何过桥时间最短?

2.参考源码:

#!/usr/bin/env python

def fun(arr, time = 0):
    ll = len(arr)
    if ll == 1:
        return arr[0]
    if ll == 2:
        return arr[1] + time
    if ll == 3:
        return arr[0] + arr[1] + arr[2] + time
    x = 2*arr[0] + arr[-1] + arr[-2]
    y = arr[0] + 2*arr[1] + arr[-1]
    if x < y:
        return fun(arr[0:ll - 2], time + x)
    else:
        return fun(arr[0:ll - 2], time + y)

arr = [2, 5, 6, 9, 13]

print fun(arr)

7) 生命游戏 ->中

1.问题描述:
生命游戏称为细胞自动机游戏,或者元胞自动机游戏。生命游戏是英国数学家J.H.Conway首次提出的。在1970年,J.H.Conway小组正在研究一种细胞自动装置,J.H.Conway从中获得启发,提出了一种生命游戏,然后将其发表在《科学美国人》的“数学游戏”专栏。
生命游戏是一个典型的零玩家游戏,只需要用户输入初始的细胞分布,然后细胞便按照规则进行繁殖演化。生命游戏反映了生命演化和秩序的关系,具有很深刻的含义,在地理学、经济学、计算机科学等领域得到了非常广泛的应用。

2.参考源码:

#!/usr/bin/env python

import time
ecosystem = [[1 for i in xrange(12)] for i in xrange(12)]

def judge(arr, x, y):
    count = 0
    if arr[x-1][y] != 0:
        count += 1
    if arr[x-1][y-1] != 0:
        count += 1
    if arr[x+1][y-1] != 0:
        count += 1
    if arr[x+1][y] != 0:
        count += 1
    if arr[x+1][y+1] != 0:
        count += 1
    if arr[x][y+1] != 0:
        count += 1
    if arr[x][y-1] != 0:
        count += 1
    if arr[x-1][y+1] != 0:
        count += 1
    return count

def main(arr):
    for i in xrange(1, 11):
        for j in xrange(1, 11):
            if judge(arr, i, j) < 2 or judge(arr, i, j) > 4:
                arr[i][j] = 0
            if judge(arr, i, j) == 3 or judge(arr, i, j) == 4:
                arr[i][j] = 1

while True:
    main(ecosystem)
    print '-----------------------------------------------'
    for i in xrange(1, 11):
        print ecosystem[i]
    time.sleep(1)

趣味问题

1) 双色球 ->易

1.问题描述:
根据福利彩票双色球玩法规则,6个蓝色球,范围为1 ~ 33,不允许重复,1个红色球,范围为1 ~ 16,自动生成6个蓝色球,1个红色球。

2.参考源码:

#!/usr/bin/env python

import random
def fun():
    numa = [i for i in xrange(1, 34)]
    a = []
    for i in xrange(6):
        a.append(random.choice(numa))
        numa.remove(a[-1])
    a.append(random.choice([i for i in xrange(1, 17)]))
    print a

fun()

2) 金额转换 ->中

1.问题描述:
金额转换,阿拉伯数字的金额转换成中国传统的形式。
如:(¥1011)→(壹仟零壹拾壹元整)输出。

2.参考源码:

#!/usr/bin/env python
#coding:utf-8

ct = [u'零', u'一', u'二', u'三', u'四', u'五', u'六', u'七', u'八', u'九']
ut = ['', u'十', u'百', u'千']
steps = [u'', u'万', u'亿']

def g(s):
    res = u''
    for i in xrange(len(s)):
        k = s[-i-1]
        res =  ('' if k == '0' and res and res[0] == u'零' else ct[int(k)]) + ('' if k == '0' else ut[i]) + res

    return res[:-1] if s[-1] == '0' else res

def fun(s):
    l = len(s)
    p = s[-4:]
    i = 0 
    res = ''
    while p:
        t = g(p)    
        if t:
            z = u'零' if t[-1] in ut and res and res[0] != u'零' else ''
            res = t + steps[i] + z + res
        i += 1
        p = s[i * -4 - 4:i * -4]

    print res + u'元'

n = ''
while not n.isdigit(): 
    n = raw_input('')
fun(n)

3) 尾数前移 ->易

1.问题描述:
求一个自然数N,个位数是6,将6提到最前面所得数是N的4倍。

2.参考源码:

#coding:utf-8

#解题思路:
#   1.令末位数t = 6, 除末位以外部分n
#   2.t连续×10移动到最高位, 再加上n
#   3.t + n == 10 * n + 6 ?

# 1236 => 6123 == 4 * 1236

def fun(n):
    nn = n
    t = 6
    while nn > 0:
        t *= 10
        nn /= 10

    m = 10 * n + 6
    if t + n == m * 4:
        print m

for x in range(1, 100000):
    fun(x)

4) 高斯八皇后 ->难

1.问题描述:
八皇后问题是高斯于1950年提出的,这是一个典型的回溯算法的问题。八皇后问题的大意如下:
国际象棋的棋盘是8行8列共64个单元格,在棋盘上摆件八个皇后,使其不能互相攻击,也就是说任意两个皇后都不能处于同一行、同一列或同一斜线上。

问总共有多少种摆放方法,每一种摆放方式是怎样的。目前,数学上可以证明八皇后问题总共有92种解。

2.参考源码:

#coding:utf-8

#解体思路:
#    1.回溯法,逐行确定皇后所在列的位置.
#    2.如果N行全部, 则得到一个解.

def isValid(s, col):
    row = len(s)

    for r, c in enumerate(s):
        if c == col or abs(row - r) == abs(col - c):
            return False

    return True

def queen(n, s=()):
    if len(s) == n:
        return [s]

    res = []
    for col in range(n):
        if not isValid(s, col): continue
        for r in queen(n, s + (col,)):
            res.append(r)

    return res
    #以上部分可以用一行列表解析
    #return [res for col in range(n) if isValid(s, col) for res in queen(n, s + (col,))]

print [[(r, c) for r, c in enumerate(s)]for s in queen(4)]

5) 找假币 ->中

1.问题描述:
现在有8枚银币,其中有一枚是假币。但是,从外观和做工上无法分辨哪枚是真币哪枚是假币,只知道假币的重量要比真币稍轻。

要求仅使用一个天平,如何以最少的步骤寻找到假银币?

2.参考源码:

#!/usr/bin/env python

def fun(arr, down = 0):
    x = (len(arr) + 2)/3
    if len(arr) == 1:
        return down + 1
    elif sum(arr[0:x]) == sum(arr[x:2*x]):
        return fun(arr[2*x:3*x], down + 2*x)
    elif sum(arr[0:x]) > sum(arr[x:2*x]):
        return fun(arr[x:2*x], down + x)
    else:
        return fen(arr[0:x], down)

arr = [2, 2, 2, 2, 2, 2, 2, 1]
print fun(arr)

6) 窃贼问题 ->中

1.问题描述:
窃贼问题的大意如下:
有一个窃贼带着一个背包去偷东西,房屋中共有5件物品,其重量和价值如下:
物品1:6公斤,48元;
物品2:5公斤,40元;
物品3:2公斤,12元;
物品4:1公斤,8元;
物品5:1公斤,7元;

窃贼希望能够拿最大价值的东西,而窃贼的背包最多可装重量8公斤的物品。
那么窃贼应该装上列那些物品才能达到要求呢?

2.参考源码:

def m(i, c, w, v, n):
    if i == n:
        return 0, []

    res = m.d.get((i, c))
    if res:
        return res[0], res[1][:]

    m0, res0 = m(i + 1, c, w, v, n)
    if c >= w[i]:
        m1, res1 = m(i + 1, c - w[i], w, v, n)
        m1 += v[i]
        if m1 > m0:
            res1.insert(0, 1)
            m.d[(i, c)] =  m1, res1[:]
            return m1, res1

    res0.insert(0, 0)
    m.d[(i, c)] =  m0, res0[:]
    return m0, res0
m.d = {}

print m(0, 8, w, v, len(w))

7) 三色棋 ->中

1.问题描述:
有一条绳子上面挂有白、红、蓝三种颜色的多面旗子,这些旗子的排列是无序的。现在要将绳子上的旗子按蓝、白、红三种颜色进行归类排列,但是只能在绳子上进行旗子的移动,并且每次只能调换两个旗子。

问如何采用最少的步骤来完成三色棋的排列呢?

2.参考源码:

#coding:utf-8

import random
def fun(l):
    count = 0
    a = l.count(0)
    b = a + l.count(1)
    k1 = a
    k2 = len(l) - 1

    #把第一个区域全部交换成白
    for i in xrange(a):
        if l[i] == 0:
            continue

        if l[i] == 1:
            while l[k1] != 0: k1 += 1
            k = k1
        elif l[i] == 2:
            while l[k2] != 0: k2 -= 1
            k = k2
        l[k] = l[i]
        l[i] = 0
        count += 1

    #把第二个区域全部交换成红
    k = len(l) - 1
    for i in xrange(a, b):
        if l[i] == 2:
            while l[k] != 1: k -= 1
            l[k] = l[i]
            l[i] = 1
            count += 1
    return count

t = [random.choice([0,1,2]) for i in xrange(30)]
print t
steps = fun(t)
print t, steps

你可能感兴趣的:(Python,学习笔记)