计算机导论课作业 03(基于Python)

1、(10 points)《计算机导论》1.5.4,完成求圆周率-蒙特卡洛法的Python程序,试验不同的times值。试试看10的9次方。

思路:利用解析几何中单位圆的几何意义来构造出单位圆四分之一的点集,利用多次迭代使落在圆内的点比上1*1正方形的面积近似于pi/4,最后将得到的概率乘以4即可近似得到pi的大小

import random

def pi(times):
    sum = 0
    for i in range(times):
        x = random.random()
        y = random.random()
        d2 = x*x+y*y
        if d2 <= 1: sum+=1
    return(sum/times*4)
times=1e10    
x=pi(int(times))
print("Pi=%.8f"%(x))


3、(10 points)请写一个Python程序,利用双层循环完成以下的输出:
******
-*****
–****
—***
----**
-----*
------
第一行打印出6个星号,第二行打印出一个“-”和5个星号,依此类推,到第7行时打印出6个“-”。必须要用双层循环,在内层会有两个循环。

a=int(input("please import a number: \n"))
for i in range(1,a+2):
    for j in range(1,i):
        print("_",end="")
    for j in range(a+1,i,-1):
        print("*",end="")
    print("\n")

4、(10 points)《编程导论》练习题2.1.2 和 2.1.3。

思路1:题目要求循环体内无法使用乘法,我们可以换个思路考虑,不能用乘法但是可以用除法啊!!!
思路2:不在循环体内用乘法就在循环体外用吧,内部用加法代替乘法

#2.1.2
#(1)
x=0;y=0;b=2
for i in range(0,10):
    if x == 0:
        y = b
        print("y = ",y,"x = ",x)
        x += 0.5
    else:
        y = 7.378/(1/x)+b
        print("y = ",y,"x = ",x)
        x += 0.5
#(2)
y=2;x=0;a=7.378*0.5
for i in range(1,10):
    y += a
    x += 0.5
print("y = ",y,"x = ",x)

2.1.3
思路:既然用幂函数运算比较耗时不如用pow函数

a0 = 2
n = int(input("please import a number: \n"))
p = 2
x = 0
for i in range(0,n):
    x += a0 * pow(p,i)
print("the sum of product is ",x)

5、(10 points)(A)完成《编程导论》2.1.2节的第二种方法和第三种方法的Python程序。(B)请问当L=[1,2,3,4,5,6,7,8] 和 L=[8,7,6,5,4,3,2,1] 时这二种方法所需要的比较次数各是多少?

#方法2
L = [12,31,45,79,22]
MIN = MAX =L[0]
for i in range(1,len(L)):
    if MIN>L[i]:MIN = L[i]
    elif MAX<L[i]:MAX = L[i]
print(MAX)
print(MIN)   

#方法3
方法3

L = [12,31,45,79,22]
if L[0]>L[1]:min=L[1];max=L[0]
else: max = L[1]; min = L[0]
for i in range(2,len(L)-1,2):
    if L[i] > L[i+1]:
        if min > L[i+1]:min = L[i+1]
        if max < L[i]:max = L[i]
    else:
        if min > L[i]:min = L[i]
        if max < L[i+1]:max=L[i+1]
if len(L)%2 != 0:
    if min > L[len(L)-1]:min = L[len(L)-1]
    elif max < L[len(L)-1]:max = L[len(L)-1]
print(max,"\n",min)

L=【1,2,3,4,5,6,7,8】
第二种方法 14次
第三种方法 7次
L=【8,7,6,5,4,3,2,1】
第二种方法 7次
第三种方法 7次

6、(10 points)《编程导论》练习题2.1.4,假设x=1, y=1, 找出是否有数列元素是11的倍数也是13的倍数,打印出此数。(请注意沙老师出题时也不知道有没有这个数!所以沙老师也很好奇你的答案。)

x = int(input("please enter x as the first number \n"))
y = int(input("please enter y as the second number \n"))
a = int(input("The first common factor of the aiming number is \n"))
b = int(input("The second common factor of the aiming number is \n"))

L=[]#该程序未判定输入的第一第二项是否符合同除的条件
L.append(x)#由于修改的代码多于目前已写的代码量,且考虑到一般情况,故此处不判断第一第二项
L.append(y)
while(1):
    z = x + y
    x = y
    y = z
    L.append(z)
    if(z % a == 0):
        if(z % b == 0):
            break
print(L)


7、(10 points)《编程导论》练习题2.5.1,(A)完成及试验书中二分法的Python程序,(B)请解释为什么二分查找的前提是所搜寻的列表为排好序的列表?假设列表长度为100000,请问用二分查找法最多找几次能知道答案?(C)你能用递归函数的方式来完成此二分查找吗?

#A
def binary_search(L,a):
    min = 0
    max = len(L) - 1
    mid = (max + min) //2
    while not(L[mid] == a) and (min <= max):
        if L[mid] < a:
            min = mid + 1
        else:
            max = mid - 1
        mid = (min + max) // 2
    if L[mid] == a:
        return mid
    else:return -1
L = [1,2,3,4]
a = binary_search(L,99)
print(a)


#C
def binary_itration(L,a,min,max,b):
    mid = (min + max)//2
    if b == mid:
        return -1
    if L[min] == a:
        return min
    if L[max] == a:
        return max
    if L[mid] < a:
        min = mid 
        b = mid
        return binary_itration(L,a,min,max,b)
    elif L[mid] > a:
        max = mid 
        b = mid
        return binary_itration(L,a,min,max,b)
    elif L[mid] == a:
        return mid
    
X=[1,2,3,4,5,6,7,8]
a=binary_itration(X,8,0,len(X)-1,-1)
print(a)



9、(10 points)《编程导论》2.5.1 节的排序算法,(A)完成选择排序和插入排序的python程序。(B)假设输入的列表是反向的,从大到小:例如N=10000;L=[i for i in range(N, 0,-1)],请分析这两种排序算法所需要的“比较”次数。哪个算法比较快?

import time;

def selectionsort(L):
    start = time.clock()
    for i in range(len(L)-1):
        min = i
        for j in range(i+1,len(L)):
            if L[j] < L[min]:min = j
        tempt = L[min]
        L[min] = L[i]
        L[i] = tempt
    timeusing = time.clock() - start
    printf("selection sort is ",timeusing)
    return L



def insertion(L,a):
    for i in range(len(L)):  
        if L[i]>a:
            L0 = L[0:i]
            L1 = L[i:len(L)]
            return L0+[a]+L1
    return L+[a]

def insertionsort(L):
    start = time.clock()
    L0=[]
    for i in L:
        L0 = insertion(L0,i)
    timeusing = time.clock() - start
    printf("insertionsort sort is ",timeusing)
    return L0

L=list(range(10000,0,-1))
X=list(range(10000,0,-1))
a= selectionsort(L)
print(a)
n= insertionsort(X)
print(n)

10、(10 points)《编程导论》练习题2.5.2

L = [12,11,3,11,6,11,12,3,11]


def statistic_size(L):
    L0 = []
    L1 = list(set(L))
    for e in L1:
        count = 0
        for i in L:
            if e == i:
                count += 1
        L2 = [e,count]
        L0.append(L2)
    return L0

A=statistic_size(L)
print(A)

11、(10 points)《编程导论》练习题2.5.3。对于出现次数相同的元素的顺序是按照其值从小到大排序。

L = list(map(int,input().split(",")))

def statistic_sort(L,i):
    a = L[i+1]
    for index in range(i+1):#对L[i][1]进行比较之后再排序
        if L[index][1] > a[1]:break
    else:index = i+1
    for k in range(i+1,index,-1):
        L[k]=L[k-1]
    L[index] = a
    return L


def statistic_size(L):
    L0 = []
    L1 = list(set(L))
    for e in L1:
        count = 0
        for i in L:
            if e == i:
                count += 1
        L2 = [e,count]
        L0.append(L2)
    return L0



A=statistic_size(L)
print(A)
for i in range(len(A)-1):
    A = statistic_sort(A,i)

print(A)

12、(15 points)
改写扑克牌游戏,我要你模拟不同情况下庄家的胜率。(A)按照原来的规则,庄家是等所有玩家结束后,他才开始玩牌,假设我们改变规则,庄家不是最后一个翻牌,而是先翻牌,他的胜率会降低吗?请你模拟多次比赛,最好让程序自动模拟玩家和庄家(不是手动输入),计算庄家得胜率。(B)假设庄家不是用17作为继续拿牌的标准,而是用16,18,19?其得胜率会有什么改变?这题是不是很有趣。其实这就是科研的探索。你还能想到其他什么不同的规则来测试呢?

(当年把PYTHON当成C语言写了)

def Poker():#生成牌
    Number = ['A',2,3,4,5,6,7,8,9,'J','Q','K']
    Type = ["♦","♣","♥","♠"]
    L = []
    for i in range(len(Number)):
        for e in range(len(Type)):
            L.append([Number[i],Type[e]]) 
    return L


def shuffle(L):#打乱牌库
    for i in range(len(L)):
        j = random.randint(0,len(L)-1)
        L[j],L[i] = L[i],L[j]
    return L


def Player_data(Playernumber):#输入参与的人数,52张牌最多只有6个人
    Players = []#有几个人参与,如闲家为1则参与人数为2
    if 2 <= Playernumber:
        if Playernumber <= 6:
            for i in range(Playernumber):
                Players.append("Player"+str(i))#初始化玩家的名字,并默认玩家1为庄家
    else:
        print("人数不满足要求")
        return 0
    return Players

    
def deal1(Players,Poker):  #进行发牌
    L = []
    for i in range(len(Players)):
        a = 2
        X = []
        X.append("Players"+str(i+1))
        while a > 0:
            j = random.randint(0,len(Poker)-1)
            X.append(Poker[j])
            #给玩家发牌
            del Poker[j]#并删除掉Poker的其中一张牌
            
            a -= 1
        L.append(X)
    return L,Poker

def situation_1(L):#展现一下场上的情况
    A = L[0].pop()
    for i in range(len(L)):
        print(L[i])
    L[0].append(A)


def decide(Person,Poker):#询问个人是否n进行选择
    while 1:
        choice = input("是否选择继续抽牌?请输入“y”或者“n”来继续游戏\n")
        if choice == "y" or choice == "Y":
            j = random.randint(0,len(Poker))
            Person.append(Poker[j])
            del Poker[j]
            print(Person)
        elif choice =="n" or choice == "N":
            return Person,Poker
        else:
            print("请输入正确的指令")
    

def point(player):#计分
    sum = 0 
    A = 0
    for i in range(1,len(player)):
        if player[i][0] == "J":
            
            sum += 10
        elif player[i][0] == "Q":
            sum += 10
        elif player[i][0] == "K":
            sum += 10
        elif player[i][0] != "A":
            
            sum += player[i][0]

    for i in range(1,len(player)):
        if player[0] == "A":
            A += 1
    sum1 = sum
    max = 0
    sumA = 0
    for i in range(A+1):
        sumA = i + (A-i)*11
        if (sumA + sum) <=21 and sumA > max:
            max = sumA
            sum1 = max + sum
    if sum1 == sum:
        sum += A
    else:
        return sum1
    return sum


def deal2(person,Poker):#给庄家发牌
    j=random.randint(0,len(Poker)-1)
    person.append(Poker[j])
    del Poker[j]
    return person,Poker


def Judge(player2,player1,Poker,win,lose,draw):#判断闲家输赢,给庄家发牌并判断输赢
    sum2 = int(point(player2))

    if sum2 > 21:
        print("你输了")
        lose += 1
        print("你的点数为%d"%sum2)
        return win,lose,draw

    sum1 = int(point(player1))


    while sum1 < 17:
        player1,Poker = deal2(player1,Poker)
        sum1 = int(point(player1))


    if sum1 > 21:
        print("你赢了!")
        win += 1
        print(sum1,sum2)
        return win,lose,draw
    else:
        if sum1 < sum2:
            print("你赢了!")
            win += 1
            print(sum1,sum2)
            return win,lose,draw
        elif sum1 > sum2:
            print("你输了")
            lose += 1
            print(sum1,sum2)
            return win,lose,draw
        elif sum1 == sum2:
            print("平局")
            draw += 1
            print(sum1,sum2)
            return win,lose,draw

        
Random_Poker = shuffle(Poker())#先进行洗牌,得到乱序的牌堆
Player = Player_data(2)#c初始化玩家数据
first_deal,Random_Poker = deal1(Player,Random_Poker)#第一次发牌,并删除发出的牌
situation_1(first_deal)#展现一下场上的情况
num1 = first_deal[0]
num2 = first_deal[1]

win = 0
lose = 0
draw = 0

num2,Random_Poker = decide(num2,Random_Poker)#选择是否继续抽牌
win,lose,draw=Judge(num2,num1,Random_Poker,win,lose,draw)#停止抽牌后判断胜负


#print(Random_Poker)

自动运行

#(自动运行版本)
import random

def Poker():#生成排好顺序的牌
    Number = ['A',2,3,4,5,6,7,8,9,'J','Q','K']
    Type = ["♦","♣","♥","♠"]
    L = []
    for i in range(len(Number)):
        for e in range(len(Type)):
            L.append([Number[i],Type[e]]) 
    return L


def shuffle(L):#打乱牌库
    for i in range(len(L)):
        j = random.randint(0,len(L)-1)
        L[j],L[i] = L[i],L[j]
    return L


def Player_data(Playernumber):#输入参与的人数,52张牌最多只有6个人
    Players = []#有几个人参与,如闲家为1则参与人数为2
    if 2 <= Playernumber:
        if Playernumber <= 6:
            for i in range(Playernumber):
                Players.append("Player"+str(i))#初始化玩家的名字,并默认玩家1为庄家
    else:
        print("人数不满足要求")
        return 0
    return Players

    
def deal1(Players,Poker):  #进行发牌
    L = []
    for i in range(len(Players)):
        a = 2
        X = [] #生成一个列表,里面装着i个列表元素
        X.append("Players"+str(i+1))#每一个列表元素里面第一个内容是字符串“Player(i)
        while a > 0:  #每个玩家发两张牌
            j = random.randint(0,len(Poker)-1)
            X.append(Poker[j])
            
            del Poker[j]#并删除掉Poker的其中一张牌
            
            a -= 1
        L.append(X)
    return L,Poker#返回玩家和所获得牌,并删除四张已经发下来的牌


def point(player):#计分
    sum = 0 
    A = 0
    for i in range(1,len(player)):
        if player[i][0] == "J":
            
            sum += 10
        elif player[i][0] == "Q":
            sum += 10
        elif player[i][0] == "K":
            sum += 10
        elif player[i][0] != "A":
            
            sum += player[i][0]

    for i in range(1,len(player)):
        if player[0] == "A":
            A += 1
    sum1 = sum
    max = 0
    sumA = 0
    for i in range(A+1):
        sumA = i + (A-i)*11
        if (sumA + sum) <=21 and sumA > max:
            max = sumA
            sum1 = max + sum
    if sum1 == sum:#如果发现上一个for循环没加上数,说明A全取1的数值都会导致数据大于21点,所以下方直接让sum加上i个1
        sum += A
    else:
        return sum1
    return sum


def auto(Person,Poker):#让程序自动决定是否抽牌,输入的数值为闲家的数据,并输入剩余的48张牌
    judge_number = int(point(Person))
    while 1:
        a = random.random()#生成抽牌的概率
        if judge_number <= 11:#数据小于等于11则选择抽
            j = random.randint(0,len(Poker)-1)
            Person.append(Poker[j])
            del Poker[j]
            judge_number = point(Person)
        elif 11 < judge_number <= 21:#每当数据大于11一个单位,则抽的概率减少10%.
            
            if a > 0.1*(judge_number - 11):
                j = random.randint(0,len(Poker)-1)
                Person.append(Poker[j])
                del Poker[j]
                judge_number = point(Person)
            else:return Person,Poker
        else:
            return Person,Poker
            
        





def deal2(person,Poker):#给庄家发牌
    j=random.randint(0,len(Poker)-1)
    person.append(Poker[j])
    del Poker[j]
    return person,Poker


def Judge(player2,player1,Poker,win,lose,draw):#判断闲家输赢,给庄家发牌并判断输赢
    sum2 = int(point(player2))

    if sum2 > 21:
        print("你输了")
        lose += 1
        print(player1)
        print(player2)
        print("你的点数为%d"%sum2)
        
        return win,lose,draw

    sum1 = int(point(player1))


    while sum1 < 17:
        player1,Poker = deal2(player1,Poker)
        sum1 = int(point(player1))


    if sum1 > 21:
        print("你赢了!")
        win += 1
        print(player1)
        print(player2)
        print(sum1,sum2)
        
        return win,lose,draw
    else:
        if sum1 < sum2:
            print("你赢了!")
            win += 1
            print(player1)
            print(player2)
            print(sum1,sum2)
            return win,lose,draw
        elif sum1 > sum2:
            print("你输了")
            lose += 1
            print(player1)
            print(player2)
            print(sum1,sum2)
            return win,lose,draw
        elif sum1 == sum2:
            print("平局")
            print(player1)
            print(player2)
            draw += 1
            print(sum1,sum2)
            return win,lose,draw

def matching():
    win=0
    lose=0
    draw=0
    
    Random_Poker = shuffle(Poker())#先进行洗牌,得到乱序的牌堆
    Player = Player_data(2)#c初始化玩家数据
    first_deal,Random_Poker = deal1(Player,Random_Poker)#第一次发牌,并删除发出的牌

        
    num1 = first_deal[0]
    num2 = first_deal[1]
    num2,Random_Poker = auto(num2,Random_Poker)#程序选择抽牌

    win,lose,draw=Judge(num2,num1,Random_Poker,win,lose,draw)#停止抽牌后判断胜负,并记录输赢和的次数
    #由于只需要计算庄家胜利的概率,故返回lose的次数即可。
    return lose
        
    

def main():
    times = int(input("输入模拟次数:"))
    sUm = 0
    for i in range(times):
        sUm += matching()
    print("--------------模拟完成--------------")
    print("庄家获胜概率为:",sUm/times)

if __name__ == "__main__":
main()

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值