2 同计算机导论实例4-3“绘制一个半径为r的圆”,请利用小乌龟绘画出任意k的正k边形。
from turtle import *
import math
def jumpto(x,y):
up();goto(x,y);down()
def step(r,k):
S = math.radians(90*(1-2/k))
return ((2*r)/math.tan(S))
def draw(x,y,r,k):
S = step(r,k)
speed(1000);jumpto(x,y)
for i in range(k):
forward(S)
left(360/k)
draw(0,0,50,30)
s=Screen()
s.exitonclick()
from turtle import *
reset()
k=int(input())
for i in range(k):
forward(720/k)
left(360/k)
s=Screen()
s.exitonclick()
3、 (10 points)小乌龟程序练习题4.8.1
from turtle import *
for i in range(5):
forward(100)
right(180-36)
s=Screen()
s.exitonclick()
4、 (10 points)小乌龟程序练习题4.8.2
from turtle import *
def jumpto(x,y):
up()
goto(x,y)
down()
speed(2000)
for i in range(4):
jumpto(0,-20*i)
circle(50+20*i)
for i in range(0,90,6):
jumpto(0,50)
left(i)
for j in range(4):
forward(100)
left(90)
S=Screen()
S. exitonclick(
注意对于找假币问题,我们假设只有一个天平,天平两端放钱币(可以任意多个)后,天平可以知道哪边比较重或轻。你可以调用两个sum()值的比较来“模拟”天平。注意你没有一个“秤”能得出钱币的实际重量,你只能利用天平得出两堆钱币的相对重量轻重。
5、 (每题6 points)练习题5.1.1, 5.1.2, 5.1.3, 5.1.5
#练习题5.1.1,
import random
L=[]
n = int(input())
fake = random.randint(0,n-1)
for i in range(n):
L.append(3)
L[fake]=2
print(L)
for i in range(len(L)-1):
if L[i]==L[i+1]:
continue
elif L[i]>L[i+1]:
print(i+2)
break
else:print(i+1);break
#5.1.2,
import random
L=[]
n = int(input())
fake = random.randint(0,n-1)
for i in range(n):
L.append(3)
L[fake]=2
#L=[3,3,3,3,3,2,3,3,3,3,3]
print(L)
if len(L) <= 1:
print("硬币太少")
else:
x=len(L)
y = 0
L1 = L[:x//2]
L2 = L[x//2:x//2*2]
while(len(L1)>1):
K1 = sum(L1)
K2 = sum(L2)
#print(K1," ",K2)
if(K1 == K2):
print("假币是第%d枚"%(x+y))
break
elif(K1>K2):#从右边找
x//=2
y+=x
L1 = L2[:x//2]
L2 = L2[x//2:x//2*2]
#print(L1," ",L2)
#print(x," ",y)
elif(K2>K1):
x//=2
L2 = L1[x//2:x//2*2]
L1 = L1[:x//2]
#print(L1," ",L2)
#print(x," ",y)
if(len(L1)==1):
if L1[0]>L2[0]:
print("假币是第%d枚"%(2+y))
elif L1[0]<L2[0]:
print("假币是第%d枚"%(1+y))
else:
print("假币是第%d枚"%(3+y))
#5.1.3,
def findcoin(a,L):
x=len(L)
print(a,L)
if(x==1):return(a)
if x%2:
x-=1
y=1
else:y=0
if(sum(L[:x//2])<sum(L[x//2:x])):
return(findcoin(a,L[:x//2]))
elif(sum(L[:x//2])>sum(L[x//2:x])):
return(findcoin(a+x//2,L[x//2:x]))
else:
if (y==0):return(-1)
else:
if(L[x]<L[0]):return(a+x)
else:return(-1)
import random
L=[]
n = int(input())
fake = random.randint(0,n-1)
for i in range(n):
L.append(3)
L[fake]=2
a=findcoin(0,L)
print(a+1)
5.1.5
方法一:逐个比较n-1次
方法二:三分法,分成三份,
如果有两份较轻,就从两份中继续三分法
如果只有一份轻,
那么就是三分法里面没放进去的一个硬币或者两个硬币中有假币
一个硬币不用比较,两个硬币比较一次可以得到,剩下在那一份轻的硬币中继续三分法
如果三份质量相同,那就是没有进行比较的两个银币均为假币
6、 (10 points)练习题 5.1.7,编程。
Q=[[0,0],[0,0]]
import random
L=[]
n = int(input())
fake = random.randint(0,n-1)
rand = random.random()
for i in range(n):
L.append(3)
if rand > 0.5:
L[fake]+=1
else:
L[fake]-=1
print(L)
Q[0][0]=L[0]
Q[0][1]+=1
for i in range(1,len(L)):
if Q[0][0]==L[i]:
Q[0][1]+=1
else:
Q[1][0]=L[i]
Q[1][1]+=1
print(Q)
if (Q[0][1] == 1 and Q[1][1]>=2):
a=(Q[0][1]+Q[1][1])
print("第%d枚硬币是假币"%a)
break
elif(Q[1][1] == 1 and Q[0][1]>=2):
a=(Q[0][1]+Q[1][1])
print("第%d枚硬币是假币"%a)
Break
7、 (10 points)改写Hanoi 程序, 假设A杆起初有n个圆盘, 从小到大编号为1,2,…, n,请打印出每次移动后A, B, C上的圆盘编号从小到大有哪些。请试验n=4. 这题可以与一位同学合作。
count=1
def main():
n=int(input("盘子个数"))
A=[['A'],[]];B=[['B'],[]];C=[['C'],[]]
for i in range(n,0,-1):
A[1].append(i)
Hanoi(n,A,B,C)
def Hanoi(n,A,B,C):
global count
if n == 1:
print("%d %s->%s"%(count,A[0][0],C[0][0]))
C[1].append(A[1].pop())
print(A[0][0],A[1],B[0][0],B[1],C[0][0],C[1])
count+=1
elif n > 1:
Hanoi(n-1,A,C,B)
Hanoi(1,A,B,C)
Hanoi(n-1,B,A,C)
if __name__=="__main__":
main()
8、 (10 points) 编程导论 习题4.1
List=[1,2,3,4,12,45,6,0]
def min_max(List,L,R):
if (R-L)==1:
if List[L]<List[R]:
return List[L],List[R]
else:
return List[R],List[L]
if L==R:
return List[L],List[L]
if L>R:
return [],[]
mid = (L + R) // 2
min1,max1 = min_max(List,mid,R)
min2,max2 = min_max(List,L,mid)
if min1<min2:
MIN = min1
else:
MIN = min2
if max1>max2:
Max = max1
else:
Max = max2
return MIN,Max
MIN,MAX=min_max(List,0,len(List)-1)
print(MIN," ",MAX)
9、 (10 points) 编程导论 习题4.2
L=[1,2,3,4,5]
time = 0
def ave(L,n):
if len(L)==1:
return L[0]
return (L[0]+ave(L[1:],n-1)*(n-1))/n
a = ave(L,len(L))
print(a)
10、 (12 points)给定一个整数列表L输出一个列表S,其中S[i]=L[0]到L[i]的和。例如L=[1,2,4,2], 则输出S=[1,3,7,9]。用二种递归方式做Python编程。
A)用简单递归(不是二分法)方式实现此程序
L=[1,2,4,2]
def SUM(L):
A = []
if len(L) == 1:
A+=[L[0]]
return L[0],A
else:
num,K=SUM(L[:len(L)-1])
num+=L[len(L)-1]
K.append(num)
return num,K
a,K = SUM(L)
print(a,K)
B) 再用二分递归方式来实现此程序。
L=[1,2,3,4,5,6,7,8]
def SUM(L):
A = []
if len(L) == 1:
A+=[L[0]]
return A
else:
A1 = SUM(L[:len(L)//2])
A2 = SUM(L[len(L)//2:])
for i in range(len(A2)):
A2[i]+=A1[len(A1)-1]
A1 += A2
return A1
K = SUM(L)
print(K)
11、 (8 points)计算机导论的程序练习题 5.3.2。 试验和解释。
def FA(a,b,c):
carry = 0;sum = 0
if (( a==1 and b == 1) or (b==1 and c == 1) or (a==1 and c ==1 )):
carry = 1
if(( a== 1 and b == 1 and c == 1)or(a==1 and b == 0 and c == 0)or(a==0 and b == 1 and c == 0) or (a==0 and b == 0 and c == 1)):
sum = 1
return carry,sum
def add_B(x,y,c=0):
while(len(x)<len(y)):
x = [0]+x
while(len(x)>len(y)):
y = [0]+y
if len(x) == 1:
ctemp ,stemp = FA(x[0],y[0],c)
return(ctemp,[stemp])
if len(x) == 0:
return c,[]
c1,s1 = add_B(x[len(x)//2:len(x)],y[len(y)//2:len(y)],c)
c2,s2 = add_B(x[0:len(x)//2],y[0:len(y)//2],0)
c3,s3 = add_B(x[0:len(x)//2],y[0:len(y)//2],1)
if c1 == 0:
return(c2,s2+s1)
if c1 == 1:
return(c3,s3+s1)
L1=[0,0,0,1,1,1]
L2=[1,1,1]
a,b=add_B(L1,L2,1)
b=[a]+b
while(b[0]==0):
b=b[1:]
print(b)