True/False
- False
- False
- True
- True
- True
- False
- True
- False
- False
- False
Multiple Choice
- b
- c
- d
- a
- c
- a
- b
- a
- a
- b
Discussion
-
- randrange(11)
- random() - 0.5
- randrange(1,7)
- randrange(1,7) + randrange(1,7)
- random()*20 - 10.0
- The issue here is mainly comfort/risk. When there is uncertainty whether the problem can even be solved, starting with an experimentatl prototype is probably a good idea.
Programming Exercises
1.
解法一(绝对正确)
# c09ex01.py
# Racquetball best of n games
from random import random
def main():
printIntro()
probA, probB, n, matches = getInputs()
winsA, winsB = simMatches(matches, n, probA, probB)
printSummary(winsA, winsB)
def printIntro():
# Prints an introduction to the program
print("This program simulates racquetball matches between two")
print('players called "A" and "B". The abilities of each player is')
print("indicated by a probability (a number between 0 and 1) that")
print("the player wins the point when serving. Player A always")
print("serves first in the first game of a match, and the first")
print("service alternates in subsequent games. \n")
def getInputs():
# RETURNS probA, probB, number of games to simulate
a = float(input("What is the prob. player A wins a serve? "))
b = float(input("What is the prob. player B wins a serve? "))
n = int(input("How many games are in a match? "))
m = int(input("How many matches should be simulated? "))
return a, b, n, m
def simMatches(howMany, n, probA, probB):
# Simulates n games of racquetball between players A and B
# RETURNS number of wins for A, number of wins for B
winsA = winsB = 0
for i in range(howMany):
gamesA, gamesB = simOneMatch(n, probA, probB)
if gamesA > gamesB:
winsA = winsA + 1
else:
winsB = winsB + 1
return winsA, winsB
def simOneMatch(n, probA, probB):
gamesA = gamesB = 0
needed = n/2 + 1
while gamesA < needed and gamesB < needed:
# Alternate serves, A serves first game of match
if (gamesA + gamesB) % 2 == 1:
firstServe = "A"
else:
firstServe = "B"
scoreA, scoreB = simOneGame(probA, probB, firstServe)
if scoreA > scoreB:
gamesA = gamesA + 1
else:
gamesB = gamesB + 1
return gamesA, gamesB
def simOneGame(probA, probB, Server):
# Simulates a single game or racquetball between players A and B
# RETURNS A's final score, B's final score
serving = Server
scoreA = 0
scoreB = 0
while not gameOver(scoreA, scoreB):
if serving == "A":
if random() < probA:
scoreA = scoreA + 1
else:
serving = "B"
else:
if random() < probB:
scoreB = scoreB + 1
else:
serving = "A"
return scoreA, scoreB
def gameOver(a,b):
# a and b are scores for players in a racquetball game
# RETURNS true if game is over, false otherwise
return a == 15 or b == 15
def printSummary(winsA, winsB):
# Prints a summary of wins for each player.
n = winsA + winsB
print("\nMatches simulated:", n)
print("Wins for A: {0} ({1:0.1%})".format(winsA, winsA/n))
print("Wins for B: {0} ({1:0.1%})".format(winsB, winsB/n))
if __name__ == "__main__": main()
解法二(不知道对不对)
from random import *
def main():
printIntro()
probA,probB,n = getInputs()
winsA,winsB = simNGames(n,probA,probB)
printSummary(winsA,winsB)
def printIntro():
print('This program simulates a game of racquetball between two ')
print('players called "A" and "B". The ability of each player is')
print('indicated by a probability (a number between 0 and 1) that')
print("the player wins the point when serving. Player A always")
print('has the first serve.')
def getInputs():
a = float(input("What is the prob.player A wins a serve? "))
b = float(input("What is the prob.player B wins a serve? "))
n = int(input("How many games to simulate?"))
return a,b,n
def simNGames(n,probA,probB):
winsA = winsB = 0
for i in range(n):
scoreA,scoreB = simOneGame(probA,probB,i)
if scoreA > scoreB:winsA = winsA + 1
if scoreB > scoreA:winsB = winsB + 1
return winsA,winsB
def simOneGame(probA,probB,i):
scoreA,scoreB = 0,0
if i % 2 == 0:serving = 'B'
else:serving = 'A'
while not gameOver(scoreA,scoreB):
if serving == 'A':
if random() < probA:
scoreA = scoreA + 1
else:serving = 'B'
else:
if random() < probB:scoreB = scoreB + 1
else:serving = 'A'
return scoreA,scoreB
def gameOver(a,b):
return a==15 or b == 15
def printSummary(winsA,winsB):
n = winsA + winsB
print('\nGames simulated:',n)
print('Wins for A: {0} ({1:0.2%})'.format(winsA,winsA/n))
print('Wins for B: {0} ({1:0.2%})'.format(winsB,winsB/n))
if __name__ =='__main__':main()
2.
解法一
from random import *
def main():
printIntro()
probA,probB,n = getInputs()
winsA,winsB,a0,b0 = simNGames(n,probA,probB)
printSummary(winsA,winsB,a0,b0)
def printIntro():
print('This program simulates a game of racquetball between two ')
print('players called "A" and "B". The ability of each player is')
print('indicated by a probability (a number between 0 and 1) that')
print("the player wins the point when serving. Player A always")
print('has the first serve.')
def getInputs():
a = float(input("What is the prob.player A wins a serve? "))
b = float(input("What is the prob.player B wins a serve? "))
n = int(input("How many games to simulate?"))
return a,b,n
def simNGames(n,probA,probB):
winsA = winsB = 0
a0 = b0 =0
for i in range(n):
scoreA,scoreB = simOneGame(probA,probB)
if scoreA > scoreB:winsA = winsA + 1
if scoreB > scoreA:winsB = winsB + 1
if scoreA == 0:b0 = b0 + 1
if scoreB == 0:a0 = a0 + 1
return winsA,winsB,a0,b0
def simOneGame(probA,probB):
serving,scoreA,scoreB = 'A',0,0
while not gameOver(scoreA,scoreB):
if serving == 'A':
if random() < probA:
scoreA = scoreA + 1
else:serving = 'B'
else:
if random() < probB:scoreB = scoreB + 1
else:serving = 'A'
return scoreA,scoreB
def gameOver(a,b):
return a == 15 or b == 15 or (a == 7 and b ==0) or (a == 0 and b == 7)
def printSummary(winsA,winsB,a0,b0):
n = winsA + winsB
print('\nGames simulated:',n)
print('Wins for A: {0} ({1:0.2%})'.format(winsA,winsA/n),end =' ')
print('Shutouts for A: {}({:.2%})'.format(a0,a0/winsA))
print('Wins for B: {0} ({1:0.2%})'.format(winsB,winsB/n),end =' ')
print('Shutouts for B: {}({:.2%})'.format(b0,b0/winsB))
if __name__ =='__main__':main()
解法二
from random import random
def main():
printIntro()
probA, probB, n = getInputs()
winsA, shutsA, winsB, shutsB = simNGames(n, probA, probB)
printSummary(winsA, shutsA, winsB, shutsB)
def printIntro():
# Prints an introduction to the program
print("This program simulates a game of racquetball between two")
print('players called "A" and "B". The abilities of each player is')
print("indicated by a probability (a number between 0 and 1) that")
print("the player wins the point when serving. Player A always")
print("has the first serve.\n")
def getInputs():
# RETURNS probA, probB, number of games to simulate
a = float(input("What is the prob. player A wins a serve? "))
b = float(input("What is the prob. player B wins a serve? "))
n = int(input("How many games to simulate? "))
return a, b, n
def simNGames(n, probA, probB):
# Simulates n games of racquetball between players A and B
# RETURNS number of wins for A, number of wins for B
winsA = winsB = 0
shutsA = shutsB = 0
for i in range(n):
scoreA, scoreB = simOneGame(probA, probB)
if scoreA > scoreB:
winsA = winsA + 1
if scoreB == 0:
shutsA = shutsA + 1
else:
winsB = winsB + 1
if scoreA == 0:
shutsB = shutsB + 1
return winsA, shutsA, winsB, shutsB
def simOneGame(probA, probB):
# Simulates a single game or racquetball between players A and B
# RETURNS A's final score, B's final score
serving = "A"
scoreA = 0
scoreB = 0
while not gameOver(scoreA, scoreB):
if serving == "A":
if random() < probA:
scoreA = scoreA + 1
else:
serving = "B"
else:
if random() < probB:
scoreB = scoreB + 1
else:
serving = "A"
return scoreA, scoreB
def gameOver(a,b):
# a and b are scores for players in a racquetball game
# RETURNS true if game is over, false otherwise
return a == 15 or b == 15 \
or (a == 7 and b == 0) \
or (b == 7 and a == 0)
def printSummary(winsA, shutsA, winsB, shutsB):
# Print a nicely formatted report
n = winsA + winsB
print("Summary of", n , "games:")
print()
print(" wins (% total) shutouts (% wins) ")
print("--------------------------------------------")
printLine("A", winsA, shutsA, n)
printLine("B", winsB, shutsB, n)
def printLine(label, wins, shuts, n):
template = "Player {0}: {1:4} ({2:6.1%}) {3:11} ({4})"
if wins == 0: # Avoid division by zero!
shutStr = "------"
else:
shutStr = "{0:6.1%}".format(shuts/wins)
print(template.format(label, wins, wins/n, shuts, shutStr))
if __name__ == "__main__": main()
3 正确性有待验证,正确的关键在gameResult(),oneGameResult()函数存在某种缺陷,导致不能实现比赛规则
from random import *
def main():
print('This is a python program simulating the volleyball games.')
n,pa,pb = getinput()
wa,wb = gameResult(n,pa,pb)
result(n,wa,wb)
def getinput():
n = int(input("Enter the times to be simulate: "))
pa = float(input("Enter the winning probability of team A: "))
pb = float(input("Enter the winning probability of team B: "))
return n,pa,pb
def finCondition(sa,sb):
if sa > 14 and sb > 14 and abs(sa - sb) > 1:
return True
else:return False
def oneGameResult(pa,pb):
serving = 'A'
if serving == "A":
if random() < pa:
sa += 1
else:serving = 'B'
if serving == "B":
if random() < pb:
sb += 1
else:serving = 'A'
def gameResult(n,pa,pb):
wa = wb =0
for i in range(n):
sa = sb = 0
while not finCondition(sa,sb):
serving = 'A'
if serving == "A":
if random() < pa:
sa += 1
else:serving = 'B'
if serving == "B":
if random() < pb:
sb += 1
else:serving = 'A'
if sa > sb:wa += 1
if sa < sb:wb += 1
return wa,wb
def result(n,wa,wb):
print("Games simulated: {}".format(n))
print("Wins for A: {} Winning percentage for A: {:.2%}".format(wa,wa/n))
print("Wins for B: {} Winning percentage for B: {:.2%}".format(wb,wb/n))
if __name__ == '__main__':
main()
4 正确性有待验证,oneGameResult()函数存在某种缺陷,导致不能实现比赛规则
from random import *
def main():
print('This is a python program simulating the volleyball games.')
n,pa,pb = getinput()
wa,wb = gameResult(n,pa,pb)
result(n,wa,wb)
def getinput():
n = int(input("Enter the times to be simulate: "))
pa = float(input("Enter the shooting accuracy of team A: "))
pb = float(input("Enter the shooting accuracy of team B: "))
return n,pa,pb
def finCondition(sa,sb):
if sa == 25 or sb == 25:
return True
else:return False
def oneGameResult(pa,pb):
serving = 'A'
if serving == "A":
if random() < pa:
sa += 1
else:serving = 'B'
if serving == "B":
if random() < pb:
sb += 1
else:serving = 'A'
def gameResult(n,pa,pb):
wa = wb =0
for i in range(n):
sa = sb = 0
while not finCondition(sa,sb):
if i % 2 ==0:serving = 'A'
else:serving = "B"
if serving == "A":
if random() > pb:
sa += 1
else:
if random() > pa:
sb += 1
serving = 'B'
if serving == "B":
if random() < pa:
sb += 1
else:
if random() > pa:
sb += 1
serving = 'B'
if sa > sb:wa += 1
if sa < sb:wb += 1
return wa,wb
def result(n,wa,wb):
print("Games simulated: {}".format(n))
print("Wins for A: {} Winning percentage for A: {:.2%}".format(wa,wa/n))
print("Wins for B: {} Winning percentage for B: {:.2%}".format(wb,wb/n))
if __name__ == '__main__':
main()
7
解法一
from random import *
def main():
n = int(input("Enter the times of the game to simulate: "))
wins = simGame(n)
print("Wins: {}\nWinning percentage: {:.2%}".format(wins,wins/n))
def roll():
r = randrange(1,7) + randrange(1,7)
return r
def simGame(n):
wins = losses = 0
for i in range(n):
r1 = roll()
if r1 in [2,3,12]:losses += 1
elif r1 in [7,11]:wins += 1
else:
wins += reRoll(r1)
return wins
def reRoll(r):
while True:
R = roll()
if R == 7:
return 0
break
elif R == r:
return 1
break
if __name__ =="__main__":main()
解法二(绝对正确)
# c09ex07.py
# Simulation of game of craps.
from random import randrange
def main():
print("This program estimates the probability of winning at craps.")
n = int(input("How many games should I simulate? "))
wins = simNGames(n)
print("\nThe player wins", wins, "games.")
print("The estimated probabillity of a win is {0:0.2%}".format(wins/n))
def simNGames(n):
wins = 0
for i in range(n):
if winCraps():
wins = wins + 1
return wins
def winCraps():
roll = rollDice()
if roll == 7 or roll == 11:
return True
elif roll == 2 or roll == 3 or roll == 12:
return False
else:
return rollForPoint(roll)
def rollForPoint(toMake):
roll = rollDice()
while roll != 7 and roll != toMake:
roll = rollDice()
return roll == toMake
def rollDice():
return randrange(1,7) + randrange(1,7)
if __name__ == '__main__':
main()
8
来看一种错误的解法(预测概率37.4%)。你能看出哪里错误吗?在评论区有奖竞答,欢迎读者朋友留言。答对的朋友可以获得python书籍。
from random import *
def main():
print("Simulation of a Blackjack dealer.\n")
n = int(input("How many trials? "))
busts = 0
for i in range(n):
points,hasA = 0,False
while points < 17:
r = randrange(1,14)
if r > 10:r = 10
points,hasA = add(points,r,hasA)
if points > 21:
busts += 1
print('Games simulated: {0}'.format(n))
print("Bust times: {}".format(busts))
print("Estimated bust prob: {:.2%}".format(busts/n))
def add(points,r,hasA):
if r != 1:
if hasA == False:
return points + r,hasA
else:
if points + 10 + r > 16:
return points + 10 + r,hasA
else:
return points + r,hasA
if r == 1:
hasA = True
if 16 < points + r + 10:
return points,hasA
else:
return points + r,hasA
if __name__ == '__main__':main()
正确解法(预测概率28.17%)
# c09ex08.py
# Simulation to Blackjack dealer to estimate bust probability.
from random import randrange
def main():
print("Simulation of a Blackjack dealer.\n")
n = int(input("How many trials? "))
busts = 0
for i in range(n):
points = dealHand()
if points > 21:
busts = busts + 1
print("In %d hands dealer busted %d times." % (n, busts))
print("Estimated prob =", float(busts)/n)
def dealHand():
total = 0
haveAce = False
while total < 17:
card = randrange(1,14)
if card == 1:
haveAce = True
total = total + BJValue(card)
if haveAce:
total = adjustForAce(total)
return total
def BJValue(card):
if card > 10:
return 10
else:
return card
def adjustForAce(total):
if 16 < total + 10 < 22:
return total + 10
else:
return total
if __name__ == '__main__':
main()
9
# c09ex08.py
# Simulation to Blackjack dealer to estimate bust probability.
from random import randrange
def main():
print("Simulation of a Blackjack dealer.\n")
n = int(input("How many trials for each start value? "))
print("\nStart Prob of Bust")
print("-------------------")
for start in range(1,11):
busts = simulateHands(n, start)
print("{0:5} {1:7.2f}".format(start, busts/n))
def simulateHands(n, start):
busts = 0
for i in range(n):
points = dealHand(start)
if points > 21:
busts = busts + 1
return busts
def dealHand(start):
total = start
haveAce = (start == 1)
while total < 17:
card = randrange(1,14)
if card == 1:
haveAce = True
total = total + BJValue(card)
if haveAce:
total = adjustForAce(total)
return total
def BJValue(card):
if card > 10:
return 10
else:
return card
def adjustForAce(total):
if 16 < total + 10 < 22:
return total + 10
else:
return total
if __name__ == '__main__':
main()
10
解法一
from random import *
import math
def main():
n,h = int(input("Enter the times to simulate: ")),0
for i in range(n):
x,y = 2*random() - 1,2*random() - 1
h += isCircle(x,y)
pi = 4*h/n
print("Estimated times:",n)
print("Estimated pi:",pi)
print("Accuarate pi:",math.pi)
print("Error",abs(pi - math.pi))
def isCircle(x,y):
if x*x + y*y <= 1:return 1
else:return 0
if __name__ =='__main__':main()
解法二
from random import random
def main():
print("This program estimates the value of pi using")
print('random "dart" tosses.')
n = int(input("\nHow many darts should I simulate? "))
hits = throwDarts(n)
print("Estimated value of pi =", 4.0 * hits / n)
def throwDarts(n):
hits = 0
for i in range(n):
x = 2 * random() - 1
y = 2 * random() - 1
if x*x + y*y <= 1:
hits = hits + 1
return hits
if __name__ == '__main__':
main()
11
解法一
from random import *
def main():
n,h = int(input("Enter the times to simulate: ")),0
for i in range(n):
h += isSame()
print("Estimated times:",n)
print("Estimated prob:",h/n)
def isSame():
if randrange(1,7)==randrange(1,7)==randrange(1,7)==\
randrange(1,7)==randrange(1,7):return 1
else:return 0
if __name__ =='__main__':main()
解法二
from random import randrange
def main():
print("This program estimates the probability of rolling")
print("five of a kind on a single roll of 5 dice.\n")
n = int(input("How many rolls should I simulate? "))
hits = 0
for i in range(n):
if equalRolls(5):
hits = hits + 1
print("Estimated prob =", float(hits)/n)
def equalRolls(count):
# count is number of dice to be rolled (must be >1)
# returns True if all values turn out the same, False o/w
first = randrange(1,7)
for i in range(count-1):
roll = randrange(1,7)
if roll != first:
return False
# All rolls were equal to the first
return True
if __name__ == '__main__':
main()
12
解法一
from random import *
def main():
n,h = int(input("Enter the times to simulate: ")),0
for i in range(n):
h += step()
print("Estimated times:",n)
print("Final position:",h)
print("Relative move:{:.2%}".format(h/n))
def step():
return randrange(-1,3,2)
if __name__ =='__main__':main()
解法二
from random import random
def main():
print("Simulation of random walk in one dimension.\n")
walks = int(input("How many walks should I do? "))
steps = int(input("How many steps should I take on each? "))
totalDist = 0
for i in range(walks):
thisDist = randomWalk(steps)
totalDist = totalDist + thisDist
print("Average distance from start", totalDist/walks)
def randomWalk(n):
pos = 0
for i in range(n):
if random() <.5:
pos = pos - 1
else:
pos = pos + 1
return abs(pos)
if __name__ == '__main__':
main()
13
解法一
from random import *
def main():
n,x,y = int(input("Enter the times to simulate: ")),0,0
for i in range(n):
dx,dy = step()
x,y = x+dx,y+dy
d = (x*x + y*y)**(1/2)
print("Estimated times:",n)
print("Final position:({},{})".format(x,y))
print("Relative move:({:.2%},{:.2%})".format(x/n,y/n))
print("Estimated distance:",d)
print("Relative move: {:.2%}".fommat(d/n))
def step():
p = random()
if p<.25:return 1,0
elif p<.5:return -1,0
elif p<.75:return 0,1
else:return 0,-1
if __name__ =='__main__':main()
解法二
from random import randrange
def main():
print("Simulation of two dimensional random walk\n")
walks = int(input("How man walks should I do? "))
steps = int(input("How many steps should I take on each? "))
totalDist = 0
for i in range(walks):
thisDist = randomWalk2D(steps)
totalDist = totalDist + thisDist
print("Average distance from start", totalDist/walks)
def randomWalk2D(n):
x,y = 0,0 # start at the origin
for i in range(n):
dir = randrange(4)
if dir == 0: # go left
x = x - 1
elif dir == 1: # go up
y = y + 1
elif dir == 2: # go right
x = x + 1
else: # go down
y = y - 1
return (x*x + y*y)**.5 # distance to origin
if __name__ == '__main__':
main()
14
解法一
from random import *
from graphics import *
from math import *
def main():
n = int(input('Steps to simulate: '))
win = drawW()
x,y = 0,0
for i in range(n):
x,y = step(x,y,win)
win.getMouse()
win.close()
def drawW():
win = GraphWin('',600,600)
win.setCoords(-60,-60,60,60)
for i in range(-50,51):
Line(Point(i,-50),Point(i,50)).draw(win)
for j in range(-50,51):
Line(Point(-50,j),Point(50,j)).draw(win)
return win
def step(x,y,win):
angle = 2*pi*random()
dx,dy = cos(angle),sin(angle)
l = Line(Point(x,y),Point(x+dx,y+dy))
l.setWidth(2)
l.setFill('red')
l.draw(win)
x,y = x+dx,y+dy
return x,y
if __name__ =='__main__':main()
解法二
from random import random
from math import sin, cos, pi
from graphics import *
def main():
print("Graphical Random Walk\n")
n = int(input("How many steps should I take? "))
win = GraphWin("Random Walk", 500,500)
win.setCoords(-50,-50, 50, 50)
curr = Point(0,0)
next = Point(0,0)
for i in range(n):
angle = random()* 2 * pi
dx = cos(angle)
dy = sin(angle)
next.move(dx,dy)
Line(curr,next).draw(win)
curr.move(dx,dy)
win.getMouse()
win.close()
if __name__ == '__main__':
main()
15
# c09ex15.py
# Puzzle problem. Imagine a cube circumscribed about a unit sphere.
# An "eyeball" at the origin "sees" each wall as 1/6 of the field of
# view. Suppose the eye is moved to (0.5, 0, 0), what proportion of
# the total field of view is taken up by the side of the cube at x = 1.
# This program approximates the solution to this problem using Monte Carlo
# techniques. It generates rays in random directions from the point of
# observation and determines the proportion that intersect the side of cube
# at x = 1.
# if x is the x position of the observer and (a,b,c) are the components of a
# direction vector, the points along the ray from the observer in that
# direction are given by the parametric equation: p = (x,0,0) + t(a,b,c) for
# t >= 0. Solving for the time of intersection (when p.x == 1) we have get
# t == (1-x)/ a. Thus the point of intersection is (1, (1-x)b/a, (1-x)c/a)
# So the ray "strikes" the side of interest iff:
# (-1 <= (1-x)b/a <=1) and (-1 <= (1-x)c/a <= 1)
from random import random
def randomDirection():
# Generate a random direction vector in threespace.
# Method: generate a random point inside of a unit sphere.
# (x,y,z) are chosen in the range -1.0 to 1.0. Any point falling
# outside of the unit sphere is discarded.
while True:
# Generate points until a suitable one is found.
x = 2*random()-1
y = 2*random()-1
z = 2*random()-1
if x*x + y*y + z*z < 1 and (x,y,z) != (0,0,0):
return x,y,z
def main():
print("Puzzle problem solver.\n")
x = float(input("Enter x position of the observer (-1 <= x < 1) "))
n = int(input("Number of samplings: "))
hits = 0
for i in range(n):
a,b,c = randomDirection()
t = (1-x)/a
if t> 0 and (-1 <= t*b <= 1) and (-1 <= t*c <= 1):
hits = hits + 1
print("Estimated FOV =", hits/n)
if __name__ == '__main__':
main()