Samples and Populations

The population considered in the book is contained in the nycflights13 dataset. In the nycflights13 dataset contains all of the departing flights from airports in the NYC Area.

library(pacman)
p_load(mdsr, nycflights13, tidyverse, skimr)

Recall the flights dataframe.

flights

Take a sample of flights from NYC to SF. Get all of the flights to SF and take a sample of 25 of them.

Note that I did not set a seed for the sample, so your answers will differ from what is in the book.

SF <- flights %>% 
  filter(dest == "SFO", !is.na(arr_delay))
SF
  
sf_25 <- SF %>%
  slice_sample(n = 25)

Get the summary statistics for the sample taken.

sf_25 %>%
  skim(arr_delay)
── Data Summary ────────────────────────
                           Values    
Name                       Piped data
Number of rows             25        
Number of columns          19        
_______________________              
Column type frequency:               
  numeric                  1         
________________________             
Group variables                      

── Variable type: numeric ──────────────────────────────────────────────────────────────────────────────────────────────────────
  skim_variable n_missing complete_rate  mean    sd    p0   p25   p50   p75  p100 hist 
1 arr_delay             0             1  47.4  94.5   -60    -8    16    70   317 ▇▅▁▁▁

Since the SF dataset contains all flights from NYC to SF in 2013, the statistics computed from the SF dataset are the calculated population paramters.

SF %>%
  skim(arr_delay)
── Data Summary ────────────────────────
                           Values    
Name                       Piped data
Number of rows             13173     
Number of columns          19        
_______________________              
Column type frequency:               
  numeric                  1         
________________________             
Group variables                      

── Variable type: numeric ──────────────────────────────────────────────────────────────────────────────────────────────────────
  skim_variable n_missing complete_rate  mean    sd    p0   p25   p50   p75  p100 hist 
1 arr_delay             0             1  2.67  47.7   -86   -23    -8    12  1007 ▇▁▁▁▁

Get the 98th percentile of the sample.

sf_25 %>%
  summarize(q98 = quantile(arr_delay, p = 0.98))

Get the estimated proportion of filights to SF with a delay less than 90 minutes.

SF %>%
  group_by(arr_delay < 90) %>%
  count() %>%
  mutate(pct = n / nrow(SF))

Compare with the 98th percentile. 90 minutes is the 95th percentile.

SF %>%
  summarize(q98 = quantile(arr_delay, p = 0.98))

Sample Statistics

The sampling distribution.

Usually sampling is done without replacement.

n <- 25
SF %>%
  slice_sample(n = n) %>%
  summarize(mean_arr_delay = mean(arr_delay))

Note that different random sample produce different values for the sample statistic.

SF %>%
  slice_sample(n = n) %>%
  summarize(mean_arr_delay = mean(arr_delay))

Using simulation we can approximate the sampling distribution of the sample statistics. Here we are computing the mean, but we could do this for any statistic we are interested in, the median, sample variance, sample standard deviation, etc.

Note that the do() function is from the mosaic package. We could just use a for loop.

num_trials <- 500
sf_25_means <- 1:num_trials %>%
  map_dfr(
    ~ SF %>%
      slice_sample(n = n) %>%
      summarize(mean_arr_delay = mean(arr_delay))
  ) %>%
  mutate(n = n)
head(sf_25_means)

Summarize the sample means.

sf_25_means %>%
  skim(mean_arr_delay)
── Data Summary ────────────────────────
                           Values    
Name                       Piped data
Number of rows             500       
Number of columns          2         
_______________________              
Column type frequency:               
  numeric                  1         
________________________             
Group variables                      

── Variable type: numeric ──────────────────────────────────────────────────────────────────────────────────────────────────────
  skim_variable  n_missing complete_rate  mean    sd    p0   p25   p50   p75  p100 hist 
1 mean_arr_delay         0             1  2.62  9.61 -20.5 -4.59   1.3  8.75  57.3 ▃▇▃▁▁

Confidence intervals

sf_25_means %>%
  summarize(
    x_bar = mean(mean_arr_delay),
    se = sd(mean_arr_delay)
  ) %>%
  mutate(
    ci_lower = x_bar - 2 * se, # approximately 95% of observations 
    ci_upper = x_bar + 2 * se  # are within two standard errors
  ) 

Using a larger sample size give a smaller Standard Error.

n <- 100
sf_100_means <- 1:500 %>%
  map_dfr(
    ~ SF %>%
      slice_sample(n = n) %>%
      summarize(mean_arr_delay = mean(arr_delay))
  ) %>%
  mutate(n = n)

Plots to compare the sampling distributions with different sample sizes.

sf_25_means %>%
  bind_rows(sf_100_means) %>%
  ggplot(aes(x = mean_arr_delay)) + 
  geom_histogram(bins = 30) + 
  facet_grid( ~ n) + 
  xlab("Sample mean")

Boostrap

Usually for random sampling we sample without replacement.

three_flights <- SF %>%
  slice_sample(n = 3, replace = FALSE) %>%
  select(year, month, day, dep_time)
three_flights

With the Bootstrap we use sampling with replacement

three_flights %>% slice_sample(n = 3, replace = TRUE)
n <- 200
orig_sample <- SF %>% 
  slice_sample(n = n, replace = FALSE)
orig_sample

The reason for sampling with replacement is that we only have the Original Sample of size \(n\). We do not have the population. So if we sampled with out replacement we would only have one sample to look at. Sampling the Original Sample with replace allow us to general lots of samples and to investiage the variability of these samples.

orig_sample %>%
  slice_sample(n = n, replace = TRUE) %>%
  summarize(mean_arr_delay = mean(arr_delay))
sf_200_bs <- 1:num_trials %>%
  map_dfr(
    ~orig_sample %>%
      slice_sample(n = n, replace = TRUE) %>%
      summarize(mean_arr_delay = mean(arr_delay))
  ) %>%
  mutate(n = n)
sf_200_bs %>%
  skim(mean_arr_delay)
── Data Summary ────────────────────────
                           Values    
Name                       Piped data
Number of rows             500       
Number of columns          2         
_______________________              
Column type frequency:               
  numeric                  1         
________________________             
Group variables                      

── Variable type: numeric ──────────────────────────────────────────────────────────────────────────────────────────────────────
  skim_variable  n_missing complete_rate  mean    sd    p0   p25   p50   p75  p100 hist 
1 mean_arr_delay         0             1  2.99  3.10 -5.32  1.06  2.84  4.82  14.2 ▁▇▇▂▁
sf_200_bs %>% ggplot(aes(x = mean_arr_delay)) +
  geom_histogram()

sf_200_pop <- 1:num_trials %>%
  map_dfr(
    ~SF %>%
      slice_sample(n = n, replace = TRUE) %>%
      summarize(mean_arr_delay = mean(arr_delay))
  ) %>%
  mutate(n = n)
sf_200_pop %>%
  skim(mean_arr_delay)
── Data Summary ────────────────────────
                           Values    
Name                       Piped data
Number of rows             500       
Number of columns          2         
_______________________              
Column type frequency:               
  numeric                  1         
________________________             
Group variables                      

── Variable type: numeric ──────────────────────────────────────────────────────────────────────────────────────────────────────
  skim_variable  n_missing complete_rate  mean    sd    p0   p25   p50   p75  p100 hist 
1 mean_arr_delay         0             1  2.54  3.42 -7.16 0.232  2.52  4.77  11.5 ▁▅▇▆▁
sf_200_pop %>% ggplot(aes(x = mean_arr_delay)) +
  geom_histogram()

Question: Do the histograms look somewhat similar?

orig_sample %>%
  summarize(q98 = quantile(arr_delay, p = 0.98))
n <- nrow(orig_sample)
sf_200_bs <- 1:num_trials %>%
  map_dfr(
    ~orig_sample %>%
      slice_sample(n = n, replace = TRUE) %>%
      summarize(q98 = quantile(arr_delay, p = 0.98))
  )
sf_200_bs %>%
  skim(q98)
── Data Summary ────────────────────────
                           Values    
Name                       Piped data
Number of rows             500       
Number of columns          1         
_______________________              
Column type frequency:               
  numeric                  1         
________________________             
Group variables                      

── Variable type: numeric ──────────────────────────────────────────────────────────────────────────────────────────────────────
  skim_variable n_missing complete_rate  mean    sd    p0   p25   p50   p75  p100 hist 
1 q98                   0             1  148.  40.1  55.0  121.   140  162.   310 ▁▇▅▁▁
n_large <- 10000
sf_10000_bs <- SF %>% 
  slice_sample(n = n_large, replace = FALSE)
sf_200_bs <- 1:num_trials %>%
  map_dfr(~sf_10000_bs %>%
        slice_sample(n = n_large, replace = TRUE) %>%
        summarize(q98 = quantile(arr_delay, p = 0.98))
  )
sf_200_bs %>%
  skim(q98)
── Data Summary ────────────────────────
                           Values    
Name                       Piped data
Number of rows             500       
Number of columns          1         
_______________________              
Column type frequency:               
  numeric                  1         
________________________             
Group variables                      

── Variable type: numeric ──────────────────────────────────────────────────────────────────────────────────────────────────────
  skim_variable n_missing complete_rate  mean    sd    p0   p25   p50   p75  p100 hist 
1 q98                   0             1  152.  4.91   137   151   152  154.  167. ▁▁▇▂▁

outliers

SF %>%
  filter(arr_delay >= 420) %>% 
  select(month, day, dep_delay, arr_delay, carrier)
SF %>% 
  filter(arr_delay < 420) %>%
  ggplot(aes(arr_delay)) + 
  geom_histogram(binwidth = 15) + 
  labs(x = "Arrival delay (in minutes)")

SF %>%
  group_by(hour) %>%
  count() %>%
  pivot_wider(names_from = hour, values_from = n) %>%
  data.frame()
SF %>%
  ggplot(aes(x = hour, y = arr_delay)) +
  geom_boxplot(alpha = 0.1, aes(group = hour)) +
  geom_smooth(method = "lm") + 
  xlab("Scheduled hour of departure") + 
  ylab("Arrival delay (minutes)") + 
  coord_cartesian(ylim = c(-30, 120)) 

mod1 <- lm(arr_delay ~ hour, data = SF)
broom::tidy(mod1)
LS0tCnRpdGxlOiAiQ2hhcHRlciA3IFN0YXRpc3RpY2FsIEZvdW5kYXRpb25zIgpvdXRwdXQ6CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KCiMjIFNhbXBsZXMgYW5kIFBvcHVsYXRpb25zCgpUaGUgcG9wdWxhdGlvbiBjb25zaWRlcmVkIGluIHRoZSBib29rIGlzIGNvbnRhaW5lZCBpbiB0aGUgKm55Y2ZsaWdodHMxMyogZGF0YXNldC4gIEluIHRoZSAqbnljZmxpZ2h0czEzKiBkYXRhc2V0IGNvbnRhaW5zIGFsbCBvZiB0aGUgZGVwYXJ0aW5nIGZsaWdodHMgZnJvbSBhaXJwb3J0cyBpbiB0aGUgTllDIEFyZWEuCgpgYGB7cn0KbGlicmFyeShwYWNtYW4pCgpwX2xvYWQobWRzciwgbnljZmxpZ2h0czEzLCB0aWR5dmVyc2UsIHNraW1yKQpgYGAKClJlY2FsbCB0aGUgKmZsaWdodHMqIGRhdGFmcmFtZS4KCmBgYHtyfQpmbGlnaHRzCmBgYAoKVGFrZSBhIHNhbXBsZSBvZiBmbGlnaHRzIGZyb20gTllDIHRvIFNGLiAgR2V0IGFsbCBvZiB0aGUgZmxpZ2h0cyB0byBTRiBhbmQgdGFrZSBhIHNhbXBsZSBvZiAyNSBvZiB0aGVtLgoKTm90ZSB0aGF0IEkgZGlkIG5vdCBzZXQgYSBzZWVkIGZvciB0aGUgc2FtcGxlLCBzbyB5b3VyIGFuc3dlcnMgd2lsbCBkaWZmZXIgZnJvbSB3aGF0IGlzIGluIHRoZSBib29rLgoKYGBge3J9ClNGIDwtIGZsaWdodHMgJT4lIAogIGZpbHRlcihkZXN0ID09ICJTRk8iLCAhaXMubmEoYXJyX2RlbGF5KSkKU0YKICAKc2ZfMjUgPC0gU0YgJT4lCiAgc2xpY2Vfc2FtcGxlKG4gPSAyNSkKYGBgCgpHZXQgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIHNhbXBsZSB0YWtlbi4KCmBgYHtyfQpzZl8yNSAlPiUKICBza2ltKGFycl9kZWxheSkKYGBgCgpTaW5jZSB0aGUgU0YgZGF0YXNldCBjb250YWlucyBhbGwgZmxpZ2h0cyBmcm9tIE5ZQyB0byBTRiBpbiAyMDEzLCB0aGUgc3RhdGlzdGljcyBjb21wdXRlZCBmcm9tIHRoZSBTRiBkYXRhc2V0IGFyZSB0aGUgY2FsY3VsYXRlZCBwb3B1bGF0aW9uIHBhcmFtdGVycy4KCmBgYHtyfQpTRiAlPiUKICBza2ltKGFycl9kZWxheSkKYGBgCgpHZXQgdGhlIDk4dGggcGVyY2VudGlsZSBvZiB0aGUgc2FtcGxlLgoKYGBge3J9CnNmXzI1ICU+JQogIHN1bW1hcml6ZShxOTggPSBxdWFudGlsZShhcnJfZGVsYXksIHAgPSAwLjk4KSkKYGBgCgpHZXQgdGhlIGVzdGltYXRlZCBwcm9wb3J0aW9uIG9mIGZpbGlnaHRzIHRvIFNGIHdpdGggYSBkZWxheSBsZXNzIHRoYW4gOTAgbWludXRlcy4KCmBgYHtyfQpTRiAlPiUKICBncm91cF9ieShhcnJfZGVsYXkgPCA5MCkgJT4lCiAgY291bnQoKSAlPiUKICBtdXRhdGUocGN0ID0gbiAvIG5yb3coU0YpKQpgYGAKCkNvbXBhcmUgd2l0aCB0aGUgOTh0aCBwZXJjZW50aWxlLiAgOTAgbWludXRlcyBpcyB0aGUgOTV0aCBwZXJjZW50aWxlLgoKYGBge3J9ClNGICU+JQogIHN1bW1hcml6ZShxOTggPSBxdWFudGlsZShhcnJfZGVsYXksIHAgPSAwLjk4KSkKYGBgCgojIyBTYW1wbGUgU3RhdGlzdGljcwoKVGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbi4KClVzdWFsbHkgc2FtcGxpbmcgaXMgZG9uZSB3aXRob3V0IHJlcGxhY2VtZW50LgoKYGBge3J9Cm4gPC0gMjUKU0YgJT4lCiAgc2xpY2Vfc2FtcGxlKG4gPSBuKSAlPiUKICBzdW1tYXJpemUobWVhbl9hcnJfZGVsYXkgPSBtZWFuKGFycl9kZWxheSkpCmBgYAoKTm90ZSB0aGF0IGRpZmZlcmVudCByYW5kb20gc2FtcGxlIHByb2R1Y2UgZGlmZmVyZW50IHZhbHVlcyBmb3IgdGhlIHNhbXBsZSBzdGF0aXN0aWMuCgpgYGB7cn0KU0YgJT4lCiAgc2xpY2Vfc2FtcGxlKG4gPSBuKSAlPiUKICBzdW1tYXJpemUobWVhbl9hcnJfZGVsYXkgPSBtZWFuKGFycl9kZWxheSkpCmBgYAoKVXNpbmcgc2ltdWxhdGlvbiB3ZSBjYW4gYXBwcm94aW1hdGUgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc2FtcGxlIHN0YXRpc3RpY3MuICBIZXJlIHdlIGFyZSBjb21wdXRpbmcgdGhlIG1lYW4sIGJ1dCB3ZSBjb3VsZCBkbyB0aGlzIGZvciBhbnkgc3RhdGlzdGljIHdlIGFyZSBpbnRlcmVzdGVkIGluLCB0aGUgbWVkaWFuLCBzYW1wbGUgdmFyaWFuY2UsIHNhbXBsZSBzdGFuZGFyZCBkZXZpYXRpb24sIGV0Yy4KCk5vdGUgdGhhdCB0aGUgKipkbygpKiogZnVuY3Rpb24gaXMgZnJvbSB0aGUgKm1vc2FpYyogcGFja2FnZS4gIFdlIGNvdWxkIGp1c3QgdXNlIGEgZm9yIGxvb3AuCgpgYGB7cn0KbnVtX3RyaWFscyA8LSA1MDAKc2ZfMjVfbWVhbnMgPC0gMTpudW1fdHJpYWxzICU+JQogIG1hcF9kZnIoCiAgICB+IFNGICU+JQogICAgICBzbGljZV9zYW1wbGUobiA9IG4pICU+JQogICAgICBzdW1tYXJpemUobWVhbl9hcnJfZGVsYXkgPSBtZWFuKGFycl9kZWxheSkpCiAgKSAlPiUKICBtdXRhdGUobiA9IG4pCgpoZWFkKHNmXzI1X21lYW5zKQpgYGAKClN1bW1hcml6ZSB0aGUgc2FtcGxlIG1lYW5zLiAgCgpgYGB7cn0Kc2ZfMjVfbWVhbnMgJT4lCiAgc2tpbShtZWFuX2Fycl9kZWxheSkKYGBgCgpDb25maWRlbmNlIGludGVydmFscwoKYGBge3J9CnNmXzI1X21lYW5zICU+JQogIHN1bW1hcml6ZSgKICAgIHhfYmFyID0gbWVhbihtZWFuX2Fycl9kZWxheSksCiAgICBzZSA9IHNkKG1lYW5fYXJyX2RlbGF5KQogICkgJT4lCiAgbXV0YXRlKAogICAgY2lfbG93ZXIgPSB4X2JhciAtIDIgKiBzZSwgIyBhcHByb3hpbWF0ZWx5IDk1JSBvZiBvYnNlcnZhdGlvbnMgCiAgICBjaV91cHBlciA9IHhfYmFyICsgMiAqIHNlICAjIGFyZSB3aXRoaW4gdHdvIHN0YW5kYXJkIGVycm9ycwogICkgCmBgYAoKVXNpbmcgYSBsYXJnZXIgc2FtcGxlIHNpemUgZ2l2ZSBhIHNtYWxsZXIgU3RhbmRhcmQgRXJyb3IuCgpgYGB7cn0KbiA8LSAxMDAKc2ZfMTAwX21lYW5zIDwtIDE6NTAwICU+JQogIG1hcF9kZnIoCiAgICB+IFNGICU+JQogICAgICBzbGljZV9zYW1wbGUobiA9IG4pICU+JQogICAgICBzdW1tYXJpemUobWVhbl9hcnJfZGVsYXkgPSBtZWFuKGFycl9kZWxheSkpCiAgKSAlPiUKICBtdXRhdGUobiA9IG4pCmBgYAoKUGxvdHMgdG8gY29tcGFyZSB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9ucyB3aXRoIGRpZmZlcmVudCBzYW1wbGUgc2l6ZXMuCgpgYGB7cn0Kc2ZfMjVfbWVhbnMgJT4lCiAgYmluZF9yb3dzKHNmXzEwMF9tZWFucykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbWVhbl9hcnJfZGVsYXkpKSArIAogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCkgKyAKICBmYWNldF9ncmlkKCB+IG4pICsgCiAgeGxhYigiU2FtcGxlIG1lYW4iKQpgYGAKCiMjIEJvb3N0cmFwCgpVc3VhbGx5IGZvciByYW5kb20gc2FtcGxpbmcgd2Ugc2FtcGxlIHdpdGhvdXQgcmVwbGFjZW1lbnQuCgpgYGB7cn0KdGhyZWVfZmxpZ2h0cyA8LSBTRiAlPiUKICBzbGljZV9zYW1wbGUobiA9IDMsIHJlcGxhY2UgPSBGQUxTRSkgJT4lCiAgc2VsZWN0KHllYXIsIG1vbnRoLCBkYXksIGRlcF90aW1lKQp0aHJlZV9mbGlnaHRzCmBgYAoKV2l0aCB0aGUgQm9vdHN0cmFwIHdlIHVzZSBzYW1wbGluZyAqKndpdGggcmVwbGFjZW1lbnQqKgoKYGBge3J9CnRocmVlX2ZsaWdodHMgJT4lIHNsaWNlX3NhbXBsZShuID0gMywgcmVwbGFjZSA9IFRSVUUpCmBgYAoKYGBge3J9Cm4gPC0gMjAwCm9yaWdfc2FtcGxlIDwtIFNGICU+JSAKICBzbGljZV9zYW1wbGUobiA9IG4sIHJlcGxhY2UgPSBGQUxTRSkKb3JpZ19zYW1wbGUKYGBgCgpUaGUgcmVhc29uIGZvciBzYW1wbGluZyB3aXRoIHJlcGxhY2VtZW50IGlzIHRoYXQgd2Ugb25seSBoYXZlIHRoZSBPcmlnaW5hbCBTYW1wbGUgb2Ygc2l6ZSAkbiQuICBXZSBkbyBub3QgaGF2ZSB0aGUgcG9wdWxhdGlvbi4gIFNvIGlmIHdlIHNhbXBsZWQgd2l0aCBvdXQgcmVwbGFjZW1lbnQgd2Ugd291bGQgb25seSBoYXZlIG9uZSBzYW1wbGUgdG8gbG9vayBhdC4gIFNhbXBsaW5nIHRoZSBPcmlnaW5hbCBTYW1wbGUgd2l0aCByZXBsYWNlIGFsbG93IHVzIHRvIGdlbmVyYWwgbG90cyBvZiBzYW1wbGVzIGFuZCB0byBpbnZlc3RpYWdlIHRoZSB2YXJpYWJpbGl0eSBvZiB0aGVzZSBzYW1wbGVzLgoKYGBge3J9Cm9yaWdfc2FtcGxlICU+JQogIHNsaWNlX3NhbXBsZShuID0gbiwgcmVwbGFjZSA9IFRSVUUpICU+JQogIHN1bW1hcml6ZShtZWFuX2Fycl9kZWxheSA9IG1lYW4oYXJyX2RlbGF5KSkKYGBgCgoKYGBge3J9CnNmXzIwMF9icyA8LSAxOm51bV90cmlhbHMgJT4lCiAgbWFwX2RmcigKICAgIH5vcmlnX3NhbXBsZSAlPiUKICAgICAgc2xpY2Vfc2FtcGxlKG4gPSBuLCByZXBsYWNlID0gVFJVRSkgJT4lCiAgICAgIHN1bW1hcml6ZShtZWFuX2Fycl9kZWxheSA9IG1lYW4oYXJyX2RlbGF5KSkKICApICU+JQogIG11dGF0ZShuID0gbikKCnNmXzIwMF9icyAlPiUKICBza2ltKG1lYW5fYXJyX2RlbGF5KQoKCnNmXzIwMF9icyAlPiUgZ2dwbG90KGFlcyh4ID0gbWVhbl9hcnJfZGVsYXkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKQoKYGBgCgpgYGB7cn0Kc2ZfMjAwX3BvcCA8LSAxOm51bV90cmlhbHMgJT4lCiAgbWFwX2RmcigKICAgIH5TRiAlPiUKICAgICAgc2xpY2Vfc2FtcGxlKG4gPSBuLCByZXBsYWNlID0gVFJVRSkgJT4lCiAgICAgIHN1bW1hcml6ZShtZWFuX2Fycl9kZWxheSA9IG1lYW4oYXJyX2RlbGF5KSkKICApICU+JQogIG11dGF0ZShuID0gbikKCnNmXzIwMF9wb3AgJT4lCiAgc2tpbShtZWFuX2Fycl9kZWxheSkKCnNmXzIwMF9wb3AgJT4lIGdncGxvdChhZXMoeCA9IG1lYW5fYXJyX2RlbGF5KSkgKwogIGdlb21faGlzdG9ncmFtKCkKYGBgCgoqKlF1ZXN0aW9uOioqIERvIHRoZSBoaXN0b2dyYW1zIGxvb2sgc29tZXdoYXQgc2ltaWxhcj8KCmBgYHtyfQpvcmlnX3NhbXBsZSAlPiUKICBzdW1tYXJpemUocTk4ID0gcXVhbnRpbGUoYXJyX2RlbGF5LCBwID0gMC45OCkpCmBgYAoKYGBge3J9Cm4gPC0gbnJvdyhvcmlnX3NhbXBsZSkKc2ZfMjAwX2JzIDwtIDE6bnVtX3RyaWFscyAlPiUKICBtYXBfZGZyKAogICAgfm9yaWdfc2FtcGxlICU+JQogICAgICBzbGljZV9zYW1wbGUobiA9IG4sIHJlcGxhY2UgPSBUUlVFKSAlPiUKICAgICAgc3VtbWFyaXplKHE5OCA9IHF1YW50aWxlKGFycl9kZWxheSwgcCA9IDAuOTgpKQogICkKCnNmXzIwMF9icyAlPiUKICBza2ltKHE5OCkKYGBgCgoKYGBge3J9Cm5fbGFyZ2UgPC0gMTAwMDAKc2ZfMTAwMDBfYnMgPC0gU0YgJT4lIAogIHNsaWNlX3NhbXBsZShuID0gbl9sYXJnZSwgcmVwbGFjZSA9IEZBTFNFKQoKc2ZfMjAwX2JzIDwtIDE6bnVtX3RyaWFscyAlPiUKICBtYXBfZGZyKH5zZl8xMDAwMF9icyAlPiUKICAgICAgICBzbGljZV9zYW1wbGUobiA9IG5fbGFyZ2UsIHJlcGxhY2UgPSBUUlVFKSAlPiUKICAgICAgICBzdW1tYXJpemUocTk4ID0gcXVhbnRpbGUoYXJyX2RlbGF5LCBwID0gMC45OCkpCiAgKQoKc2ZfMjAwX2JzICU+JQogIHNraW0ocTk4KQpgYGAKCiMjIG91dGxpZXJzCgpgYGB7cn0KU0YgJT4lCiAgZmlsdGVyKGFycl9kZWxheSA+PSA0MjApICU+JSAKICBzZWxlY3QobW9udGgsIGRheSwgZGVwX2RlbGF5LCBhcnJfZGVsYXksIGNhcnJpZXIpCmBgYAoKYGBge3J9ClNGICU+JSAKICBmaWx0ZXIoYXJyX2RlbGF5IDwgNDIwKSAlPiUKICBnZ3Bsb3QoYWVzKGFycl9kZWxheSkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxNSkgKyAKICBsYWJzKHggPSAiQXJyaXZhbCBkZWxheSAoaW4gbWludXRlcykiKQpgYGAKCgpgYGB7cn0KU0YgJT4lCiAgZ3JvdXBfYnkoaG91cikgJT4lCiAgY291bnQoKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gaG91ciwgdmFsdWVzX2Zyb20gPSBuKSAlPiUKICBkYXRhLmZyYW1lKCkKYGBgCgpgYGB7cn0KU0YgJT4lCiAgZ2dwbG90KGFlcyh4ID0gaG91ciwgeSA9IGFycl9kZWxheSkpICsKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjEsIGFlcyhncm91cCA9IGhvdXIpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICB4bGFiKCJTY2hlZHVsZWQgaG91ciBvZiBkZXBhcnR1cmUiKSArIAogIHlsYWIoIkFycml2YWwgZGVsYXkgKG1pbnV0ZXMpIikgKyAKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMwLCAxMjApKSAKYGBgCgpgYGB7cn0KbW9kMSA8LSBsbShhcnJfZGVsYXkgfiBob3VyLCBkYXRhID0gU0YpCmJyb29tOjp0aWR5KG1vZDEpCmBgYAoKCgo=