“What d'you mean?” he said.
“Well, all right, last desperate million-to-one chances always work, right, no problem, but. . . well, it's pretty wossname, specific. I mean, isn't it?”
“You tell me,” said Nobby.
“What if it's just a thousand-to-one chance?” said Colon agonisedly.
“What?”
“Anyone ever heard of a thousand-to-one shot coming up?”
Carrot looked up. “Don't be daft, Sergeant,” he said. “No-one ever saw a thousand-to-one chance come up. The odds against it are-” his lips moved- “millions to one.”
Guards! Guards!, Terry Pratchett
Who's going to win? Will it be Colon, with his one-in-a-million shot? Or will the dragon leave him a drifting cloud of ash?
We're going to create a function that randomly says who wins. To outline how this works, we'll define a function that always works one way first.
In [1]:
from numpy.random import rand
def colon_wins(p_colon):
"""
If a random number is less than `p_colon` then Colon wins, otherwise the dragon does.
Parameters
----------
p_colon: scalar
Probability that Colon wins
Notes
-----
In this case we do not use a random number, but fix it to be zero:
this way, Colon always wins
"""
return 0.0 <= p_colon
Let's see this working 20 times, when the probability of Colon winning is 50%:
In [2]:
for i in range(20):
if colon_wins(0.5):
print("Colon wins!")
else:
print("What's that ash cloud?")
Now let's check we still get the same result, even when the probability of Colon winning is only 10%:
In [3]:
for i in range(20):
if colon_wins(0.1):
print("Colon wins!")
else:
print("What's that ash cloud?")
Now we'll re-define the function so that it's using proper random numbers:
In [4]:
def colon_wıns(p_colon):
"""
If a random number is less than `p_colon` then Colon wins, otherwise the dragon does.
Parameters
----------
p_colon: scalar
Probability that Colon wins
"""
return rand() <= p_colon
Now, when called 20 times, when the probability of Colon winning is 50%:
In [5]:
for i in range(20):
if colon_wıns(0.5):
print("Colon wins!")
else:
print("What's that ash cloud?")
And, when called 20 times, when the probability of Colon winning is 10%:
In [6]:
for i in range(20):
if colon_wıns(0.1):
print("Colon wins!")
else:
print("What's that ash cloud?")
Let's check that, as the number of trials is increased, we really get the probability we expect:
In [7]:
trials = 1000000
success = 0
for i in range(trials):
success += colon_wıns(0.5)
print("50% success in theory: {:.2f}% success in {} trials.".
format(success/trials*100, trials))
In [8]:
trials = 1000000
success = 0
for i in range(trials):
success += colon_wıns(0.1)
print("10% success in theory: {:.2f}% success in {} trials.".
format(success/trials*100, trials))
Finally, what happens when the probability of Colon winning is minute: 0.0001%, or Pratchett's famous one-in-a-million chance?
In [9]:
trials = 1000000
success = 0
for i in range(trials):
success += colon_wins(1e-6)
print("One-in-a-million success in theory: {:.2f}% success in {} trials.".
format(success/trials*100, trials))
It's a miracle! The function knows Pratchett's rule!