python 习题

使用蒙特-卡罗方法计算圆周率近似值

蒙特-卡罗方法是一种通过概率来得到问题近似解的方法。假设又一块边长为2的正方形木板,上面画一个单位圆,然后随意往木板上扔飞镖,落点坐标(x,y)必然在木板上(更多的是落在单位圆内),如果扔的次数足够多,那么落在单位圆内的次数除以总次数再乘以4,这个次数会无限接近圆周率的值。

from random import random
times = int(input('请输入掷飞镖次数:'))
hits = 0
for i in range(times):
    x = random()
    y = random()
    if x*x+y*y<=1 :
        hits += 1
print(4.0*hits/times)

求素数

1.使用列表实现筛选法

maxNumber = int(input('请输入一个大于2的自然数:'))
lst = list(range(2,maxNumber))
# 最大整数的平方根
m = int(maxNumber**0.5)
for index,value in enumerate(lst):
    # 如果当前数字已大于最大整数的平方根,结束判断
    if value > m:
        break
    # 对该位置之后的元素进行过滤
    lst[index+1:] = filter(lambda x: x%value != 0,lst[index+1:])
print(lst)

2.使用集合实现筛选法

maxNumber = int(input('请输入一个大于2的自然数:'))
numbers = set(range(2,maxNumber))
# 最大整数的平方根,以及小于该数字的所有素数
m = int(maxNumber**0.5)+1
primesLessThanM = [p for p in range(2,m)
                   if 0 not in [p%d for d in range(2,int(p**0.5)+1)]]
# 遍历最大整数平方根之内的自然数
for p in primesLessThanM:
    for i in range(2,maxNumber//p+1):
        # 在集合中删除数字所有的倍数
        numbers.discard(i*p)
print(numbers)

小明爬楼梯

假设一段楼梯共15个台阶,小明一步最多能上3个台阶。递推法,递归法。

def climbStairs1(n):
    # 递推法
    a = 1
    b = 2
    c = 4
    for i in range(n-3):
        c,b,a = a+b+c,c,b
    return c
def climbStairs2(n):
    # 递归法
    first3 = {1:1,2:2,3:4}
    if n in first3.keys():
        return first3[n]
    else:
        return climbStairs2(n-1) + \
               climbStairs2(n-2) + \
               climbStairs2(n-3)
print(climbStairs1(15))
print(climbStairs2(15))

蒙蒂霍尔

假设你正参加一个有奖游戏节目,并且有3道门可选:其中一个后面是汽车,另外两个后面是山羊。你选择一个门,比如说1号门,主持人当然知道每个门后面是什么并且打开了一个门,比如说3号门,后面是一只山羊。这时,主持人会问你“你想改选2号门吗?”,然后根据你的选择确定最终要打开的门,并确定你获得山羊(输)或者汽车(赢)。

from random import randrange

def init():
    # 返回一个字典,键为3个门号,值为门后的物品
    result = {i: 'goat' for i in range(3)}
    r = randrange(3)
    result[r] = 'car'
    return result

def startGame():
    # 获取本次游戏中每个门的情况
    doors = init()
    # 获取玩家选择的门号
    while True:
        try:
            firstDoorNum = int(input('Choose a door to open:'))
            assert 0 <=firstDoorNum <= 2
            break
        except:
            print('Door number must be between {} and {}'.format(0,2))
    # 主持人查看另外两个门后的物品情况
    for door in doors.keys()-{firstDoorNum}:
        # 打开其中一个后面为山羊的门
        if doors[door] == 'goat':
            print('"goat" behind the door', door)
            # 获取第三个门号,让玩家纠结
            thirdDoor = (doors.keys()-{door,firstDoorNum}).pop()
            change = input('Switch to {}?(y/n)'.format(thirdDoor))
            finalDoorNum = thirdDoor if change == 'y' else firstDoorNum
            if doors[finalDoorNum] == 'goat':
                return 'I win!'
            else:
                return 'You win.'
while True:
    print('='*30)
    print(startGame())
    r = input('Do you want to try once more?(y/n)')
    if r == 'n':
        break

猜数游戏

程序运行时,系统生成一个随机数,然后提示用户进行猜测,并根据用户输入进行必要的提示(猜对了、太大了、太小了),如果猜对则提前结束程序,如果次数用完仍没有猜对,提前游戏结束并给出正确答案。

from random import randint
def guessNumber(maxValue=10,maxTimes=3):
    # 随机生成一个整数
    value = randint(1,maxValue)
    for i in range(maxTimes):
        prompt = 'Start to GUESS:(1-10)' if i==0 else 'Guess again:'
        # 使用异常处理结构,防止输入不是数字的情况
        try:
            x = int(input(prompt))
        except:
            print('Must input an integer between 1 and ',maxValue)
        else:
            if x == value:
                # 猜对了
                print('Congratulations!')
                break
            elif x > value:
                print('Too big')
            else:
                print('Too little')
    else:
        # 次数用完还没猜对,游戏结束,提示正确答案
        print('Game ouer.FAIL.')
        print('The value is ',value)
guessNumber()

抓狐狸游戏

假设一共有一排5个洞口,小狐狸最开始的时候在其中一个洞口,然后玩家随机打开一个洞口,如果里面有狐狸就抓到了。如果洞口里没有狐狸就第二天再来抓,但是第二天狐狸会在玩家来抓之前跳到隔壁洞口里。

from random import choice,randrange
def catchMe(n=5,maxStep=10):
    '''模拟抓小狐狸,一共n个洞口,允许抓maxStep次
    如果失败,小狐狸就会跳到隔壁洞口'''
    # n个洞口,有狐狸为1,没有狐狸为0
    positions = [0] * n
    # 狐狸的随机位置
    oldPos = randrange(0,n)
    positions[oldPos] = 1

    # 抓maxStep次
    while maxStep >= 0:
        maxStep -= 1
        # 这个循环保证用户输入的是有效洞口编号
        while True:
            try:
                x = input('今天打算打开哪个洞口(0-{0}):'.format(n-1))
                # 如果输入的不是数字,就会跳转到except部分
                x = int(x)
                # 如果输入的洞口有效,结束这个循环,否则就继续输入
                assert 0 <= x < n,'要按套路来啊,再给你一次机会。'
                break
            except:
                # 如果输入的不是数字,就执行这里的代码
                print('要按套路来啊,再给你一次机会。')
        if positions[x] == 1:
            print('成功,我抓到小狐狸啦。')
            break
        else:
            print('今天又没抓到。')

        # 如果这次没抓到,狐狸就跳到隔壁洞口
        if oldPos == n-1:
            newPos = oldPos - 1
        elif oldPos == 0:
            newPos = oldPos + 1
        else:
            newPos = oldPos + choice((-1,1))
        positions[oldPos],positions[newPos] = 0,1
        oldPos = newPos
    else:
        print('放弃吧,你这样乱试是没有希望的。')
# 启动游戏,开始抓狐狸吧
catchMe()

汉诺塔问题

据说古代有一个梵塔,塔内有三个底座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个和尚想把这64个盘子从A座移到C座,但每次只能允许移动一个盘子。在移动盘子的过程中可以利用B座,但任何时候3个座上的盘子都必须始终保持大盘在下、小盘在上额顺序。如果只有一个盘子,则不需要利用B座,直接将盘子从A移动到C即可。

def hannoi(num,src,dst,temp=None):
    if num < 1:
        return
    global times    # 声明用来记录移动次数的变量为全局变量
    # 递归调用函数本身,先把除最后一个盘子之外的所有盘子移动到临时柱子上
    hannoi(num-1,src,temp,dst)
    # 移动最后一个盘子
    print('The {0} Times move:{1}-->{2}'.format(times,src,dst))
    towers[dst].append(towers[src].pop())
    for tower in 'ABC':    # 输出3根柱子上的盘子
        print(tower,':',towers[tower])
    times += 1
    # 把除最后一个盘子之外的其他盘子从临时柱子上移动到目标柱子上
    hannoi(num-1,temp,dst,src)
times = 1   # 用来记录移动次数的变量
n = 3   # 盘子的数量
towers = {'A':list(range(n,0,-1)),
          'B':[],
          'C':[]
          }
# A 表示最初放置盘子的柱子,C是目标柱子,B是临时柱子
hannoi(n,'A','C','B')

凯撒加密

输入一个字符串,然后输入一个整数作为凯撒加密算法的密钥,然后输出该字符串加密后的结果。

import string
def kaisa():
    s = input('请输入一个字符串:')
    k = int(input('请输入一个整数密钥:'))

    lower = string.ascii_lowercase
    upper = string.ascii_uppercase
    before = string.ascii_letters
    after = lower[k:] + lower[:k] + upper[k:] + upper[:k]
    table = str.maketrans(before,after)
    out = s.translate(table)

    print(out)
kaisa()

自定义类模拟三维向量及运算

定义一个三维向量类,并定义相应的特殊方法实现两个该类对象之间的加、减运算(要求支持运算符+、-),实现该类对象与标量的乘、除运算(要求支持运算符*、/),以及向量长度的计算(要求使用属性实现)。

class Vector3:
    # 构造方法,初始化,定义向量坐标
    def __init__(self,x,y,z):
        self.__x = x
        self.__y = y
        self.__z = z

    # 与一个向量相加,对应分量相加,返回新向量
    def __add__(self, anotherPoint):
        x = self.__x + anotherPoint.__x
        y = self.__y + anotherPoint.__y
        z = self.__z + anotherPoint.__z
        return Vector3(x,y,z)

    # 减去另一个向量,对应分量相减,返回新向量
    def __sub__(self, anotherPoint):
        x = self.__x - anotherPoint.__x
        y = self.__y - anotherPoint.__y
        z = self.__z - anotherPoint.__z
        return Vector3(x, y, z)

    # 向量与一个数字相乘,各分量乘以同一个数字,返回新向量
    def __mul__(self, n):
        x, y, z = self.__x*n, self.__y*n, self.__z*n
        return Vector3(x,y,z)

    # 向量除以一个数字,各分量除以同一个数字,返回新向量
    def __truediv__(self, n):
        x, y, z = self.__x/n, self.__y/n, self.__z/n
        return Vector3(x, y, z)

    # 查看向量长度,所有分量平方和的平方根
    @property
    def length(self):
        return (self.__x**2 + self.__y**2 + self.__z**2)
    def __str__(self):
        return 'Vector3({},{},{})'.format(self.__x,
                                          self.__y,
                                          self.__z)

v1 = Vector3(3, 4, 5)
v2 = Vector3(5, 6, 7)
print(v1+v2)
print(v1-v2)
print(v1*3)
print(v2/2)
print(v1.length)

文本文件操作

编写一个程序demo.py,要求运行该程序后,生成demo_new.py文件,其中内容与demo.py一样,只是在每一行的后面加上行号以#开始,并且所有行的#符号垂直对齐。

filename = 'demo.py'
with open(filename, 'r') as fp:
    lines = fp.readlines()
maxLength = len(max(lines, key=len))

lines = [line.rstrip().ljust(maxLength)+'#'+str(index)+'\n'
         for index, line in enumerate(lines)]
with open(filename[:-3]+'_new.py', 'w') as fp:
    fp.writelines(lines)

磁盘垃圾文件清理器

要求程序运行时,通过命令行参数指定要清理的文件夹,然后删除该文件夹及其子文件夹中所有扩展名为tmp、log、obj、txt以及大小为0的文件。

from os.path import isdir,join,splitext
from os import remove,listdir,chmod,stat

filetypes = ('.tmp','.log','.obj','.txt')

def test2(directory):
    if not isdir(directory):
        return
    for filename in listdir(directory):
        temp = join(directory,filename)
        if isdir(temp):
            test2(temp)
        elif splitext(temp)[1] in filetypes or stst(temp).st_size == 0:
            chmod (temp,0o777)
            remove(temp)
            print(temp,'deleted...')
test2(r'D:\test')

你可能感兴趣的:(python,新手村,python习题)