Negative Binomial Distribution
Like a binomial variable, a negative binomial has only 2 outcomes
(aka, binary).
Unlike the binomial distribution, we don’t know how many trials
we are going to have (N is random).
Instead, the number of one result is known before the trials
(\(k\) for known) and the other result
is random (\(r\) for random).
Let’s have our parameters be
\(r\) = the number of correct
questions answered = 5
\(k\) = number of incorrect
questions before stopping = 2,
\(\pi_k\) = 0.25 and \(\pi_r = 1 - \pi_k = 0.25\)
r = 5 # Number of correct questions needed to win $5000
k = 2 # number of incorrect questions required to stop
pi_r = 0.75 # Probability of a correct answer
pi_k = 0.25 # Probability of an incorrect answer
The equation to calculate the probability using a Negative Binomial
Distribution is:
\[P(Y = r | k, \pi) = \frac{(r + k -
1)!}{r!(k - 1)!} \pi_r^r (1 - \pi_r)^k \]
dnbinom()
dnbinom() has the same argument names as
dbinom() where
x = the result of the random group \(Y_r\)
- The number of correct questions
size = the number of the known group \(Y_k\)
- number of incorrect questions
prob = the probability of the known group: \(\pi_k\)
- Probability of getting the question incorrect
# P(Y_r = 5)
dnbinom(
x = r, # successes
size = k, # needed failures
prob = pi_k # prob of failure
)
## [1] 0.08898926
The contestant has about a 8.9% chance of answering exactly 5
questions correctly before answering 2 incorrectly
But if they want to win $5000 or more, what can we do?
Let’s find the probabilities of all possible values of \(Y_r\) by creating a table of the outcomes
and the corresponding probabilities of \(Y\)
Hypothetically, the contestant can keep answering questions
indefinitely, so we’ll just look at the probability they answer 0 to 50
questions correctly.
nbin_df <-
tibble(
Y_r = 0:50,
P_Yr = dnbinom(x = Y_r, # Different possible correct answers
size = 2, # Always 2 incorrect answers
prob = pi_k) # Probability of an incorrect answer = 0.25
)
# Rounding the results
nbin_df |>
round(digits = 4)
## # A tibble: 51 × 2
## Y_r P_Yr
## <dbl> <dbl>
## 1 0 0.0625
## 2 1 0.0938
## 3 2 0.106
## 4 3 0.106
## 5 4 0.0989
## 6 5 0.089
## 7 6 0.0779
## 8 7 0.0667
## 9 8 0.0563
## 10 9 0.0469
## # ℹ 41 more rows
### Graph representing the probabilities
nbin_df |>
# Let's remove any outcomes that have less than 0.01% chance of occurring
filter(P_Yr > 0.0001) |>
ggplot(
mapping = aes(x = factor(Y_r), y = P_Yr)
) +
# Adding the bars
geom_col(fill = "steelblue") +
# Adding a vertical line at the 'goal' of 5 correct questions
geom_vline(
xintercept = 5,
color = "orange",
linewidth = 1
) +
labs(
x = "r",
y = "P(Y = r)"
) +
scale_y_continuous(expand = c(0, 0, 0.05, 0)) +
theme_bw() +
theme(plot.title = element_text(hjust = 0.5, size = 16)) +
labs(title = 'Negative binomial with k = 2 and pi_k = 0.25')

Now we can add up the probabilities for \(Y_r \ge 5\)
nbin_df |>
filter(Y_r >= 5) |>
summarize(`P(At Least 5 Correct)` = sum(P_Yr)) |>
round(digits = 4)
## # A tibble: 1 × 1
## `P(At Least 5 Correct)`
## <dbl>
## 1 0.534
So they have a little more than 50% probability of winning at least
$5000
2) pnbinom() - Cumulative Probability
We could have also used pnbinom() with
lower = F and some adjustments:
# P(Y <= r) = pnbinom(r, k, pi_k)
pnbinom(q = r, size = k, prob = pi_k)
## [1] 0.5550537
# P(Y >= r) = pnbinom(r-1, k, pi_k)
pnbinom(q = r-1, size = k, prob = pi_k, lower = F)
## [1] 0.5339355
If you round to enough decimal places, the two methods won’t be
exactly the same since the probability they answer more than 50 correct
is technically not 0, but they should be very similar since it is close
to it!
It’s not hard to have R calculate more of the probabilities, you
could let r go up to 1000 (or more!) instead of just 50, but the
difference is very, very small
3) qnbinom()
From the show’s perspective, you want to make sure you don’t give
away too much money. What’s the maximum amount of money 95% of
contestants will take home? That is, how many questions will 95% or
fewer contestants answer correctly?
# P(Y_r <= r) >= p
qnbinom(p = 0.95,
size = 2,
prob = 0.25)
## [1] 16
# What's the probability that Y_r <= 16?
pnbinom(q = 16,
size = 2,
prob = 0.25)
## [1] 0.960536
# About 96%. That is the probability that Y_r <= 15?
pnbinom(q = 15,
size = 2,
prob = 0.25)
## [1] 0.949887
# "only" 94.99%, so about 95% of contestants will win 15k or less.
4) rnbinom() - Generating negative binomial
samples:
If we want to generate \(n\)
different negative binomial random variables, that’s what
rnbinom() is for!
Let’s simulate 20 contestants playing on the game show:
rnbinom(n = 20, size = 2,prob = 0.25)
## [1] 4 8 1 3 1 1 6 5 11 7 7 0 1 12 4 16 7 10 2 0
Now let’s simulate 10,000 contestants and create a graph of the
results:
# Number of contestants
N = 1e5
# Simulating and plotting the results of 10,000 contestants
tibble(
Y = rnbinom(n = N, size = 2, prob = 0.25)
) |>
# Counting how many contests get 1 question right, 2 questions, ...
count(Y) |>
## Plotting the results
ggplot(
mapping = aes(x = factor(Y), y = n/N) # y = Probability instead of count
) +
geom_col(
fill = "steelblue"
) +
# Calculating the expected value and displaying it on the line
geom_vline(
mapping = aes(xintercept = sum(Y*n/N)),
color = "orange",
linewidth = 1
) +
labs(
x = "r",
y = "Estimated P(Y = r)"
) +
scale_y_continuous(expand = c(0, 0, 0.05, 0)) +
theme_bw()

LS0tDQp0aXRsZTogIk5lZ2F0aXZlIEJpbm9taWFsIERpc3RyaWJ1dGlvbiBpbiBSIg0KYXV0aG9yOiAiQ2hhcHRlciAxOiBQcm9iYWJpbGl0eSBEaXN0cmlidXRpb25zIg0KZGF0ZTogIlNUQSA0NTA0Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGZpZ193aWR0aDogNg0KICAgIGZpZ19oZWlnaHQ6IDYNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcuYWxpZ24gPSAnY2VudGVyJykNCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSkNCmBgYA0KDQojIyBJbml0aWFsIERlc2NyaXB0aW9uOiBGb3VyIERpc3RyaWJ1dGlvbiBMZXR0ZXJzDQoNClRoZSBkaWZmZXJlbnQgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uIGZ1bmN0aW9ucyBhbGwgc3RhcnQgd2l0aCBvbmUgb2YgdGhlIGZvbGxvd2luZyA0IGxldHRlcnM6DQoNCjEpICBkICRccmlnaHRhcnJvdyQgZGVuc2l0eTogRmluZCB0aGUgcHJvYmFiaWxpdHkgZm9yIGEgc3BlY2lmaWMgdmFsdWU6ICRQKFk9YSkkDQoNCjIpICBwICRccmlnaHRhcnJvdyQgRmluZCB0aGUgcHJvYmFiaWxpdHkgZm9yIHRoZSBzcGVjaWZpYyB2YWx1ZSBhbmQgYWxsIHZhbHVlcyBsZXNzIHRoYW4gaXQgKGFrYSwgY3VtdWxhdGl2ZSBwcm9iYWJpbGl0eSk6ICRQKFkgXGxlIGEpJA0KDQozKSAgcSAkXHJpZ2h0YXJyb3ckIHF1YW50aWxlOiBGaW5kcyB0aGUgc21hbGxlc3QgdmFsdWUgb2YgdGhlIHJhbmRvbSB2YXJpYWJsZSwgJGEkLCBzbyB0aGF0ICRQKFkgXGxlIGEpIFxnZSBwJA0KDQotICAgSXQncyBiYXNpY2FsbHkgcCBpbiByZXZlcnNlOiBJZiB3ZSBrbm93IHRoZSBwcm9iYWJpbGl0eSwgd2hhdCBpcyB0aGUgdmFsdWUgb2YgdGhlIHJhbmRvbSB2YXJpYWJsZT8NCg0KNCkgIHIgJFxyaWdodGFycm93JCBnZW5lcmF0ZSBhIHZhbHVlIG9mIHRoZSByYW5kb20gdmFyaWFibGUgWSBnaXZlbiB0aGUgcGFyYW1ldGVycw0KDQojIyBOZWdhdGl2ZSBCaW5vbWlhbCBEaXN0cmlidXRpb24NCg0KLSAgIExpa2UgYSBiaW5vbWlhbCB2YXJpYWJsZSwgYSBuZWdhdGl2ZSBiaW5vbWlhbCBoYXMgb25seSAyIG91dGNvbWVzIChha2EsIGJpbmFyeSkuDQoNCi0gICBVbmxpa2UgdGhlIGJpbm9taWFsIGRpc3RyaWJ1dGlvbiwgd2UgZG9uJ3Qga25vdyBob3cgbWFueSB0cmlhbHMgd2UgYXJlIGdvaW5nIHRvIGhhdmUgKE4gaXMgcmFuZG9tKS4NCg0KLSAgIEluc3RlYWQsIHRoZSBudW1iZXIgb2Ygb25lIHJlc3VsdCBpcyBrbm93biBiZWZvcmUgdGhlIHRyaWFscyAoJGskIGZvciBrbm93bikgYW5kIHRoZSBvdGhlciByZXN1bHQgaXMgcmFuZG9tICgkciQgZm9yIHJhbmRvbSkuDQoNCkxldCdzIGhhdmUgb3VyIHBhcmFtZXRlcnMgYmUNCg0KLSAgICRyJCA9IHRoZSBudW1iZXIgb2YgY29ycmVjdCBxdWVzdGlvbnMgYW5zd2VyZWQgPSA1DQoNCi0gICAkayQgPSBudW1iZXIgb2YgaW5jb3JyZWN0IHF1ZXN0aW9ucyBiZWZvcmUgc3RvcHBpbmcgPSAyLA0KDQotICAgJFxwaV9rJCA9IDAuMjUgYW5kICRccGlfciA9IDEgLSBccGlfayA9IDAuMjUkDQoNCmBgYHtyIG5iaW5vbV9wYXJhbWV0ZXJzfQ0KciA9IDUgICAgICAgICAjIE51bWJlciBvZiBjb3JyZWN0IHF1ZXN0aW9ucyBuZWVkZWQgdG8gd2luICQ1MDAwDQprID0gMiAgICAgICAgICMgbnVtYmVyIG9mIGluY29ycmVjdCBxdWVzdGlvbnMgcmVxdWlyZWQgdG8gc3RvcA0KcGlfciA9IDAuNzUgICAjIFByb2JhYmlsaXR5IG9mIGEgY29ycmVjdCBhbnN3ZXINCnBpX2sgPSAwLjI1ICAgIyBQcm9iYWJpbGl0eSBvZiBhbiBpbmNvcnJlY3QgYW5zd2VyDQpgYGANCg0KVGhlIGVxdWF0aW9uIHRvIGNhbGN1bGF0ZSB0aGUgcHJvYmFiaWxpdHkgdXNpbmcgYSBOZWdhdGl2ZSBCaW5vbWlhbCBEaXN0cmlidXRpb24gaXM6DQoNCiQkUChZID0gciB8IGssIFxwaSkgPSBcZnJhY3sociArIGsgLSAxKSF9e3IhKGsgLSAxKSF9IFxwaV9yXnIgKDEgLSBccGlfcileayAkJA0KDQojIyMgYGRuYmlub20oKWANCg0KYGRuYmlub20oKWAgaGFzIHRoZSBzYW1lIGFyZ3VtZW50IG5hbWVzIGFzIGBkYmlub20oKWAgd2hlcmUNCg0KLSAgIGB4ID1gIHRoZSByZXN1bHQgb2YgdGhlIHJhbmRvbSBncm91cCAkWV9yJA0KICAgIC0gICBUaGUgbnVtYmVyIG9mIGNvcnJlY3QgcXVlc3Rpb25zDQotICAgYHNpemUgPWAgdGhlIG51bWJlciBvZiB0aGUga25vd24gZ3JvdXAgJFlfayQNCiAgICAtICAgbnVtYmVyIG9mIGluY29ycmVjdCBxdWVzdGlvbnMNCi0gICBgcHJvYiA9YCB0aGUgcHJvYmFiaWxpdHkgb2YgdGhlIGtub3duIGdyb3VwOiAkXHBpX2skDQogICAgLSAgIFByb2JhYmlsaXR5IG9mIGdldHRpbmcgdGhlIHF1ZXN0aW9uIGluY29ycmVjdA0KDQpgYGB7ciBkbmJpbm9tfQ0KIyBQKFlfciA9IDUpIA0KZG5iaW5vbSgNCiAgeCA9IHIsICAgICAgICMgc3VjY2Vzc2VzDQogIHNpemUgPSBrLCAgICAjIG5lZWRlZCBmYWlsdXJlcw0KICBwcm9iID0gcGlfayAgIyBwcm9iIG9mIGZhaWx1cmUNCikNCmBgYA0KDQpUaGUgY29udGVzdGFudCBoYXMgYWJvdXQgYSA4LjklIGNoYW5jZSBvZiBhbnN3ZXJpbmcgZXhhY3RseSA1IHF1ZXN0aW9ucyBjb3JyZWN0bHkgYmVmb3JlIGFuc3dlcmluZyAyIGluY29ycmVjdGx5DQoNCkJ1dCBpZiB0aGV5IHdhbnQgdG8gd2luIFwkNTAwMCBvciBtb3JlLCB3aGF0IGNhbiB3ZSBkbz8NCg0KTGV0J3MgZmluZCB0aGUgcHJvYmFiaWxpdGllcyBvZiBhbGwgcG9zc2libGUgdmFsdWVzIG9mICRZX3IkIGJ5IGNyZWF0aW5nIGEgdGFibGUgb2YgdGhlIG91dGNvbWVzIGFuZCB0aGUgY29ycmVzcG9uZGluZyBwcm9iYWJpbGl0aWVzIG9mICRZJA0KDQpIeXBvdGhldGljYWxseSwgdGhlIGNvbnRlc3RhbnQgY2FuIGtlZXAgYW5zd2VyaW5nIHF1ZXN0aW9ucyBpbmRlZmluaXRlbHksIHNvIHdlJ2xsIGp1c3QgbG9vayBhdCB0aGUgcHJvYmFiaWxpdHkgdGhleSBhbnN3ZXIgMCB0byA1MCBxdWVzdGlvbnMgY29ycmVjdGx5Lg0KDQpgYGB7ciBuYmlub21fZGZ9DQpuYmluX2RmIDwtIA0KICB0aWJibGUoDQogICAgWV9yID0gMDo1MCwNCiAgICBQX1lyID0gZG5iaW5vbSh4ID0gWV9yLCAgICAgICAjIERpZmZlcmVudCBwb3NzaWJsZSBjb3JyZWN0IGFuc3dlcnMNCiAgICAgICAgICAgICAgICAgICBzaXplID0gMiwgICAgICAjIEFsd2F5cyAyIGluY29ycmVjdCBhbnN3ZXJzDQogICAgICAgICAgICAgICAgICAgcHJvYiA9IHBpX2spICAgIyBQcm9iYWJpbGl0eSBvZiBhbiBpbmNvcnJlY3QgYW5zd2VyID0gMC4yNQ0KICApDQoNCiMgUm91bmRpbmcgdGhlIHJlc3VsdHMNCm5iaW5fZGYgfD4gDQogIHJvdW5kKGRpZ2l0cyA9IDQpIA0KDQoNCg0KIyMjIEdyYXBoIHJlcHJlc2VudGluZyB0aGUgcHJvYmFiaWxpdGllcw0KbmJpbl9kZiB8PiANCiAgDQogICMgTGV0J3MgcmVtb3ZlIGFueSBvdXRjb21lcyB0aGF0IGhhdmUgbGVzcyB0aGFuIDAuMDElIGNoYW5jZSBvZiBvY2N1cnJpbmcNCiAgZmlsdGVyKFBfWXIgPiAwLjAwMDEpIHw+IA0KICANCiAgZ2dwbG90KA0KICAgIG1hcHBpbmcgPSBhZXMoeCA9IGZhY3RvcihZX3IpLCB5ID0gUF9ZcikNCiAgKSArIA0KICANCiAgIyBBZGRpbmcgdGhlIGJhcnMgIA0KICBnZW9tX2NvbChmaWxsID0gInN0ZWVsYmx1ZSIpICsNCiAgDQogICMgQWRkaW5nIGEgdmVydGljYWwgbGluZSBhdCB0aGUgJ2dvYWwnIG9mIDUgY29ycmVjdCBxdWVzdGlvbnMNCiAgZ2VvbV92bGluZSgNCiAgICB4aW50ZXJjZXB0ID0gNSwNCiAgICBjb2xvciA9ICJvcmFuZ2UiLA0KICAgIGxpbmV3aWR0aCA9IDENCiAgKSArDQogIA0KICBsYWJzKA0KICAgIHggPSAiciIsDQogICAgeSA9ICJQKFkgPSByKSINCiAgKSArIA0KICANCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCwgMC4wNSwgMCkpICsgDQogIA0KICB0aGVtZV9idygpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNikpICsNCiAgDQogIGxhYnModGl0bGUgPSAnTmVnYXRpdmUgYmlub21pYWwgd2l0aCBrID0gMiBhbmQgcGlfayA9IDAuMjUnKQ0KDQpgYGANCg0KTm93IHdlIGNhbiBhZGQgdXAgdGhlIHByb2JhYmlsaXRpZXMgZm9yICRZX3IgXGdlIDUkDQoNCmBgYHtyfQ0KbmJpbl9kZiB8PiANCiAgZmlsdGVyKFlfciA+PSA1KSB8PiANCiAgc3VtbWFyaXplKGBQKEF0IExlYXN0IDUgQ29ycmVjdClgID0gc3VtKFBfWXIpKSB8PiANCiAgcm91bmQoZGlnaXRzID0gNCkNCmBgYA0KDQpTbyB0aGV5IGhhdmUgYSBsaXR0bGUgbW9yZSB0aGFuIDUwJSBwcm9iYWJpbGl0eSBvZiB3aW5uaW5nIGF0IGxlYXN0IFwkNTAwMA0KDQojIyMgMikgYHBuYmlub20oKWAgLSBDdW11bGF0aXZlIFByb2JhYmlsaXR5DQoNCldlIGNvdWxkIGhhdmUgYWxzbyB1c2VkIGBwbmJpbm9tKClgIHdpdGggYGxvd2VyID0gRmAgYW5kIHNvbWUgYWRqdXN0bWVudHM6DQoNCmBgYHtyfQ0KIyBQKFkgPD0gcikgPSBwbmJpbm9tKHIsIGssIHBpX2spIA0KcG5iaW5vbShxID0gciwgc2l6ZSA9IGssIHByb2IgPSBwaV9rKQ0KDQoNCiMgUChZID49IHIpID0gcG5iaW5vbShyLTEsIGssIHBpX2spIA0KcG5iaW5vbShxID0gci0xLCBzaXplID0gaywgcHJvYiA9IHBpX2ssIGxvd2VyID0gRikNCg0KYGBgDQoNCklmIHlvdSByb3VuZCB0byBlbm91Z2ggZGVjaW1hbCBwbGFjZXMsIHRoZSB0d28gbWV0aG9kcyB3b24ndCBiZSBleGFjdGx5IHRoZSBzYW1lIHNpbmNlIHRoZSBwcm9iYWJpbGl0eSB0aGV5IGFuc3dlciBtb3JlIHRoYW4gNTAgY29ycmVjdCBpcyB0ZWNobmljYWxseSBub3QgMCwgYnV0IHRoZXkgc2hvdWxkIGJlIHZlcnkgc2ltaWxhciBzaW5jZSBpdCBpcyBjbG9zZSB0byBpdCENCg0KSXQncyBub3QgaGFyZCB0byBoYXZlIFIgY2FsY3VsYXRlIG1vcmUgb2YgdGhlIHByb2JhYmlsaXRpZXMsIHlvdSBjb3VsZCBsZXQgciBnbyB1cCB0byAxMDAwIChvciBtb3JlISkgaW5zdGVhZCBvZiBqdXN0IDUwLCBidXQgdGhlIGRpZmZlcmVuY2UgaXMgdmVyeSwgdmVyeSBzbWFsbA0KDQojIyMgMykgYHFuYmlub20oKWANCg0KRnJvbSB0aGUgc2hvdydzIHBlcnNwZWN0aXZlLCB5b3Ugd2FudCB0byBtYWtlIHN1cmUgeW91IGRvbid0IGdpdmUgYXdheSB0b28gbXVjaCBtb25leS4gV2hhdCdzIHRoZSBtYXhpbXVtIGFtb3VudCBvZiBtb25leSA5NSUgb2YgY29udGVzdGFudHMgd2lsbCB0YWtlIGhvbWU/IFRoYXQgaXMsIGhvdyBtYW55IHF1ZXN0aW9ucyB3aWxsIDk1JSBvciBmZXdlciBjb250ZXN0YW50cyBhbnN3ZXIgY29ycmVjdGx5Pw0KDQpgYGB7ciBxbmJpbm9tfQ0KIyBQKFlfciA8PSByKSA+PSBwDQpxbmJpbm9tKHAgPSAwLjk1LA0KICAgICAgICBzaXplID0gMiwNCiAgICAgICAgcHJvYiA9IDAuMjUpDQoNCg0KIyBXaGF0J3MgdGhlIHByb2JhYmlsaXR5IHRoYXQgWV9yIDw9IDE2Pw0KcG5iaW5vbShxID0gMTYsDQogICAgICAgIHNpemUgPSAyLA0KICAgICAgICBwcm9iID0gMC4yNSkNCg0KIyBBYm91dCA5NiUuIFRoYXQgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgWV9yIDw9IDE1Pw0KcG5iaW5vbShxID0gMTUsDQogICAgICAgIHNpemUgPSAyLA0KICAgICAgICBwcm9iID0gMC4yNSkNCg0KIyAib25seSIgOTQuOTklLCBzbyBhYm91dCA5NSUgb2YgY29udGVzdGFudHMgd2lsbCB3aW4gMTVrIG9yIGxlc3MuIA0KDQpgYGANCg0KIyMjIDQpIGBybmJpbm9tKClgIC0gR2VuZXJhdGluZyBuZWdhdGl2ZSBiaW5vbWlhbCBzYW1wbGVzOg0KDQpJZiB3ZSB3YW50IHRvIGdlbmVyYXRlICRuJCBkaWZmZXJlbnQgbmVnYXRpdmUgYmlub21pYWwgcmFuZG9tIHZhcmlhYmxlcywgdGhhdCdzIHdoYXQgYHJuYmlub20oKWAgaXMgZm9yIQ0KDQpMZXQncyBzaW11bGF0ZSAyMCBjb250ZXN0YW50cyBwbGF5aW5nIG9uIHRoZSBnYW1lIHNob3c6DQoNCmBgYHtyIHJuYmlub219DQpybmJpbm9tKG4gPSAyMCwgc2l6ZSA9IDIscHJvYiA9IDAuMjUpIA0KYGBgDQoNCk5vdyBsZXQncyBzaW11bGF0ZSAxMCwwMDAgY29udGVzdGFudHMgYW5kIGNyZWF0ZSBhIGdyYXBoIG9mIHRoZSByZXN1bHRzOg0KDQpgYGB7ciBmaWcud2lkdGg9OH0NCiMgTnVtYmVyIG9mIGNvbnRlc3RhbnRzDQpOID0gMWU1DQoNCiMgU2ltdWxhdGluZyBhbmQgcGxvdHRpbmcgdGhlIHJlc3VsdHMgb2YgMTAsMDAwIGNvbnRlc3RhbnRzDQp0aWJibGUoDQogIFkgPSBybmJpbm9tKG4gPSBOLCBzaXplID0gMiwgcHJvYiA9IDAuMjUpDQopIHw+ICANCiAgDQogICMgQ291bnRpbmcgaG93IG1hbnkgY29udGVzdHMgZ2V0IDEgcXVlc3Rpb24gcmlnaHQsIDIgcXVlc3Rpb25zLCAuLi4NCiAgY291bnQoWSkgfD4gDQogIA0KICANCiAgIyMgUGxvdHRpbmcgdGhlIHJlc3VsdHMNCiAgZ2dwbG90KA0KICAgIG1hcHBpbmcgPSBhZXMoeCA9IGZhY3RvcihZKSwgeSA9IG4vTikgIyB5ID0gUHJvYmFiaWxpdHkgaW5zdGVhZCBvZiBjb3VudA0KICApICsgDQogIA0KICBnZW9tX2NvbCgNCiAgICBmaWxsID0gInN0ZWVsYmx1ZSINCiAgKSArIA0KICANCiAgIyBDYWxjdWxhdGluZyB0aGUgZXhwZWN0ZWQgdmFsdWUgYW5kIGRpc3BsYXlpbmcgaXQgb24gdGhlIGxpbmUNCiAgZ2VvbV92bGluZSgNCiAgICBtYXBwaW5nID0gYWVzKHhpbnRlcmNlcHQgPSBzdW0oWSpuL04pKSwNCiAgICBjb2xvciA9ICJvcmFuZ2UiLA0KICAgIGxpbmV3aWR0aCA9IDENCiAgKSArDQogIA0KICBsYWJzKA0KICAgIHggPSAiciIsDQogICAgeSA9ICJFc3RpbWF0ZWQgUChZID0gcikiDQogICkgKyANCiAgDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDAsIDAuMDUsIDApKSArIA0KICANCiAgdGhlbWVfYncoKQ0KDQpgYGANCg==