重点讲解 杨辉三角 和 约瑟夫环报数游戏。
💪💪💪💪
python 永远滴神!!

例5-3 编写并使用能够生成斐波那契数列的生成器函数

def demo(s):
    result = [0, 0]     #不能直接定义为元组,因为元组是不能对其中元素进行修改操作的。
    for ch in s:
        if ch.islower():
            result[1] += 1
        elif ch.isupper():
            result[0] += 1
    return tuple(result)

例5-4 编写函数,接收字符串参数,返回一个元组,其中第一个元素为大写字母个数,第二个元素为小写字母个数。

def fun(s: str):
    result = [0, 0]
    for ch in s:
        if ch.islower():
            result[1] += 1
        elif ch.isupper():
            result[0] += 1
    return tuple(result)


if __name__ == '__main__':
    newstr = "asdhasjgdAasghd"
    print(len(newstr))
    print(fun(newstr))

例5-5 编写函数,接收一个整数t为参数,打印杨辉三角前t行。

注意:看此教程前请先学习生成器的原理,yield返回的用法规律,不然可能会懵逼。
下面我按照自己的理解写下思路:
首先附上我们需要求得的杨辉三角:

[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]
 
[1, 7, 21, 35, 35, 21, 7, 1]
 
[1, 8, 28, 56, 70, 56, 28, 8, 1]
 
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

很显然,是按照一行一个数列(list)实现的,也就是说,我们得在程序中不断的返回每一行的list并且打印出来
第一步:先找规律,抽象化问题:
首先我们观察到,第一行为[1],我们直接初始化列表 : p = [1]
其次我们观察到,下面的每一行的开头结尾都是[1],那么我们可以推导出每一行的规律为:[1]+.........+[1]
那么我们发现,从第三行开始中间的 [2],第四行中间的 [3,3],第五行中间的 [4,6,4] 等等以此类推才是我们需要推导的部分

第一行:[1] 设 p = [1]

第二行:[1]+[1] 设 p = [1,1]

第三行:[1]+[2]+[1] 设 p = [1,2,1]

第四行:[1]+[3]+[3]+[1]设 p = [1,3,3,1]

....

经过找规律,我们发现,每一个新的list中间的部分,都等于上一行list的:第0个元素+第1个元素,第1个元素+第2个元素,第2个元素+第3个元素,.......

加上头尾也就是[1] +[ p[0]+p[1] ]+[ p[1]+p[2] ].....+[1]

比如上面第三行:p[0] = 1, p[1] = 2, p[2] = [1]

那么第四行就是:[1] [1+2] [2+1] [1]

后面以此类推
既然核心点是这个除去首位两个 [1] 的中间部分:[p[0] + p[1]]+[p[1] + p[2]]+[p[2] + p[3]]........

我们很容易得到规律:[p[i] + p[i+1]]# for i in range(x)

如果还没看懂,你可以找一张纸,将每一行都按照这个规律写出来:

new p代表本行list的中间部分,p代表上一行list:

[1]
 
[1]+[1]
 
[1]+[2]+[1] new p = p[0] + p[1] / i = 0,1 需要 i in range(1)
# range(1) = 0,根据[p[i] + p[i+1]]即可实现p[0]+p[0+1]
 
[1]+[3]+[3]+[1] new p = p[0] + p[1], p[1] + p[2] /i = 0,1,2 需要 i in range(2)
[1]+[4]+[6]+[4]+[1] new p = p[0] + p[1], p[1] + p[2], p[2] + p[3] /i = 0,1,2,3 需要 i in range(3)
[1]+[5]+[10]+[10]+[5]+[1] new p = p[0] + p[1], p[1] + p[2], p[2] + p[3], p[3] + p[4] /i = 0,1,2,3,4需要 i in range(4)

i的规律为上一行list元素个数-1,也就是len(p) - 1
至此,已经可以得出推导式:
[1] + [p[i] + p[i + 1] for i in range(len(p) - 1)] + [1]

补全程序代码:

def triangles(t):
    lis = [1]
    while t:
        print(lis)
        lis = [1] + [lis[i] + lis[i + 1] for i in range(len(lis) - 1)] + [1]
        t -= 1


if __name__ == '__main__':
    triangles(10)

运行结果:

例5-6 编写函数,接收一个正偶数为参数,输出两个素数,并且这两个素数之和等于原来的正偶数。如果存在多组符合条件的素数,则全部输出。

def demo(n):
    def IsPrime(p):
        if p == 2:
            return True
        if p % 2 == 0:
            return False
        for i in range(3, int(p ** 0.5) + 1, 2):
            if p % i == 0:
                return False
        return True

    if isinstance(n, int) and n > 0 and n % 2 == 0:
        for i in range(2, n // 2 + 1):
            if IsPrime(i) and IsPrime(n - i):
                print(i, '+', n - i, '=', n)


if __name__ == '__main__':
    demo(100)

例5-7 编写函数,计算字符串匹配的准确率。

以打字练习程序为例,假设origin为原始内容,userInput为用户输入的内容,下面的代码用来测试用户输入的准确率。


def rate(origin, user_input):
    if not (isinstance(origin, str) and isinstance(user_input, str)):
        origin = str(origin)
        user_input = str(origin)
    right = sum((1 for o, u in zip(origin, user_input) if o == u))
    return round(right / len(origin), 2)


if __name__ == '__main__':
    print(rate("12345", "1233445"))

例5-8 编写函数模拟猜数游戏。

系统随机产生一个数,玩家最多可以猜5次,系统会根据玩家的猜测进行提示,玩家则可以根据系统的提示对下一次的猜测进行适当调整。

from random import randint


def guess(maxValue=100, maxTimes=5):
    # 随机生成一个整数
    value = randint(1, maxValue)
    print("游戏开始!")
    for i in range(maxTimes):
        prompt = '你还有 %d 次机会请输入猜测的数字:' % (maxTimes - i)
        # 使用异常处理结构,防止输入不是数字的情况
        try:
            x = int(input(prompt))
        except ValueError:
            print('Must input an integer between 1 and ', maxValue)
        else:
            # 猜对了
            if x == value:
                print('恭喜你,答对啦!')
                break
            elif x > value:
                print('猜大啦!')
            else:
                print('猜小了')
    else:
        # 次数用完还没猜对,游戏结束,提示正确答案
        print('游戏结束')
        print('正确答案是', value)


if __name__ == '__main__':
    guess()

编写函数模拟报数游戏。

有n个人围成一圈,顺序编号,从第一个人开始从1到k(假设k=3)报数,报到k的人退出圈子,然后圈子缩小,从下一个人继续游戏,问最后留下的是原来的第几号。
第一步:演算一下过程。j假设n=10,k=3。由于列表索引值从0开始所以第一个删除的值应该是3,索引为2 (即 k-1)
删除后后面数值的索引发生改变。6的索引从 5变为4 (2+k-1)
依次类推。
当到删除3,6,9 剩下: 1 2 4 5 7 8 10 按理应该删除 索引为8的值。
但是总长度为7。所以求余 8 % 7 = 1 。所以删除索引为1的值。
具体表格演示如下:
pop(2)的意思是 删除上一行索引为 2 的列。

索引0123456789
初始12345678910
pop(2)1245678910
pop(4)124578910
pop(6)12457810
pop(1)1457810
pop(3)145810
pop(0)45810
pop(2)4510
pop(1)410
4

代码实现:

def func(n=100, k=3):
    lis = [i for i in range(1, n + 1)]
    lis_len = len(lis)
    index = (k - 1) % lis_len
    while lis_len > 1:
        lis.pop(index)
        lis_len -= 1
        index = (k - 1 + index) % lis_len
        # print(lis,   index)
    print(lis[0])


if __name__ == '__main__':
    func(10, 3)