TLDR: Skip to the bottom to see the javascript function.
I decided to add a feature to the tenzies challenge that would show both the number of rolls so far and a prediction for the number of remaining rolls. The prediction would simply be from an estimate of the expected number of rolls to get remaining unfrozen dice to all roll a target value–whatever the value is you already have frozen.
So let’s say you just froze your 5th die, and you are about to roll the remaining 5. A message will appear telling you how many more rolls are expected to get the 5 remaining dice to your number. This estimate decreases by one after each roll you make, even going negative if you are unlucky. I know this isn’t logically accurate since the odds don’t change over time (there is no “law of averages”), but it does give the nice effect of tracking your actual number of rolls more closely.
So the question is, what is the average (mean, or expected value) number of rolls of all the dice before they all show the same number? For that matter, should we be using the average, the median or the mode? Since the distribution is skewed, median would probably be a better number to track, and maybe even the mode, but the mean felt like more of a challenge so that’s what I set out to do.
Analysis
Probability of a succes in one throw is the probablity of rolling one face of the die out of six:
\[p = 1/6\]
The probability of not throwing the target value is the inverse, or \(1-p\). So the probability of k successive misses given by this function:
\[(1-p)^k\]
Inverting this gives the probability of at least one success in k throws:
\[1-(1-p)^k\] Does this pass the intuition test? The higher the value of k, the higher the likelihood of a success. If you roll a die 12 times, you’re pretty certain you’re going to roll that number. The formula tells you it will happen with a probability of 89%. Seems about right.
But now, if you are rolling \(n\) dice, then the probability of finding at least one success in \(k\) throws of each die is the product of the probabilities of success of each individual die:
\[(1-(1-p)^k)^n\] The first deriviative of this formula will give you the Probability Mass Function (PMF). This will tell us the probability of a particular number of throws being the exact number required. I cheated and used a site called derivative-calculator.net to work out the derivative.
\[-n\ln\left(1-p\right)\left(1-\left(1-p\right)^k\right)^{n-1}\left(1-p\right)^k\] So what is the expected value of \(k\) given \(n\)? From reading different articles it appears there’s a closed form solution for this but I don’t understand the notation well enough to implement it so instead I just calculated it brute force by multiplying the rolls by their probability using the PMF, above. Here’s what that looks like:
\[\sum_{k=1}^{m}-kn\ln\left(1-p\right)\left(1-\left(1-p\right)^k\right)^{n-1}\left(1-p\right)^k\]
Validation
So how accurate is this? Let’s test the values predicted by the model with actual simulations of the game.
Evaluating the Model
The game begins with a random roll where you choose which dice to “freeze”. For 10 dice, the average number of same faced dice is about 3.5, which I found from simulating. (I couldn’t find or figure out the actual solution). So for our model we’ll assume we start with three dice of the same face, and the second roll will start with 7 dice instead of 10.
p <- 1/6
n <- 7
Now implement the PMF:
pmf <- function(p, k, n) {
-n * log(1-p) * ((1-(1-p)^k)^(n-1)) * (1-p)^k
}
What does this look like?
x <- 0:40
y <- pmf(1/6, x, 10)
ggplot() + aes(x=x-1, y=y) + geom_col()

Now calculate the mean number of rolls looking at the probabilities of the first 500 rolls, multiplying each by the roll number:
mean_rolls <- function(p, n) {
iter <- 1000
sum <- 0
for (k in 1:iter) {
sum <- sum + k * pmf(p, k, n)
}
return(sum)
}
1 + mean_rolls(p, 8)
[1] 15.90694
Running the simulations
Define a function to run one simulation with n
dice.
simulate <- function(n) {
# Roll a set of 6 dice using uniform random samples
firstroll <- sample(1:6, 10, replace=TRUE) |>
table() |>
sort(decreasing = T)
# Define the target as whatever we rolled the most of
target <- as.integer(names(firstroll[1]))
# Now the remaining number of dice to start rolling for simulation
n.diceleft <- n - firstroll[1]
if (n.diceleft == 0) return(1)
# Now populate a matrix with random numbers whose columns represent a sequence of 100 rolls
# of each individual dice.
dice.history <-
runif(n.diceleft * 100, 0, 6) |>
ceiling() |>
matrix(ncol=n.diceleft)
# Find the index of the first success in each column
rolls.to.target <- sapply(1:n.diceleft, \(col) {
return(which(dice.history[,col] == target)[1])
})
# Take the max of the rolls required for each die, and add 1 for firstroll
return(1 + max(rolls.to.target))
}
Run a simulation 50,000 times.
iter <- 50000
results <- sapply(1:iter, \(x){ return(simulate(10)) })
# Mode:
df <- table(results)
mode <- sort(decreasing = T, df)[1]
# Mean
avg <- sum(results) / iter
The mode was 3635 and the mean number of throws was 15.32762. The worst game took 73 rolls.
Histogram of simulations:
ggplot(tibble(x=results)) + aes(x=x) + geom_histogram(binwidth = 1) +
xlab("Number of Rolls to Success") + ylab("Number of Simulations")

Model vs Simulation
They are pretty close.
sim <- rep(0, length(x))
indices <- as.integer(names(df)) |> sort()
for (i in indices[indices <= length(x)]) {
sim[i] <- df[i]/iter
}
model.tail <- pmf(p, x, n-3)
model <- c(0, model.tail[1:length(x)-1])
data <- tibble(x=x,
model=model,
simulation=sim) |>
pivot_longer(cols=c('model', 'simulation'),
names_to='PMF',
values_to="Probability")
ggplot(data) +
aes(x=x, y=Probability, color=PMF) +
geom_line() +
xlab("Number of Rolls to Success") +
ylab("Probability for Given Number of Rolls")

Appendix
How many same dice are likely to appear in one throw?
rolls <- 10000
sum <- 0
for (i in 1:rolls) {
throw <-
sum <- sum + sample(1:6, 10, replace=T) |>
table() |>
sort(decreasing=T) |>
head(1)
}
sum/rolls
5
3.4485
Javascript Function
To calculate the expected number of remaining rolls as a function of unfrozen dice:
function ev(n) {
const p = 1/6
const iter = 500
let sum = 0
for (var k = 1; k <= iter; k++) {
const prob = -n * Math.log(1-p) * ((1-(1-p)**k)**(n-1)) * (1-p)**k
sum += k * prob
}
return(sum)
}
LS0tCnRpdGxlOiAiUHJlZGljdGluZyBEaWNlIFJvbGxzIGluIFRlbnppZXMiCmF1dGhvcjogIkJpbGwgS2F5c2VyIgpkYXRlOiAiTWFyY2ggMjQsIDIwMjIiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZ9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKKlRMRFI6KiBTa2lwIHRvIHRoZSBib3R0b20gdG8gc2VlIHRoZSBqYXZhc2NyaXB0IGZ1bmN0aW9uLgoKSSBkZWNpZGVkIHRvIGFkZCBhIGZlYXR1cmUgdG8gdGhlIHRlbnppZXMgY2hhbGxlbmdlIHRoYXQgd291bGQgc2hvdyBib3RoIHRoZSBudW1iZXIgb2Ygcm9sbHMgc28gCmZhciBhbmQgYSBwcmVkaWN0aW9uIGZvciB0aGUgbnVtYmVyIG9mIHJlbWFpbmluZyByb2xscy4gIFRoZSBwcmVkaWN0aW9uIHdvdWxkIHNpbXBseSBiZSBmcm9tIGFuIGVzdGltYXRlIG9mIHRoZQpleHBlY3RlZCBudW1iZXIgb2Ygcm9sbHMgdG8gZ2V0IHJlbWFpbmluZyB1bmZyb3plbiBkaWNlIHRvIGFsbCByb2xsIGEgdGFyZ2V0IHZhbHVlLS13aGF0ZXZlciB0aGUgdmFsdWUgaXMgeW91IGFscmVhZHkgaGF2ZSBmcm96ZW4uICAKClNvIGxldCdzIHNheSB5b3UganVzdCBmcm96ZSB5b3VyIDV0aCBkaWUsIGFuZCB5b3UgYXJlIGFib3V0IHRvIHJvbGwgdGhlIHJlbWFpbmluZyA1LiBBIG1lc3NhZ2Ugd2lsbCBhcHBlYXIKdGVsbGluZyB5b3UgaG93IG1hbnkgbW9yZSByb2xscyBhcmUgZXhwZWN0ZWQgdG8gZ2V0IHRoZSA1IHJlbWFpbmluZyBkaWNlIHRvIHlvdXIgbnVtYmVyLiAgVGhpcyBlc3RpbWF0ZSBkZWNyZWFzZXMKYnkgb25lIGFmdGVyIGVhY2ggcm9sbCB5b3UgbWFrZSwgZXZlbiBnb2luZyBuZWdhdGl2ZSBpZiB5b3UgYXJlIHVubHVja3kuICBJIGtub3cgdGhpcyBpc24ndCBsb2dpY2FsbHkgYWNjdXJhdGUgc2luY2UgdGhlIG9kZHMgZG9uJ3QgY2hhbmdlIG92ZXIgdGltZSAodGhlcmUgaXMgbm8gImxhdyBvZiBhdmVyYWdlcyIpLCBidXQgaXQgZG9lcyBnaXZlIHRoZSBuaWNlIGVmZmVjdCBvZiB0cmFja2luZyB5b3VyIGFjdHVhbCBudW1iZXIgb2Ygcm9sbHMgbW9yZSBjbG9zZWx5LgoKU28gdGhlIHF1ZXN0aW9uIGlzLCB3aGF0IGlzIHRoZSBhdmVyYWdlIChtZWFuLCBvciBleHBlY3RlZCB2YWx1ZSkgbnVtYmVyIG9mIHJvbGxzIG9mIGFsbCB0aGUgZGljZSBiZWZvcmUgdGhleSBhbGwKc2hvdyB0aGUgc2FtZSBudW1iZXI/ICBGb3IgdGhhdCBtYXR0ZXIsIHNob3VsZCB3ZSBiZSB1c2luZyB0aGUgYXZlcmFnZSwgdGhlIG1lZGlhbiBvciB0aGUgbW9kZT8gIFNpbmNlIHRoZSBkaXN0cmlidXRpb24gaXMgc2tld2VkLCBtZWRpYW4gd291bGQgcHJvYmFibHkgYmUgYSBiZXR0ZXIgbnVtYmVyIHRvIHRyYWNrLCBhbmQgbWF5YmUgZXZlbiB0aGUgbW9kZSwgYnV0IAp0aGUgbWVhbiBmZWx0IGxpa2UgbW9yZSBvZiBhIGNoYWxsZW5nZSBzbyB0aGF0J3Mgd2hhdCBJIHNldCBvdXQgdG8gZG8uCgojIyBBbmFseXNpcwoKUHJvYmFiaWxpdHkgb2YgYSBzdWNjZXMgaW4gb25lIHRocm93IGlzIHRoZSBwcm9iYWJsaXR5IG9mIHJvbGxpbmcgb25lIGZhY2Ugb2YgdGhlIGRpZSBvdXQgb2Ygc2l4OgoKJCRwID0gMS82JCQKCgpUaGUgcHJvYmFiaWxpdHkgb2YgX25vdF8gdGhyb3dpbmcgdGhlIHRhcmdldCB2YWx1ZSBpcyB0aGUgaW52ZXJzZSwgb3IgJDEtcCQuIFNvIHRoZSBwcm9iYWJpbGl0eSBvZiBrIHN1Y2Nlc3NpdmUgbWlzc2VzIGdpdmVuIGJ5IHRoaXMgZnVuY3Rpb246CgokJCgxLXApXmskJAoKSW52ZXJ0aW5nIHRoaXMgZ2l2ZXMgdGhlIHByb2JhYmlsaXR5IG9mIGF0IGxlYXN0IG9uZSBzdWNjZXNzIGluIGsgdGhyb3dzOgoKJCQxLSgxLXApXmskJApEb2VzIHRoaXMgcGFzcyB0aGUgaW50dWl0aW9uIHRlc3Q/ICBUaGUgaGlnaGVyIHRoZSB2YWx1ZSBvZiBrLCB0aGUgaGlnaGVyIHRoZSBsaWtlbGlob29kIG9mIGEgc3VjY2Vzcy4gIElmIHlvdQpyb2xsIGEgZGllIDEyIHRpbWVzLCB5b3UncmUgcHJldHR5IGNlcnRhaW4geW91J3JlIGdvaW5nIHRvIHJvbGwgdGhhdCBudW1iZXIuICBUaGUgZm9ybXVsYSB0ZWxscyB5b3UgaXQgd2lsbCBoYXBwZW4gd2l0aCBhIHByb2JhYmlsaXR5IG9mIGByIHNjYWxlczo6cGVyY2VudCgxIC0gKDEtKDEvNikpXjEyKWAuICBTZWVtcyBhYm91dCByaWdodC4KCkJ1dCBub3csIGlmIHlvdSBhcmUgcm9sbGluZyAkbiQgZGljZSwgdGhlbiB0aGUgcHJvYmFiaWxpdHkgb2YgZmluZGluZyBhdCBsZWFzdCBvbmUgc3VjY2VzcyBpbiAkayQgdGhyb3dzIG9mIGVhY2ggZGllIGlzIHRoZSBwcm9kdWN0IG9mIHRoZSBwcm9iYWJpbGl0aWVzIG9mIHN1Y2Nlc3Mgb2YgZWFjaCBpbmRpdmlkdWFsIGRpZToKCiQkKDEtKDEtcCleaylebiQkClRoZSBmaXJzdCBkZXJpdmlhdGl2ZSBvZiB0aGlzIGZvcm11bGEgd2lsbCBnaXZlIHlvdSB0aGUgUHJvYmFiaWxpdHkgTWFzcyBGdW5jdGlvbiAoUE1GKS4gIFRoaXMgd2lsbCB0ZWxsCnVzIHRoZSBwcm9iYWJpbGl0eSBvZiBhIHBhcnRpY3VsYXIgbnVtYmVyIG9mIHRocm93cyBiZWluZyB0aGUgZXhhY3QgbnVtYmVyIHJlcXVpcmVkLiAgSSBjaGVhdGVkIGFuZCB1c2VkCmEgc2l0ZSBjYWxsZWQgW2Rlcml2YXRpdmUtY2FsY3VsYXRvci5uZXRdKGh0dHBzOi8vd3d3LmRlcml2YXRpdmUtY2FsY3VsYXRvci5uZXQpIHRvIHdvcmsgb3V0IHRoZSBkZXJpdmF0aXZlLgoKJCQtblxsblxsZWZ0KDEtcFxyaWdodClcbGVmdCgxLVxsZWZ0KDEtcFxyaWdodClea1xyaWdodClee24tMX1cbGVmdCgxLXBccmlnaHQpXmskJApTbyB3aGF0IGlzIHRoZSBleHBlY3RlZCB2YWx1ZSBvZiAkayQgZ2l2ZW4gJG4kPyAgRnJvbSByZWFkaW5nIGRpZmZlcmVudCBhcnRpY2xlcyBpdCBhcHBlYXJzIHRoZXJlJ3MgYSBjbG9zZWQgZm9ybSBzb2x1dGlvbiBmb3IgdGhpcyBidXQgSSBkb24ndCB1bmRlcnN0YW5kIHRoZSBub3RhdGlvbiB3ZWxsIGVub3VnaCB0byBpbXBsZW1lbnQgaXQgc28gaW5zdGVhZCBJIGp1c3QgY2FsY3VsYXRlZAppdCBicnV0ZSBmb3JjZSBieSBtdWx0aXBseWluZyB0aGUgcm9sbHMgYnkgdGhlaXIgcHJvYmFiaWxpdHkgdXNpbmcgdGhlIFBNRiwgYWJvdmUuICBIZXJlJ3Mgd2hhdCB0aGF0IGxvb2tzIGxpa2U6IAoKJCRcc3VtX3trPTF9XnttfS1rblxsblxsZWZ0KDEtcFxyaWdodClcbGVmdCgxLVxsZWZ0KDEtcFxyaWdodClea1xyaWdodClee24tMX1cbGVmdCgxLXBccmlnaHQpXmskJAoKIyBWYWxpZGF0aW9uCgpTbyBob3cgYWNjdXJhdGUgaXMgdGhpcz8gIExldCdzIHRlc3QgdGhlIHZhbHVlcyBwcmVkaWN0ZWQgYnkgdGhlIG1vZGVsIHdpdGggYWN0dWFsIHNpbXVsYXRpb25zIG9mIHRoZSBnYW1lLgoKIyMjIEV2YWx1YXRpbmcgdGhlIE1vZGVsCgpUaGUgZ2FtZSBiZWdpbnMgd2l0aCBhIHJhbmRvbSByb2xsIHdoZXJlIHlvdSBjaG9vc2Ugd2hpY2ggZGljZSB0byAiZnJlZXplIi4gIEZvciAxMCBkaWNlLCB0aGUgYXZlcmFnZSBudW1iZXIgb2Ygc2FtZSBmYWNlZCBkaWNlIGlzIGFib3V0IDMuNSwgd2hpY2ggSSBmb3VuZCBmcm9tIHNpbXVsYXRpbmcuICAoSSBjb3VsZG4ndCBmaW5kIG9yIGZpZ3VyZSBvdXQgdGhlIGFjdHVhbCBzb2x1dGlvbikuClNvIGZvciBvdXIgbW9kZWwgd2UnbGwgYXNzdW1lIHdlIHN0YXJ0IHdpdGggdGhyZWUgZGljZSBvZiB0aGUgc2FtZSBmYWNlLCBhbmQgdGhlIHNlY29uZCByb2xsIHdpbGwgc3RhcnQgd2l0aCA3IGRpY2UgaW5zdGVhZCBvZiAxMC4gIAoKYGBge3J9CnAgPC0gMS82Cm4gPC0gNwpgYGAKCk5vdyBpbXBsZW1lbnQgdGhlIFBNRjoKCmBgYHtyfQoKcG1mIDwtIGZ1bmN0aW9uKHAsIGssIG4pIHsKICAtbiAqIGxvZygxLXApICogKCgxLSgxLXApXmspXihuLTEpKSAqICgxLXApXmsKfQpgYGAKCldoYXQgZG9lcyB0aGlzIGxvb2sgbGlrZT8KCmBgYHtyfQp4IDwtIDA6NDAKeSA8LSBwbWYoMS82LCB4LCAxMCkKZ2dwbG90KCkgKyBhZXMoeD14LTEsIHk9eSkgKyBnZW9tX2NvbCgpCmBgYAoKTm93IGNhbGN1bGF0ZSB0aGUgbWVhbiBudW1iZXIgb2Ygcm9sbHMgbG9va2luZyBhdCB0aGUgcHJvYmFiaWxpdGllcyBvZiB0aGUgZmlyc3QgNTAwIHJvbGxzLCBtdWx0aXBseWluZyBlYWNoCmJ5IHRoZSByb2xsIG51bWJlcjoKCmBgYHtyfQptZWFuX3JvbGxzIDwtIGZ1bmN0aW9uKHAsIG4pIHsKICBpdGVyIDwtIDEwMDAKICBzdW0gPC0gMAogIGZvciAoayBpbiAxOml0ZXIpIHsKICAgIHN1bSA8LSBzdW0gKyBrICogcG1mKHAsIGssIG4pCiAgfQogIHJldHVybihzdW0pCn0KCjEgKyBtZWFuX3JvbGxzKHAsIDgpCmBgYAoKIyMjIFJ1bm5pbmcgdGhlIHNpbXVsYXRpb25zCgpEZWZpbmUgYSBmdW5jdGlvbiB0byBydW4gb25lIHNpbXVsYXRpb24gd2l0aCBgbmAgZGljZS4KCmBgYHtyfQpzaW11bGF0ZSA8LSBmdW5jdGlvbihuKSB7CgogICMgUm9sbCBhIHNldCBvZiA2IGRpY2UgdXNpbmcgdW5pZm9ybSByYW5kb20gc2FtcGxlcwogIGZpcnN0cm9sbCA8LSBzYW1wbGUoMTo2LCAxMCwgcmVwbGFjZT1UUlVFKSB8PgogICAgdGFibGUoKSB8PgogICAgc29ydChkZWNyZWFzaW5nID0gVCkKICAKICAjIERlZmluZSB0aGUgdGFyZ2V0IGFzIHdoYXRldmVyIHdlIHJvbGxlZCB0aGUgbW9zdCBvZgogIHRhcmdldCA8LSBhcy5pbnRlZ2VyKG5hbWVzKGZpcnN0cm9sbFsxXSkpCiAgCiAgIyBOb3cgdGhlIHJlbWFpbmluZyBudW1iZXIgb2YgZGljZSB0byBzdGFydCByb2xsaW5nIGZvciBzaW11bGF0aW9uCiAgbi5kaWNlbGVmdCA8LSBuIC0gZmlyc3Ryb2xsWzFdCiAgaWYgKG4uZGljZWxlZnQgPT0gMCkgcmV0dXJuKDEpCiAgCiAgIyBOb3cgcG9wdWxhdGUgYSBtYXRyaXggd2l0aCByYW5kb20gbnVtYmVycyB3aG9zZSBjb2x1bW5zIHJlcHJlc2VudCBhIHNlcXVlbmNlIG9mIDEwMCByb2xscwogICMgb2YgZWFjaCBpbmRpdmlkdWFsIGRpY2UuICAKICBkaWNlLmhpc3RvcnkgPC0KICAgIHJ1bmlmKG4uZGljZWxlZnQgKiAxMDAsIDAsIDYpIHw+CiAgICBjZWlsaW5nKCkgfD4KICAgIG1hdHJpeChuY29sPW4uZGljZWxlZnQpCiAgICAKICAjIEZpbmQgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBzdWNjZXNzIGluIGVhY2ggY29sdW1uCiAgcm9sbHMudG8udGFyZ2V0IDwtIHNhcHBseSgxOm4uZGljZWxlZnQsIFwoY29sKSB7CiAgICByZXR1cm4od2hpY2goZGljZS5oaXN0b3J5Wyxjb2xdID09IHRhcmdldClbMV0pCiAgfSkKCiAgIyBUYWtlIHRoZSBtYXggb2YgdGhlIHJvbGxzIHJlcXVpcmVkIGZvciBlYWNoIGRpZSwgYW5kIGFkZCAxIGZvciBmaXJzdHJvbGwKICByZXR1cm4oMSArIG1heChyb2xscy50by50YXJnZXQpKQp9CmBgYAoKUnVuIGEgc2ltdWxhdGlvbiA1MCwwMDAgdGltZXMuCmBgYHtyfQppdGVyIDwtIDUwMDAwCnJlc3VsdHMgPC0gc2FwcGx5KDE6aXRlciwgXCh4KXsgcmV0dXJuKHNpbXVsYXRlKDEwKSkgfSkKIyBNb2RlOgpkZiA8LSB0YWJsZShyZXN1bHRzKQptb2RlIDwtIHNvcnQoZGVjcmVhc2luZyA9IFQsIGRmKVsxXQojIE1lYW4KYXZnIDwtIHN1bShyZXN1bHRzKSAvIGl0ZXIKYGBgCgpUaGUgbW9kZSB3YXMgYHIgbW9kZWAgYW5kIHRoZSBtZWFuIG51bWJlciBvZiB0aHJvd3Mgd2FzIGByIGF2Z2AuICBUaGUgd29yc3QgZ2FtZSB0b29rIGByIG1heChyZXN1bHRzKWAgcm9sbHMuCgojIyMjIEhpc3RvZ3JhbSBvZiBzaW11bGF0aW9uczoKCmBgYHtyfQpnZ3Bsb3QodGliYmxlKHg9cmVzdWx0cykpICsgYWVzKHg9eCkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsKICB4bGFiKCJOdW1iZXIgb2YgUm9sbHMgdG8gU3VjY2VzcyIpICsgeWxhYigiTnVtYmVyIG9mIFNpbXVsYXRpb25zIikKYGBgCgojIyBNb2RlbCB2cyBTaW11bGF0aW9uCgpUaGV5IGFyZSBwcmV0dHkgY2xvc2UuICAKCmBgYHtyfQpzaW0gPC0gcmVwKDAsIGxlbmd0aCh4KSkKaW5kaWNlcyA8LSBhcy5pbnRlZ2VyKG5hbWVzKGRmKSkgfD4gc29ydCgpCmZvciAoaSBpbiBpbmRpY2VzW2luZGljZXMgPD0gbGVuZ3RoKHgpXSkgewogIHNpbVtpXSA8LSBkZltpXS9pdGVyCn0KbW9kZWwudGFpbCA8LSBwbWYocCwgeCwgbi0zKQptb2RlbCA8LSBjKDAsIG1vZGVsLnRhaWxbMTpsZW5ndGgoeCktMV0pCmRhdGEgPC0gdGliYmxlKHg9eCwKICAgICAgICAgICAgICAgbW9kZWw9bW9kZWwsCiAgICAgICAgICAgICAgIHNpbXVsYXRpb249c2ltKSB8PgogIHBpdm90X2xvbmdlcihjb2xzPWMoJ21vZGVsJywgJ3NpbXVsYXRpb24nKSwKICAgICAgICAgICAgICBuYW1lc190bz0nUE1GJywKICAgICAgICAgICAgICB2YWx1ZXNfdG89IlByb2JhYmlsaXR5IikKCmdncGxvdChkYXRhKSArCiAgYWVzKHg9eCwgeT1Qcm9iYWJpbGl0eSwgY29sb3I9UE1GKSArCiAgZ2VvbV9saW5lKCkgKwogIHhsYWIoIk51bWJlciBvZiBSb2xscyB0byBTdWNjZXNzIikgKwogIHlsYWIoIlByb2JhYmlsaXR5IGZvciBHaXZlbiBOdW1iZXIgb2YgUm9sbHMiKQpgYGAKCiMgQXBwZW5kaXgKCiMjIyBIb3cgbWFueSBzYW1lIGRpY2UgYXJlIGxpa2VseSB0byBhcHBlYXIgaW4gb25lIHRocm93PwoKYGBge3J9CnJvbGxzIDwtIDEwMDAwCnN1bSA8LSAwCmZvciAoaSBpbiAxOnJvbGxzKSB7CiAgdGhyb3cgPC0gCiAgICBzdW0gPC0gc3VtICsgc2FtcGxlKDE6NiwgMTAsIHJlcGxhY2U9VCkgfD4KICAgIHRhYmxlKCkgfD4gCiAgICBzb3J0KGRlY3JlYXNpbmc9VCkgfD4KICAgIGhlYWQoMSkKfQpzdW0vcm9sbHMKYGBgCgojIyMgSmF2YXNjcmlwdCBGdW5jdGlvbiAKClRvIGNhbGN1bGF0ZSB0aGUgZXhwZWN0ZWQgbnVtYmVyIG9mIHJlbWFpbmluZyByb2xscyBhcyBhIGZ1bmN0aW9uIG9mIHVuZnJvemVuIGRpY2U6CgpgYGBqYXZhc2NyaXB0CgpmdW5jdGlvbiBldihuKSB7CiAgY29uc3QgcCA9IDEvNgogIGNvbnN0IGl0ZXIgPSA1MDAKICBsZXQgc3VtID0gMAogIGZvciAodmFyIGsgPSAxOyBrIDw9IGl0ZXI7IGsrKykgewogICAgY29uc3QgcHJvYiA9IC1uICogTWF0aC5sb2coMS1wKSAqICgoMS0oMS1wKSoqaykqKihuLTEpKSAqICgxLXApKiprCiAgICBzdW0gKz0gayAqIHByb2IKICB9CiAgcmV0dXJuKHN1bSkKfQoKYGBgCiAgICAgICAgICAgCiAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg