Inspired by FiveThirtyEight’s 2018 Christmas Riddler problem.

library(dplyr)
library(ggplot2)

Riddler Classic

From Steven Pratt, the best way to spread Christmas cheer is singing loud for all to hear:

In Santa’s workshop, elves make toys during a shift each day. On the overhead radio, Christmas music plays, with a program randomly selecting songs from a large playlist.

During any given shift, the elves hear 100 songs. A cranky elf named Cranky has taken to throwing snowballs at everyone if he hears the same song twice. This has happened during about half of the shifts. One day, a mathematically inclined elf named Mathy tires of Cranky’s sodden outbursts. So Mathy decides to use what he knows to figure out how large Santa’s playlist actually is.

Help Mathy out: How large is Santa’s playlist?

Birthday problem

This question is a generalization of the birthday problem, which goes something like this.

You’re at a party with 29 other people. How likely is it that someone shares a birthday with another partygoer?

Let’s make a couple assumptions. Suppose no attendees are born on a leap year, and people are equally likely to be born on each of the 365 remaining days.

The chance at least one pair shares a birthday is simply:

\[ P(\text{share}) = 1 - P(\text{not share}) \]

To make this concrete, let \(n\) be the total number of partygoers and consider \(n \in \{1, 2, 3\}\).

If you’re the only one in the room, clearly the probability that someone else shares your birthday is 0.

If there are two people total in the room, then both would need to be born on the same day to share a birthday, which is a \(1/365\) chance.

If there are three in the room, it gets a bit more complicated. The odds are not additive, i.e. \(2/365\), which is the most common mistake I’ve seen. We need to compare the individuals not with you (2 comparisons), but with each other as well (3 total comparisons). Essentially, they all have to be born on different days.

For no one to share a birthday, the first person can be born on any of the 365 days. The second partygoer can be born on any of the 364 remaining days, and the third on any of the 363 days not already taken. These probabilities all multiply. In other words:

\[ P(\text{share}) = 1 - P(\text{not share}) = 1 - \frac{365}{365} * \frac{364}{365} * \frac{363}{365} \approx .0082 \]

Thus, given \(n\) people:

\[ P(\text{not share}) = \left\{ \begin{array}{ll} \prod_{x=1}^{n} \frac{366-x}{365} ~ , ~ n \in [1,366] \\ 0, n > 366 \end{array} \right. \]

So for the case where \(n = 30\) we have:

\[ P(\text{share}) = 1 - \prod_{x = 1}^{30} \frac{366-x}{365} \]

# Function to compute birthday probabilities
p.bday <- function(n) {
  if (n > 366) {return(1)}
  return(1 - prod(365:(366 - n)) / 365^n)
}
p.bday(30)
[1] 0.7063162

There’s about a 70.6% chance at least one pair in the room of 30 partygoers shares a birthday!

Visualizing this for a range of \(n\), we see that the probabilities increase much more quickly than the 1/365 slope linear trendline (extrapolated from the first two points):

n <- 50
data.frame(
  attendees = 1:n
  , probability = sapply(1:n, FUN = p.bday)
  , linear.trend = {0:(n - 1)}/365
) %>%
  ggplot(aes(x = attendees, y = probability)) +
  geom_point() +
  geom_line() +
  geom_line(aes(y = linear.trend), color = 'blue', linetype = 'dashed') +
  labs(title = 'Probability of sharing a birthday by number of attendees')

As an aside, note that due to the \(365^n\) term in the denominator, for large \(n\) this function will lead to computational overflow errors.

p.bday(300)
[1] NaN

Riddler solution

The Riddler is this same type of problem, but the size of the playlist \(s\) is unknown. So we have:

\[ 0.5 \approx 1 - \prod_{x = 1}^{100} \frac{s + 1 - x}{s} \]

Or:

\[ 0.5 \approx \prod_{x = 1}^{100} \frac{s + 1 - x}{s} \]

Which is written out as:

\[ 0.5 \approx \frac{(s)(s-1)\dots(s-99)}{s^{100}} \]

To avoid integer overflow this should be rewritten in log space.

\[ \ln(.5) \approx \ln(s) + \ln(s-1) + \dots + \ln(s-99) - 100\ln(s) \\= \ln(s-1) + \dots + \ln(s-99) - 99 \ln(s) \]

Define \(f(s)\) as the probability of a repeated song for an arbitrary size \(s\) playlist.

f.s <- function(s) {
  if(s < 100) {return(1)}
  logp <- -99 * log(s)
  for (i in 1:99) {
    logp <- logp + log(s - i)
  }
  return(1 - exp(logp))
}
n <- seq(500, 15000, by = 500)
data.frame(
  songs = n
  , probability = sapply(n, FUN = f.s)
) %>%
  ggplot(aes(x = songs, y = probability)) +
  geom_point() +
  geom_line() +
  geom_hline(yintercept = .5, color = 'blue', linetype = 'dashed') +
  scale_x_continuous(breaks = seq(0, 1E6, by = 1000)) +
  labs(title = 'Probability of repeated songs by size of playlist')

We see the playlist must be between 7000 and 7500 songs. To be precise, we need to solve for \(f(s) - .5 \approx 0\).

s.candidates <- sapply(7000:7500, f.s) - .5

Which \(s\) first tips from positive to negative?

7000 + which(s.candidates < 0)[1] - 1
[1] 7175

So there are either 7175 or 7174 songs on the playlist depending on how Mathy prefers to round.

Generalized birthday problem

The preceding two functions provide an easy way to generalize the birthday probability calculation for arbitrary \(n\) and \(s\).

# General function to calculate P(not share)
p.generalized <- function(n, s, log = FALSE) {
  # Error checking
  if(
    !is.numeric(n)
    || n != round(n)
    || !is.numeric(s)
    || s != round(s)
  ) {
    stop('Requires integer inputs')
  }
  # Too small n gives P = 0
  if(n <= 1) {
    ifelse(
      log
      , return(-Inf)
      , return(0)
    )
  }
  # Too small s gives P = 0
  if(s < n) {
    ifelse(
      log
      , return(-Inf)
      , return(0)
    )
  }
  # All other n, s
  logp <- (1 - n) * log(s)
  for (i in 1:(n - 1)) {
    logp <- logp + log(s - i)
  }
  ifelse(
    log
    , return(logp)
    , return(exp(logp))
  )
}

Let’s test this on the birthday problem.

1 - p.generalized(n = 30, s = 365)
[1] 0.7063162

Since the operations take place in log space, this works even for large \(n\).

p.generalized(n = 365, s = 365)
[1] 1.454955e-157

Testing it on the Riddler:

1 - p.generalized(n = 100, s = 7175)
[1] 0.4999798

All results are exactly as expected.

LS0tDQp0aXRsZTogIkdlbmVyYWxpemluZyB0aGUgYmlydGhkYXkgcHJvYmxlbSINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IEZBTFNFDQotLS0NCg0KSW5zcGlyZWQgYnkgW0ZpdmVUaGlydHlFaWdodCdzIDIwMTggQ2hyaXN0bWFzIFJpZGRsZXIgcHJvYmxlbV0oaHR0cHM6Ly9maXZldGhpcnR5ZWlnaHQuY29tL2ZlYXR1cmVzL3NhbnRhLW5lZWRzLXNvbWUtaGVscC13aXRoLW1hdGgvKS4NCg0KYGBge3Igc2V0dXAsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmBgYA0KDQojIFJpZGRsZXIgQ2xhc3NpYw0KDQo+IEZyb20gU3RldmVuIFByYXR0LCB0aGUgYmVzdCB3YXkgdG8gc3ByZWFkIENocmlzdG1hcyBjaGVlciBpcyBzaW5naW5nIGxvdWQgZm9yIGFsbCB0byBoZWFyOg0KPg0KPiBJbiBTYW50YeKAmXMgd29ya3Nob3AsIGVsdmVzIG1ha2UgdG95cyBkdXJpbmcgYSBzaGlmdCBlYWNoIGRheS4gT24gdGhlIG92ZXJoZWFkIHJhZGlvLCBDaHJpc3RtYXMgbXVzaWMgcGxheXMsIHdpdGggYSBwcm9ncmFtIHJhbmRvbWx5IHNlbGVjdGluZyBzb25ncyBmcm9tIGEgbGFyZ2UgcGxheWxpc3QuDQo+DQo+IER1cmluZyBhbnkgZ2l2ZW4gc2hpZnQsIHRoZSBlbHZlcyBoZWFyIDEwMCBzb25ncy4gQSBjcmFua3kgZWxmIG5hbWVkIENyYW5reSBoYXMgdGFrZW4gdG8gdGhyb3dpbmcgc25vd2JhbGxzIGF0IGV2ZXJ5b25lIGlmIGhlIGhlYXJzIHRoZSBzYW1lIHNvbmcgdHdpY2UuIFRoaXMgaGFzIGhhcHBlbmVkIGR1cmluZyBhYm91dCBoYWxmIG9mIHRoZSBzaGlmdHMuIE9uZSBkYXksIGEgbWF0aGVtYXRpY2FsbHkgaW5jbGluZWQgZWxmIG5hbWVkIE1hdGh5IHRpcmVzIG9mIENyYW5reeKAmXMgc29kZGVuIG91dGJ1cnN0cy4gU28gTWF0aHkgZGVjaWRlcyB0byB1c2Ugd2hhdCBoZSBrbm93cyB0byBmaWd1cmUgb3V0IGhvdyBsYXJnZSBTYW50YeKAmXMgcGxheWxpc3QgYWN0dWFsbHkgaXMuDQo+DQo+IEhlbHAgTWF0aHkgb3V0OiBIb3cgbGFyZ2UgaXMgU2FudGHigJlzIHBsYXlsaXN0Pw0KDQojIEJpcnRoZGF5IHByb2JsZW0NCg0KVGhpcyBxdWVzdGlvbiBpcyBhIGdlbmVyYWxpemF0aW9uIG9mIHRoZSBiaXJ0aGRheSBwcm9ibGVtLCB3aGljaCBnb2VzIHNvbWV0aGluZyBsaWtlIHRoaXMuDQoNCj4gWW91J3JlIGF0IGEgcGFydHkgd2l0aCAyOSBvdGhlciBwZW9wbGUuIEhvdyBsaWtlbHkgaXMgaXQgdGhhdCBzb21lb25lIHNoYXJlcyBhIGJpcnRoZGF5IHdpdGggYW5vdGhlciBwYXJ0eWdvZXI/DQoNCkxldCdzIG1ha2UgYSBjb3VwbGUgYXNzdW1wdGlvbnMuIFN1cHBvc2Ugbm8gYXR0ZW5kZWVzIGFyZSBib3JuIG9uIGEgbGVhcCB5ZWFyLCBhbmQgcGVvcGxlIGFyZSBlcXVhbGx5IGxpa2VseSB0byBiZSBib3JuIG9uIGVhY2ggb2YgdGhlIDM2NSByZW1haW5pbmcgZGF5cy4gDQoNClRoZSBjaGFuY2UgYXQgbGVhc3Qgb25lIHBhaXIgc2hhcmVzIGEgYmlydGhkYXkgaXMgc2ltcGx5Og0KDQokJCBQKFx0ZXh0e3NoYXJlfSkgPSAxIC0gUChcdGV4dHtub3Qgc2hhcmV9KSAkJA0KDQpUbyBtYWtlIHRoaXMgY29uY3JldGUsIGxldCAkbiQgYmUgdGhlIHRvdGFsIG51bWJlciBvZiBwYXJ0eWdvZXJzIGFuZCBjb25zaWRlciAkbiBcaW4gXHsxLCAyLCAzXH0kLg0KDQpJZiB5b3UncmUgdGhlIG9ubHkgb25lIGluIHRoZSByb29tLCBjbGVhcmx5IHRoZSBwcm9iYWJpbGl0eSB0aGF0IHNvbWVvbmUgZWxzZSBzaGFyZXMgeW91ciBiaXJ0aGRheSBpcyAwLg0KDQpJZiB0aGVyZSBhcmUgdHdvIHBlb3BsZSB0b3RhbCBpbiB0aGUgcm9vbSwgdGhlbiBib3RoIHdvdWxkIG5lZWQgdG8gYmUgYm9ybiBvbiB0aGUgc2FtZSBkYXkgdG8gc2hhcmUgYSBiaXJ0aGRheSwgd2hpY2ggaXMgYSAkMS8zNjUkIGNoYW5jZS4NCg0KSWYgdGhlcmUgYXJlIHRocmVlIGluIHRoZSByb29tLCBpdCBnZXRzIGEgYml0IG1vcmUgY29tcGxpY2F0ZWQuIFRoZSBvZGRzIGFyZSAqbm90KiBhZGRpdGl2ZSwgaS5lLiAkMi8zNjUkLCB3aGljaCBpcyB0aGUgbW9zdCBjb21tb24gbWlzdGFrZSBJJ3ZlIHNlZW4uIFdlIG5lZWQgdG8gY29tcGFyZSB0aGUgaW5kaXZpZHVhbHMgbm90IHdpdGggeW91ICgyIGNvbXBhcmlzb25zKSwgYnV0IHdpdGggZWFjaCBvdGhlciBhcyB3ZWxsICgzIHRvdGFsIGNvbXBhcmlzb25zKS4gRXNzZW50aWFsbHksIHRoZXkgYWxsIGhhdmUgdG8gYmUgYm9ybiBvbiBkaWZmZXJlbnQgZGF5cy4NCg0KRm9yIG5vIG9uZSB0byBzaGFyZSBhIGJpcnRoZGF5LCB0aGUgZmlyc3QgcGVyc29uIGNhbiBiZSBib3JuIG9uIGFueSBvZiB0aGUgMzY1IGRheXMuIFRoZSBzZWNvbmQgcGFydHlnb2VyIGNhbiBiZSBib3JuIG9uIGFueSBvZiB0aGUgMzY0IHJlbWFpbmluZyBkYXlzLCBhbmQgdGhlIHRoaXJkIG9uIGFueSBvZiB0aGUgMzYzIGRheXMgbm90IGFscmVhZHkgdGFrZW4uIFRoZXNlIHByb2JhYmlsaXRpZXMgYWxsIG11bHRpcGx5LiBJbiBvdGhlciB3b3JkczoNCg0KJCQgUChcdGV4dHtzaGFyZX0pID0gMSAtIFAoXHRleHR7bm90IHNoYXJlfSkgPSAxIC0gXGZyYWN7MzY1fXszNjV9ICogXGZyYWN7MzY0fXszNjV9ICogXGZyYWN7MzYzfXszNjV9IFxhcHByb3ggLjAwODIgJCQNCg0KVGh1cywgZ2l2ZW4gJG4kIHBlb3BsZToNCg0KJCQgUChcdGV4dHtub3Qgc2hhcmV9KSA9IFxsZWZ0XHsgDQogIFxiZWdpbnthcnJheX17bGx9DQogICAgXHByb2Rfe3g9MX1ee259IFxmcmFjezM2Ni14fXszNjV9IH4gLCB+IG4gXGluIFsxLDM2Nl0NCiAgICBcXCAwLCBuID4gMzY2DQogIFxlbmR7YXJyYXl9DQpccmlnaHQuICQkDQoNClNvIGZvciB0aGUgY2FzZSB3aGVyZSAkbiA9IDMwJCB3ZSBoYXZlOg0KDQokJCBQKFx0ZXh0e3NoYXJlfSkgPSAxIC0gXHByb2Rfe3ggPSAxfV57MzB9IFxmcmFjezM2Ni14fXszNjV9ICQkDQoNCmBgYHtyfQ0KIyBGdW5jdGlvbiB0byBjb21wdXRlIGJpcnRoZGF5IHByb2JhYmlsaXRpZXMNCnAuYmRheSA8LSBmdW5jdGlvbihuKSB7DQogIGlmIChuID4gMzY2KSB7cmV0dXJuKDEpfQ0KICByZXR1cm4oMSAtIHByb2QoMzY1OigzNjYgLSBuKSkgLyAzNjVebikNCn0NCmBgYA0KYGBge3J9DQpwLmJkYXkoMzApDQpgYGANCg0KVGhlcmUncyBhYm91dCBhIGByIHAuYmRheSgzMCkgJT4lIHNjYWxlczo6cGVyY2VudCgpICU+JSBJKClgIGNoYW5jZSBhdCBsZWFzdCBvbmUgcGFpciBpbiB0aGUgcm9vbSBvZiAzMCBwYXJ0eWdvZXJzIHNoYXJlcyBhIGJpcnRoZGF5IQ0KDQpWaXN1YWxpemluZyB0aGlzIGZvciBhIHJhbmdlIG9mICRuJCwgd2Ugc2VlIHRoYXQgdGhlIHByb2JhYmlsaXRpZXMgaW5jcmVhc2UgbXVjaCBtb3JlIHF1aWNrbHkgdGhhbiB0aGUgMS8zNjUgc2xvcGUgbGluZWFyIHRyZW5kbGluZSAoZXh0cmFwb2xhdGVkIGZyb20gdGhlIGZpcnN0IHR3byBwb2ludHMpOg0KDQpgYGB7cn0NCm4gPC0gNTANCmRhdGEuZnJhbWUoDQogIGF0dGVuZGVlcyA9IDE6bg0KICAsIHByb2JhYmlsaXR5ID0gc2FwcGx5KDE6biwgRlVOID0gcC5iZGF5KQ0KICAsIGxpbmVhci50cmVuZCA9IHswOihuIC0gMSl9LzM2NQ0KKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gYXR0ZW5kZWVzLCB5ID0gcHJvYmFiaWxpdHkpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gbGluZWFyLnRyZW5kKSwgY29sb3IgPSAnYmx1ZScsIGxpbmV0eXBlID0gJ2Rhc2hlZCcpICsNCiAgbGFicyh0aXRsZSA9ICdQcm9iYWJpbGl0eSBvZiBzaGFyaW5nIGEgYmlydGhkYXkgYnkgbnVtYmVyIG9mIGF0dGVuZGVlcycpDQpgYGANCg0KQXMgYW4gYXNpZGUsIG5vdGUgdGhhdCBkdWUgdG8gdGhlICQzNjVebiQgdGVybSBpbiB0aGUgZGVub21pbmF0b3IsIGZvciBsYXJnZSAkbiQgdGhpcyBmdW5jdGlvbiB3aWxsIGxlYWQgdG8gY29tcHV0YXRpb25hbCBvdmVyZmxvdyBlcnJvcnMuDQoNCmBgYHtyfQ0KcC5iZGF5KDMwMCkNCmBgYA0KDQojIFJpZGRsZXIgc29sdXRpb24NCg0KVGhlIFJpZGRsZXIgaXMgdGhpcyBzYW1lIHR5cGUgb2YgcHJvYmxlbSwgYnV0IHRoZSBzaXplIG9mIHRoZSBwbGF5bGlzdCAkcyQgaXMgdW5rbm93bi4gU28gd2UgaGF2ZToNCg0KJCQgMC41IFxhcHByb3ggMSAtIFxwcm9kX3t4ID0gMX1eezEwMH0gXGZyYWN7cyArIDEgLSB4fXtzfSAkJA0KDQpPcjoNCg0KJCQgMC41IFxhcHByb3ggXHByb2Rfe3ggPSAxfV57MTAwfSBcZnJhY3tzICsgMSAtIHh9e3N9ICQkDQoNCldoaWNoIGlzIHdyaXR0ZW4gb3V0IGFzOg0KDQokJCAwLjUgXGFwcHJveCBcZnJhY3socykocy0xKVxkb3RzKHMtOTkpfXtzXnsxMDB9fSAkJA0KDQpUbyBhdm9pZCBpbnRlZ2VyIG92ZXJmbG93IHRoaXMgc2hvdWxkIGJlIHJld3JpdHRlbiBpbiBsb2cgc3BhY2UuDQoNCiQkIFxsbiguNSkgXGFwcHJveCBcbG4ocykgKyBcbG4ocy0xKSArIFxkb3RzICsgXGxuKHMtOTkpIC0gMTAwXGxuKHMpIFxcPSBcbG4ocy0xKSArIFxkb3RzICsgXGxuKHMtOTkpIC0gOTkgXGxuKHMpICQkDQoNCkRlZmluZSAkZihzKSQgYXMgdGhlIHByb2JhYmlsaXR5IG9mIGEgcmVwZWF0ZWQgc29uZyBmb3IgYW4gYXJiaXRyYXJ5IHNpemUgJHMkIHBsYXlsaXN0Lg0KDQpgYGB7cn0NCmYucyA8LSBmdW5jdGlvbihzKSB7DQogIGlmKHMgPCAxMDApIHtyZXR1cm4oMSl9DQogIGxvZ3AgPC0gLTk5ICogbG9nKHMpDQogIGZvciAoaSBpbiAxOjk5KSB7DQogICAgbG9ncCA8LSBsb2dwICsgbG9nKHMgLSBpKQ0KICB9DQogIHJldHVybigxIC0gZXhwKGxvZ3ApKQ0KfQ0KYGBgDQpgYGB7cn0NCm4gPC0gc2VxKDUwMCwgMTUwMDAsIGJ5ID0gNTAwKQ0KZGF0YS5mcmFtZSgNCiAgc29uZ3MgPSBuDQogICwgcHJvYmFiaWxpdHkgPSBzYXBwbHkobiwgRlVOID0gZi5zKQ0KKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gc29uZ3MsIHkgPSBwcm9iYWJpbGl0eSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAuNSwgY29sb3IgPSAnYmx1ZScsIGxpbmV0eXBlID0gJ2Rhc2hlZCcpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxRTYsIGJ5ID0gMTAwMCkpICsNCiAgbGFicyh0aXRsZSA9ICdQcm9iYWJpbGl0eSBvZiByZXBlYXRlZCBzb25ncyBieSBzaXplIG9mIHBsYXlsaXN0JykNCmBgYA0KDQpXZSBzZWUgdGhlIHBsYXlsaXN0IG11c3QgYmUgYmV0d2VlbiA3MDAwIGFuZCA3NTAwIHNvbmdzLiBUbyBiZSBwcmVjaXNlLCB3ZSBuZWVkIHRvIHNvbHZlIGZvciAkZihzKSAtIC41IFxhcHByb3ggMCQuDQoNCmBgYHtyfQ0Kcy5jYW5kaWRhdGVzIDwtIHNhcHBseSg3MDAwOjc1MDAsIGYucykgLSAuNQ0KYGBgDQoNCldoaWNoICRzJCBmaXJzdCB0aXBzIGZyb20gcG9zaXRpdmUgdG8gbmVnYXRpdmU/DQoNCmBgYHtyfQ0KNzAwMCArIHdoaWNoKHMuY2FuZGlkYXRlcyA8IDApWzFdIC0gMQ0KYGBgDQoNClNvIHRoZXJlIGFyZSBlaXRoZXIgYHIgezcwMDAgKyB3aGljaChzLmNhbmRpZGF0ZXMgPCAwKVsxXSAtIDF9ICU+JSBJKClgIG9yIGByIHs3MDAwICsgd2hpY2gocy5jYW5kaWRhdGVzIDwgMClbMV0gLSAyfSAlPiUgSSgpYCBzb25ncyBvbiB0aGUgcGxheWxpc3QgZGVwZW5kaW5nIG9uIGhvdyBNYXRoeSBwcmVmZXJzIHRvIHJvdW5kLg0KDQojIEdlbmVyYWxpemVkIGJpcnRoZGF5IHByb2JsZW0NCg0KVGhlIHByZWNlZGluZyB0d28gZnVuY3Rpb25zIHByb3ZpZGUgYW4gZWFzeSB3YXkgdG8gZ2VuZXJhbGl6ZSB0aGUgYmlydGhkYXkgcHJvYmFiaWxpdHkgY2FsY3VsYXRpb24gZm9yIGFyYml0cmFyeSAkbiQgYW5kICRzJC4NCg0KYGBge3J9DQojIEdlbmVyYWwgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIFAobm90IHNoYXJlKQ0KcC5nZW5lcmFsaXplZCA8LSBmdW5jdGlvbihuLCBzLCBsb2cgPSBGQUxTRSkgew0KICAjIEVycm9yIGNoZWNraW5nDQogIGlmKA0KICAgICFpcy5udW1lcmljKG4pDQogICAgfHwgbiAhPSByb3VuZChuKQ0KICAgIHx8ICFpcy5udW1lcmljKHMpDQogICAgfHwgcyAhPSByb3VuZChzKQ0KICApIHsNCiAgICBzdG9wKCdSZXF1aXJlcyBpbnRlZ2VyIGlucHV0cycpDQogIH0NCiAgIyBUb28gc21hbGwgbiBnaXZlcyBQID0gMA0KICBpZihuIDw9IDEpIHsNCiAgICBpZmVsc2UoDQogICAgICBsb2cNCiAgICAgICwgcmV0dXJuKC1JbmYpDQogICAgICAsIHJldHVybigwKQ0KICAgICkNCiAgfQ0KICAjIFRvbyBzbWFsbCBzIGdpdmVzIFAgPSAwDQogIGlmKHMgPCBuKSB7DQogICAgaWZlbHNlKA0KICAgICAgbG9nDQogICAgICAsIHJldHVybigtSW5mKQ0KICAgICAgLCByZXR1cm4oMCkNCiAgICApDQogIH0NCiAgIyBBbGwgb3RoZXIgbiwgcw0KICBsb2dwIDwtICgxIC0gbikgKiBsb2cocykNCiAgZm9yIChpIGluIDE6KG4gLSAxKSkgew0KICAgIGxvZ3AgPC0gbG9ncCArIGxvZyhzIC0gaSkNCiAgfQ0KICBpZmVsc2UoDQogICAgbG9nDQogICAgLCByZXR1cm4obG9ncCkNCiAgICAsIHJldHVybihleHAobG9ncCkpDQogICkNCn0NCmBgYA0KDQpMZXQncyB0ZXN0IHRoaXMgb24gdGhlIGJpcnRoZGF5IHByb2JsZW0uDQoNCmBgYHtyfQ0KMSAtIHAuZ2VuZXJhbGl6ZWQobiA9IDMwLCBzID0gMzY1KQ0KYGBgDQoNClNpbmNlIHRoZSBvcGVyYXRpb25zIHRha2UgcGxhY2UgaW4gbG9nIHNwYWNlLCB0aGlzIHdvcmtzIGV2ZW4gZm9yIGxhcmdlICRuJC4NCg0KYGBge3J9DQpwLmdlbmVyYWxpemVkKG4gPSAzNjUsIHMgPSAzNjUpDQpgYGANCg0KVGVzdGluZyBpdCBvbiB0aGUgUmlkZGxlcjoNCg0KYGBge3J9DQoxIC0gcC5nZW5lcmFsaXplZChuID0gMTAwLCBzID0gNzE3NSkNCmBgYA0KDQpBbGwgcmVzdWx0cyBhcmUgZXhhY3RseSBhcyBleHBlY3RlZC4=