#! /usr/bin/env python3 # def will_you_be_alive_test ( ): #*****************************************************************************80 # ## will_you_be_alive_test() tests will_you_be_alive(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 02 January 2024 # # Author: # # John Burkardt # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # from numpy.random import default_rng import platform print ( '' ) print ( 'will_you_be_alive_test():' ) print ( ' Python version: ' + platform.python_version ( ) ) print ( ' Test will_you_be_alive().' ) rng = default_rng ( ) airplane_seat_test ( rng ) before_test ( rng ) bernoulli_dice_test ( rng ) bingo_test ( ) black_test ( rng ) chain_test ( ) double_dart_test ( rng ) double_six_test ( rng ) final_test ( rng ) flips_test ( rng ) galileo_test ( ) gamblers_ruin_test ( rng ) golf_test ( rng ) inside_test ( rng ) liar_test ( rng ) long_test ( rng ) marks_test ( rng ) newton_test ( rng ) obtuse1_test ( rng ) obtuse2_test ( rng ) ping_pong_test ( ) plums_test ( rng ) ratio1_test ( rng ) ratio2_test ( rng ) spaghetti_test ( ) square_adjacent_test ( rng ) square_inside_test ( rng ) square_opposite_test ( rng ) squash_test ( ) steve2_test ( rng ) ten_years_test ( ) top_test ( rng ) twins_test ( rng ) # # Terminate. # print ( '' ) print ( 'will_you_be_alive_test():' ) print ( ' Normal end of execution.' ) return def airplane_seat ( trial_num, n, rng ): #*****************************************************************************80 # ## airplane_seat() simulates the airplane seat problem. # # Discussion: # # Airline passengers 1 through N are assigned seats 1 through N. # But passenger 1 is clueless, and chooses a seat randomly. # The remaining passengers board in order, choosing their assigned seat # if possible, otherwise taking an empty seat at random. # What is the probability that the last passenger, N, will be able to # sit in the correct assigned seat N? # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # Original MATLAB version by Paul Nahin; # This version by John Burkardt. # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # Input: # # integer trial_num: the number of simulations. # # integer N, the number of passengers. # # rng(): the current random number generator. # # Output: # # real PROB: the probability that the last passenger will be # properly seated. # import numpy as np prob = 0.0 for trial in range ( 0, trial_num ): occupant = -1 * np.ones ( n ) # # Passenger 0 chooses a seat at random. # passenger = 0 seat = rng.integers ( low = 0, high = n, endpoint = False ) occupant[seat] = passenger # # Passenger I will choose seat I if it is available, # otherwise a random available seat. # for passenger in range ( 1, n ): seat = passenger while ( occupant[seat] != -1 ): seat = rng.integers ( low = 0, high = n, endpoint = False ) occupant[seat] = passenger # # Did the last passenger sit in the last seat? # if ( occupant[n-1] == n - 1 ): prob = prob + 1 prob = prob / trial_num return prob def airplane_seat_test ( rng ): #*****************************************************************************80 # ## airplane_seat_test() tests airplane_seat(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # John Burkardt # # Input: # # rng(): the current random number generator. # print ( '' ) print ( 'airplane_seat_test():' ) print ( ' Airline passengers 1 to N are assigned seats 1 to N.' ) print ( ' The first passenger to board, #1, is clueless, ' ) print ( ' and chooses a seat randomly.' ) print ( ' The remaining passengers board in order, choosing their' ) print ( ' assigned seat if possible, otherwise taking an empty' ) print ( ' seat at random.' ) print ( '' ) print ( ' What is the probability that the last passenger, N, ' ) print ( ' will be able to sit in the correct assigned seat N?' ) trial_num = 100000 n = 100 prob = airplane_seat ( trial_num, n, rng ) print ( '' ) print ( ' Number of seats available =', n ) print ( ' Number of simulations =', trial_num ) print ( ' Estimated probability = ', prob ) print ( ' Theoretical probability = 0.5' ) return def before ( trial_num, bias, rng ): #*****************************************************************************80 # ## before() analyzes the second Newton gambling problem. # # Discussion: # # What is the probability of getting 4 heads before 7 tails? # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # Original MATLAB version by Paul Nahin; # This version by John Burkardt. # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # Input: # # integer trial_num: the number of simulations. # # real bias, the probability of heads on a single toss. # # rng(): the current random number generator. # # Output: # # real prob, the probability of getting 4 heads before 7 tails, # for which the exact value is: # 0.733962, if bias = 0.45 # 0.828125, if bias = 0.50 # total = 0 for loop in range ( 0, trial_num ): H = 0 T = 0 while ( H < 4 and T < 7 ): if ( rng.random ( ) < bias ): H = H + 1 else: T = T + 1 if ( H == 4 ): total = total + 1 prob = total / trial_num return prob def before_test ( rng ): #*****************************************************************************80 # ## before_test() tests before(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # John Burkardt # # Input: # # rng(): the current random number generator. # print ( '' ) print ( 'before_test():' ) print ( ' before() estimates the probability that a person,' ) print ( ' flipping a biased coin repeatedly, will reach 4 heads' ) print ( ' before reaching 7 tails.' ) print ( '' ) print ( ' bias p(4H before 7T)' ) print ( '' ) trial_num = 100000 for i in range ( 0, 105, 5 ): bias = i / 100 prob = before ( trial_num, bias, rng ) print ( ' %g %g' % ( bias, prob ) ) return def bernoulli_dice ( rng ): #*****************************************************************************80 # ## bernoulli_dice() simulates a Bernoulli dice problem. # # Discussion: # # This program models a two-player game. Players A and B take turns # tossing a fair die. The first to throw a 1 wins. On the first # round, A gets 1 toss, then B gets 1 toss, on the second A gets 2 # tosses, then B gets 2 tosses and so on. # # What is the probability that A will win? # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # Original MATLAB version by Paul Nahin; # This version by John Burkardt. # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # James Bernoulii, # Acta Eruditorum, # 1690. # # Input: # # rng(): the current random number generator. # # Output: # # real prob, the probability that player A will win. # w = 0 p = 1.0 / 6.0 trial_num = 100000 for loop in range ( 0, trial_num ): a = 0 b = 0 turn = 1 keepgoing = True while ( keepgoing ): for loopa in range ( 0, turn ): if ( rng.random ( ) < p ): a = 1 for loopa in range ( 0, turn ): if ( rng.random ( ) < p ): b = 1 if ( a == 0 ): if ( b == 0 ): turn = turn + 1 else: keepgoing = False else: w = w + 1 keepgoing = False prob = w / trial_num return prob def bernoulli_dice_test ( rng ): #*****************************************************************************80 # ## bernoulli_dice_test() tests bernoulli_dice(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # John Burkardt # # Input: # # rng(): the current random number generator. # print ( '' ) print ( 'bernoulli_dice_test():' ) print ( ' bernoulli_dice() considers the Bernoulli dice game.' ) print ( ' Players A and B toss a fair die, until a 1 is rolled.' ) print ( ' On round 1, A gets 1 toss, then B gets 1 toss.' ) print ( ' On round k, A gets k tosses, then B gets k tosses.' ) print ( ' What is the probability that A wins?' ) p = bernoulli_dice ( rng ) exact = 0.596794 print ( '' ) print ( ' Estimate = ', p ) print ( ' Exact = ', exact ) return def bingo ( A, B ): #*****************************************************************************80 # ## bingo() analyzes a nontransitive set of bingo cards. # # Licensing: # # This code is distributed under the GNU LGPL license. # # Modified: # # 02 January 2024 # # Author: # # Paul Nahin # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # Input: # # integer A[2,2], B[2,2]: the bingo cards for players X and Y. # # Output: # # xwins, ywins, ties: the number of times X wins, Y wins, or there is a tie. # import itertools # # Consider all 720 permutations of the integers 1 through 6. # xwin = 0 ywin = 0 ties = 0 for perm in itertools.permutations ( [ 1, 2, 3, 4, 5, 6 ] ): X = A.copy() Y = B.copy() keepplaying = True i = 0 xbingo = 0 ybingo = 0 while ( keepplaying ): n = perm[i] for j in range ( 0, 2 ): for k in range ( 0, 2 ): if ( X[j,k] == n ): X[j,k] = 0 if ( Y[j,k] == n ): Y[j,k] = 0 if ( X[0,0] + X[0,1] == 0 ): xbingo = True elif ( X[1,0] + X[1,1] == 0 ): xbingo = True if ( Y[0,0] + Y[0,1] == 0 ): ybingo = True elif ( Y[1,0] + Y[1,1] == 0 ): ybingo = True if ( xbingo and ybingo ): ties = ties + 1 keepplaying = False elif ( xbingo and not ybingo ): xwin = xwin + 1 keepplaying = False elif ( not xbingo and ybingo ): ywin = ywin + 1 keepplaying = False i = i + 1 return xwin, ywin, ties def bingo_test ( ): #*****************************************************************************80 # ## bingo_test() tests bingo(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 02 January 2024 # # Author: # # John Burkardt # import numpy as np print ( '' ) print ( 'bingo_test():' ) print ( ' bingo(A,B) simulates a simplified game of bingo.' ) print ( ' The bingo card is just a 2x2 array.' ) print ( ' Player X gets card A, and player Y gets card B.' ) print ( ' Many random games are played, and the results are reported.' ) print ( ' There are four possible bingo cards, C1, C2, C3, C4.' ) print ( ' It turns out to be a nontransitive system, in which every' ) print ( ' card will beat one of the others, and lose to another.' ) A = np.array ( [ [ 1, 2 ], [ 3, 4 ] ] ) B = np.array ( [ [ 2, 4 ], [ 5, 6 ] ] ) C = np.array ( [ [ 1, 3 ], [ 4, 5 ] ] ) D = np.array ( [ [ 1, 5 ], [ 2, 6 ] ] ) card = np.array ( [ A, B, C, D ] ) name = 'ABCD' print ( '' ) print ( ' The four bingo cards:' ) print ( card ) for k1 in range ( 0, 4 ): for k2 in range ( 0, 4 ): xwin, ywin, ties = bingo ( card[k1], card[k2] ) print ( ' %s %s %d, %d, %d' % ( name[k1], name[k2], xwin, ywin, ties ) ) return def black ( b_init, w_init, rng ): #*****************************************************************************80 # ## black() estimates the probability that the last ball drawn is black. # # Discussion: # # A bag of black and white marbles is to be emptied in a series of rounds. # # A round begins when a single ball is drawn from the bag, its color is # noted, and the ball is discarded. Then, one at a time, more balls are # drawn from the bag. If they match the first ball, then they are also # discarded. Otherwise, they are replaced in the bag, and this round stops. # # Rounds are taken until the bag is empty. # # This function simulates the process of a single round. # # It is desired to estimate the probability that the last marble in # the bag is black. It turns out this probability is 1/2. # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # Original MATLAB version by Paul Nahin; # This version by John Burkardt. # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # Input: # # integer b_init, w_init: the initial number of black and white # balls Typical values are b_init = 15, w_init = 39 # # rng(): the current random number generator. # # Output: # # real p, the probability that the last ball is black. # total = 0.0 trial_num = 10000 for loop in range ( 0, trial_num ): b = b_init w = w_init while ( 0 < b + w ): blackball, whiteball = draw ( b, w, rng ) b = blackball w = whiteball if ( b == 0 ): w = 0 elif ( w == 0 ): total = total + 1 b = 0 p = total / trial_num return p def black_test ( rng ): #*****************************************************************************80 # ## black_test() tests black() and draw(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 02 January 2024 # # Author: # # John Burkardt # # Input: # # rng(): the current random number generator. # print ( '' ) print ( 'black_test():' ) print ( ' A bag of B black and W white marbles is to be emptied in a ' ) print ( ' series of rounds.' ) print ( '' ) print ( ' A round begins when a single ball is drawn from the bag, ' ) print ( ' its color is noted, and the ball is discarded. Then,' ) print ( ' one at a time, more balls are drawn from the bag. If ' ) print ( ' they match the first ball, they are also discarded. ' ) print ( ' Otherwise, they are replaced in the bag, and the ' ) print ( ' round stops.' ) print ( '' ) print ( ' Rounds are taken until the bag is empty.' ) print ( '' ) print ( ' This function simulates the process of a single round.' ) print ( '' ) print ( ' Estimate the probability P that the last marble in ' ) print ( ' the bag is black. It turns out P=1/2.' ) print ( '' ) print ( ' B W P' ) print ( '' ) for b, w in ( [ 1, 1], [ 1, 10 ], [ 2, 3 ], [ 3, 3 ], [ 5, 4 ], \ [ 7, 9 ], [ 18, 13], [ 15, 39] ): p = black ( b, w, rng ) print ( ' %2d %2d %g' % ( b, w, p ) ) return def chain ( c, p ): #*****************************************************************************80 # ## chain() plots the probability that a chain letter will terminate. # # Discussion: # # A chain letter asks the recipient to make C copies and send them on. # Suppose each recipient complies, with probability p. What is the # likelihood that the chain letter will eventually terminate? # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 22 December 2022 # # Author: # # Original MATLAB version by Paul Nahin; # This version by John Burkardt. # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # Input: # # real c: the number of copies that each recipient is asked to make. # # real p: the probability that a recipient will NOT make c copies and # send them on. # # Output: # # real term: the probability that this chain of letters will terminate. # from scipy.optimize import fsolve term0 = 0.5 term = fsolve ( lambda term: term - p - ( 1.0 - p ) * term**c, term0 ) return term def chain_test ( ): #*****************************************************************************80 # ## chain_test() tests chain(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 22 December 2022 # # Author: # # John Burkardt # print ( '' ) print ( 'chain_test():' ) print ( ' chain() estimates the extinction probability of a chain letter.' ) print ( ' A chain letter asks the recipient to make C copies' ) print ( ' and send them on. Suppose that, with probability P,' ) print ( ' any recipient ignores the request, and with probability' ) print ( ' any recipient complies with it.' ) print ( ' Estimate the probability E that the chain' ) print ( ' letter will terminate.' ) print ( '' ) print ( ' Need to solve E = p + ( 1 - p ) * E^c )' ) print ( '' ) print ( ' C P E' ) for c in range ( 1, 6 ): print ( '' ) for i in range ( 1, 11, 2 ): p = i / 10 e = chain ( c, p ) print ( ' %d %g %g' % ( c, p, e ) ) return def draw ( b, w, rng ): #*****************************************************************************80 # ## draw() simulates drawing balls from a set of black and white balls. # # Discussion: # # A bag of black and white marbles is to be emptied in a series of rounds. # # A round begins when a single ball is drawn from the bag, its color is # noted, and the ball is discarded. Then, one at a time, more balls are # drawn from the bag. If they match the first ball, then they are also # discarded. Otherwise, they are replaced in the bag, and this round stops. # # Rounds are taken until the bag is empty. # # This function simulates the process of a single round. # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # Original MATLAB version by Paul Nahin; # This version by John Burkardt. # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # Input: # # integer b, w, the number of black and white balls at the # beginning of the round. # # rng(): the current random number generator. # # Output: # # integer blackball, whiteball, the number of black and # white balls at the end of the round. # if ( rng.random ( ) < b / ( w + b ) ): fcolor = 1 b = b - 1 else: fcolor = 0 w = w - 1 keepgoing = True while ( keepgoing ): if ( fcolor == 1 ): if ( rng.random ( ) < b / ( w + b ) ): b = b - 1 if ( b == 0 ): keepgoing = False else: keepgoing = False else: if ( rng.random ( ) < w / ( w + b ) ): w = w - 1 if ( w == 0 ): keepgoing = False else: keepgoing = False blackball = b whiteball = w return blackball, whiteball def double_dart ( rng ): #*****************************************************************************80 # ## double_dart() analyzes the double dart problem. # # Discussion: # # If two darts land inside the unit circle, what is the probability # that they will be at least 1 unit apart? # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # Original MATLAB version by Paul Nahin; # This version by John Burkardt. # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # Input: # # rng(): the current random number generator. # # Output: # # real prob, the probability that two darts, landing inside # the unit circle, will be at least 1 unit apart. # hits = 0 total = 0 trial_num = 100000 while ( hits < trial_num ): x1 = -1.0 + 2.0 * rng.random ( ) y1 = -1.0 + 2.0 * rng.random ( ) d1 = x1**2 + y1**2 x2 = -1.0 + 2.0 * rng.random ( ) y2 = -1.0 + 2.0 * rng.random ( ) d2 = x2**2 + y2**2 if ( d1 < 1.0 and d2 < 1.0 ): hits = hits + 1 s = ( x1 - x2 )**2 + ( y1 - y2 )**2 if ( 1.0 < s ): total = total + 1 prob = total / hits return prob def double_dart_test ( rng ): #*****************************************************************************80 # ## double_dart_test() tests double_dart(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # John Burkardt # # Input: # # rng(): the current random number generator. # import numpy as np print ( '' ) print ( 'double_dart_test():' ) print ( ' double_dart() considers the double dart problem.' ) print ( ' If two darts land randomly in the unit circle,' ) print ( ' what is the probability that they are at least 1 unit apart?' ) prob = double_dart ( rng ) exact = 3.0 * np.sqrt ( 3.0 ) / 4.0 / np.pi print ( '' ) print ( ' Estimate = ', prob ) print ( ' Exact = ', exact ) return def double_six ( rng ): #*****************************************************************************80 # ## double_six() analyzes the Newton double six dice problem. # # Discussion: # # If we toss a fair die repeatedly, how many tosses will we expect to make # until we encounter two consecutive 6's? # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # Original MATLAB version by Paul Nahin; # This version by John Burkardt. # # Reference: # # Paul Nahin, # Will You Be Alive 10 Years From Now?, # Princeton, 2014, # ISBN: 978-0691156804, # LC: QA273.25.N344 # # Input: # # rng(): the current random number generator. # # Output: # # real P, the expected number of tosses until two 6's appear consecutively. # import numpy as np trial_num = 100000 person = np.zeros ( trial_num ) check = 1.0 / 6.0 for loop in range ( 0, trial_num ): toss = 1 flip2 = 0 keeptossing = True while ( keeptossing ): result = rng.random ( ) if ( result < check ): flip1 = 1 else: flip1 = 0 if ( flip1 + flip2 == 2 ): keeptossing = False person[loop] = toss else: toss = toss + 1 flip2 = flip1 p = np.sum ( person ) / trial_num return p def double_six_test ( rng ): #*****************************************************************************80 # ## double_six_test() tests double_six(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 December 2022 # # Author: # # John Burkardt # # Input: # # rng(): the current random number generator. # print ( '' ) print ( 'double_six_test():' ) print ( ' double_six() considers Newton\'s double six dice problem.' ) print ( ' What is the expected number of times you must roll a fair die' ) print ( ' in order to observe two consecutive values of six?' ) p = double_six ( rng ) p2 = 1.0 / 6.0 exact = 1.0 / p2**2 + 1.0 / p2 print ( '' ) print ( ' Estimate = ', p ) print ( ' Exact = ', exact ) return def final ( rng ): #*****************************************************************************80 # ## final() considers ( A^2/3 + B^2/3