suppressPackageStartupMessages(library("tidyverse"))
package 㤼㸱tidyverse㤼㸲 was built under R version 3.6.3
suppressPackageStartupMessages(library("stringr"))
#The package microbenchmark is used for timing code.
suppressPackageStartupMessages(library("microbenchmark"))
package 㤼㸱microbenchmark㤼㸲 was built under R version 3.6.3

1. Write code that uses one of the map functions to:

1. Compute the mean of every column in mtcars.
2. Determine the type of each column in nycflights13::flights.
3. Compute the number of unique values in each column of iris.
4. Generate 10 random normals for each of \(\mu = −10,0,10,\) and \(100\).

1. To calculate the mean of every column in mtcars, apply the function mean() to each column, and use map_dbl, since the results are numeric.

map_dbl(mtcars, mean)
       mpg        cyl       disp         hp       drat         wt       qsec         vs 
 20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750   0.437500 
        am       gear       carb 
  0.406250   3.687500   2.812500 

2. To calculate the type of every column in nycflights13::flights apply the function typeof(), discussed in the section on Vector basics, and use map_chr(), since the results are character.

map_chr(nycflights13::flights, typeof)
          year          month            day       dep_time sched_dep_time      dep_delay 
     "integer"      "integer"      "integer"      "integer"      "integer"       "double" 
      arr_time sched_arr_time      arr_delay        carrier         flight        tailnum 
     "integer"      "integer"       "double"    "character"      "integer"    "character" 
        origin           dest       air_time       distance           hour         minute 
   "character"    "character"       "double"       "double"       "double"       "double" 
     time_hour 
      "double" 

3. There is no function that directly calculates the number of unique values in a vector. For a single column, the number of unique values of a vector can be calculated like so,

length(unique(iris$Species))
[1] 3

To apply this to all columns, we can provide the map an anonymous function. We can write anonymous function using the standard R syntax.

map_int(iris, function(x) length(unique(x)))
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
          35           23           43           22            3 

We could also use the compact, one-sided formula shortcut that purrr provides.

map_int(iris, ~ length(unique(.)))
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
          35           23           43           22            3 

In these examples, the map_int() function is used since length() returns an integer. However, the map_dbl() function will also work.

map_dbl(iris, ~ length(unique(.)))

4. To generate 10 random normals for each of \(\mu = −10,0,10,\) and \(100\): The result is a list of numeric vectors.

map(c(-10, 0, 10, 100), ~ rnorm(n = 10, mean = .))
[[1]]
 [1] -10.562685  -9.450440 -11.205591  -7.427206  -9.121196  -7.236307  -9.484426 -11.450771
 [9]  -9.985221 -10.683619

[[2]]
 [1]  0.63546587  0.71664803 -0.98568053 -1.51530864 -0.04996717 -1.49228515 -0.13181626
 [8]  0.05997331  0.64866414 -0.42070499

[[3]]
 [1]  8.313399  9.594709  9.968042 10.572528 10.234050  8.862336 10.997314 11.195132 10.603083
[10] 10.287259

[[4]]
 [1]  98.80427 101.22868 100.94155 100.79101 101.12101  99.55110  99.75927  99.56236 102.02652
[10] 101.00852

Since a single call of rnorm() returns a numeric vector with a length greater than one we cannot use map_dbl, which requires the function to return a numeric vector that is only length one. The map functions pass any additional arguments to the function being called.

2. How can you create a single vector that for each column in a data frame indicates whether or not it’s a factor?

The function is.factor() indicates whether a vector is a factor.

is.factor(diamonds$color)
[1] TRUE

To check all columns in a factor for whether it is a factor is a job for a map_*() function. Since the result of is.factor() is logical, we will use map_lgl() to apply is.factor() to the columns of the data frame.

map_lgl(diamonds, is.factor)
  carat     cut   color clarity   depth   table   price       x       y       z 
  FALSE    TRUE    TRUE    TRUE   FALSE   FALSE   FALSE   FALSE   FALSE   FALSE 

3. What happens when you use the map functions on vectors that aren’t lists? What does map(1:5, runif) do? Why?

Map functions work with any vectors, not just lists. As with lists, the map functions will apply the function to each element of the vector. In the following examples, the inputs to map() are atomic vectors (logical, character, integer, double).

map(c(TRUE, FALSE, TRUE), ~ !.)
[[1]]
[1] FALSE

[[2]]
[1] TRUE

[[3]]
[1] FALSE
map(c("Hello", "World"), str_to_upper)
[[1]]
[1] "HELLO"

[[2]]
[1] "WORLD"
map(1:5, ~ rnorm(.))
[[1]]
[1] 0.06280466

[[2]]
[1]  0.4185305 -0.3795624

[[3]]
[1] -0.2601337 -0.7149337  1.2696833

[[4]]
[1] 0.11534827 0.05702938 0.88862189 1.32397427

[[5]]
[1]  0.5122246  1.0382322  1.6076809 -1.8047729  0.6420032
map(c(-0.5, 0, 1), ~ rnorm(1, mean = .))
[[1]]
[1] -2.224334

[[2]]
[1] 0.2706889

[[3]]
[1] 0.9579823

It is important to be aware that while the input of map() can be any vector, the output is always a list.

map(1:5, runif)
[[1]]
[1] 0.1494658

[[2]]
[1] 0.6528250 0.4799463

[[3]]
[1] 0.9744443 0.2791404 0.8208076

[[4]]
[1] 0.6709032 0.5937742 0.9961677 0.2599329

[[5]]
[1] 0.56860716 0.61701854 0.07568036 0.22553429 0.54821350

This expression is equivalent to running the following.

list(
  runif(1),
  runif(2),
  runif(3),
  runif(4),
  runif(5)
)
[[1]]
[1] 0.8088577

[[2]]
[1] 0.6489569 0.3369204

[[3]]
[1] 0.09497879 0.66540476 0.89104245

[[4]]
[1] 0.01484305 0.79000957 0.27765970 0.19737707

[[5]]
[1] 0.23060943 0.19025157 0.56040339 0.06336879 0.16675676

The map() function loops through the numbers 1 to 5. For each value, it calls the runif() with that number as the first argument, which is the number of sample to draw. The result is a length five list with numeric vectors of sizes one through five, each with random samples from a uniform distribution. Note that although input to map() was an integer vector, the return value was a list.

4. What does map(-2:2, rnorm, n = 5) do? Why? What does map_dbl(-2:2, rnorm, n = 5) do? Why?

Consider the first expression.

map(-2:2, rnorm, n = 5)
[[1]]
[1] -1.875677 -2.475980 -3.953484 -2.906089 -2.607832

[[2]]
[1] -1.7310002 -0.5087884 -1.4219197 -2.3649502 -0.4751831

[[3]]
[1] -1.0501727 -1.0422769  0.8935098  0.3735523  0.7320833

[[4]]
[1]  1.4035647 -0.1525906  2.6630770 -0.3736245  1.0380134

[[5]]
[1] 2.1716007 4.2711560 0.9351085 4.0590603 0.6201520

This expression takes samples of size five from five normal distributions, with means of (-2, -1, 0, 1, and 2), but the same standard deviation (1). It returns a list with each element a numeric vectors of length 5.

However, if instead, we use map_dbl(), the expression raises an error.

#  map_dbl(-2:2, rnorm, n = 5)
#> Result 1 must be a single double, not a double vector of length 5

This is because the map_dbl() function requires the function it applies to each element to return a numeric vector of length one. If the function returns either a non-numeric vector or a numeric vector with a length greater than one, map_dbl() will raise an error. The reason for this strictness is that map_dbl() guarantees that it will return a numeric vector of the same length as its input vector.

This concept applies to the other map_*() functions. The function map_chr() requires that the function always return a character vector of length one; map_int() requires that the function always return an integer vector of length one; map_lgl() requires that the function always return an logical vector of length one. Use the map() function if the function will return values of varying types or lengths.

To return a double vector, we could use map() followed by flatten_dbl(),

flatten_dbl(map(-2:2, rnorm, n = 5))
 [1] -3.78746056 -1.57532860 -1.25197942 -3.40964151 -2.16499929 -1.10871102 -0.79198392
 [8] -0.11331084 -0.70837810 -1.36750714 -0.74433696 -0.05375261 -1.39895763  0.75811861
[15]  0.17177696 -0.91846162 -0.92356516  1.62452989  0.59117241  0.81927221  2.34703113
[22]  1.22385230  4.09175355  1.51842380  2.37895695

5. Rewrite map(x, function(df) lm(mpg ~ wt, data = df)) to eliminate the anonymous function.

This code in this question does not run, so I will use the following code.

x <- split(mtcars, mtcars$cyl)
map(x, function(df) lm(mpg ~ wt, data = df))
$`4`

Call:
lm(formula = mpg ~ wt, data = df)

Coefficients:
(Intercept)           wt  
     39.571       -5.647  


$`6`

Call:
lm(formula = mpg ~ wt, data = df)

Coefficients:
(Intercept)           wt  
      28.41        -2.78  


$`8`

Call:
lm(formula = mpg ~ wt, data = df)

Coefficients:
(Intercept)           wt  
     23.868       -2.192  

We can eliminate the use of an anonymous function using the ~ shortcut.

map(x, ~ lm(mpg ~ wt, data = .))
$`4`

Call:
lm(formula = mpg ~ wt, data = .)

Coefficients:
(Intercept)           wt  
     39.571       -5.647  


$`6`

Call:
lm(formula = mpg ~ wt, data = .)

Coefficients:
(Intercept)           wt  
      28.41        -2.78  


$`8`

Call:
lm(formula = mpg ~ wt, data = .)

Coefficients:
(Intercept)           wt  
     23.868       -2.192  

Though not the intent of this question, the other way to eliminate anonymous function is to create a named one.

run_reg <- function(df) {
  lm(mpg ~ wt, data = df)
}
map(x, run_reg)
$`4`

Call:
lm(formula = mpg ~ wt, data = df)

Coefficients:
(Intercept)           wt  
     39.571       -5.647  


$`6`

Call:
lm(formula = mpg ~ wt, data = df)

Coefficients:
(Intercept)           wt  
      28.41        -2.78  


$`8`

Call:
lm(formula = mpg ~ wt, data = df)

Coefficients:
(Intercept)           wt  
     23.868       -2.192  
LS0tDQp0aXRsZTogIlRoZSBtYXAgZnVuY3Rpb25zIg0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCi0tLQ0KDQpgYGB7cn0NCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KCJ0aWR5dmVyc2UiKSkNCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KCJzdHJpbmdyIikpDQojVGhlIHBhY2thZ2UgbWljcm9iZW5jaG1hcmsgaXMgdXNlZCBmb3IgdGltaW5nIGNvZGUuDQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeSgibWljcm9iZW5jaG1hcmsiKSkNCmBgYA0KDQojIyMgMS4gV3JpdGUgY29kZSB0aGF0IHVzZXMgb25lIG9mIHRoZSBtYXAgZnVuY3Rpb25zIHRvOg0KDQoqKjEuIENvbXB1dGUgdGhlIG1lYW4gb2YgZXZlcnkgY29sdW1uIGluIGBtdGNhcnNgLioqICANCioqMi4gRGV0ZXJtaW5lIHRoZSB0eXBlIG9mIGVhY2ggY29sdW1uIGluIGBueWNmbGlnaHRzMTM6OmZsaWdodHNgLioqICANCioqMy4gQ29tcHV0ZSB0aGUgbnVtYmVyIG9mIHVuaXF1ZSB2YWx1ZXMgaW4gZWFjaCBjb2x1bW4gb2YgYGlyaXNgLioqICANCioqNC4gR2VuZXJhdGUgMTAgcmFuZG9tIG5vcm1hbHMgZm9yIGVhY2ggb2YgJFxtdSA9IOKIkjEwLDAsMTAsJCBhbmQgJDEwMCQuKioNCg0KKioxLioqIFRvIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiBldmVyeSBjb2x1bW4gaW4gYG10Y2Fyc2AsIGFwcGx5IHRoZSBmdW5jdGlvbiBgbWVhbigpYCB0byBlYWNoIGNvbHVtbiwgYW5kIHVzZSBgbWFwX2RibGAsIHNpbmNlIHRoZSByZXN1bHRzIGFyZSBudW1lcmljLg0KDQpgYGB7cn0NCm1hcF9kYmwobXRjYXJzLCBtZWFuKQ0KYGBgDQoNCioqMi4qKiBUbyBjYWxjdWxhdGUgdGhlIHR5cGUgb2YgZXZlcnkgY29sdW1uIGluIGBueWNmbGlnaHRzMTM6OmZsaWdodHNgIGFwcGx5IHRoZSBmdW5jdGlvbiBgdHlwZW9mKClgLCBkaXNjdXNzZWQgaW4gdGhlIHNlY3Rpb24gb24gVmVjdG9yIGJhc2ljcywgYW5kIHVzZSBgbWFwX2NocigpYCwgc2luY2UgdGhlIHJlc3VsdHMgYXJlIGNoYXJhY3Rlci4NCg0KYGBge3J9DQptYXBfY2hyKG55Y2ZsaWdodHMxMzo6ZmxpZ2h0cywgdHlwZW9mKQ0KYGBgDQoNCioqMy4qKiBUaGVyZSBpcyBubyBmdW5jdGlvbiB0aGF0IGRpcmVjdGx5IGNhbGN1bGF0ZXMgdGhlIG51bWJlciBvZiB1bmlxdWUgdmFsdWVzIGluIGEgdmVjdG9yLiBGb3IgYSBzaW5nbGUgY29sdW1uLCB0aGUgbnVtYmVyIG9mIHVuaXF1ZSB2YWx1ZXMgb2YgYSB2ZWN0b3IgY2FuIGJlIGNhbGN1bGF0ZWQgbGlrZSBzbywNCg0KYGBge3J9DQpsZW5ndGgodW5pcXVlKGlyaXMkU3BlY2llcykpDQpgYGANCg0KVG8gYXBwbHkgdGhpcyB0byBhbGwgY29sdW1ucywgd2UgY2FuIHByb3ZpZGUgdGhlIG1hcCBhbiBhbm9ueW1vdXMgZnVuY3Rpb24uIFdlIGNhbiB3cml0ZSBhbm9ueW1vdXMgZnVuY3Rpb24gdXNpbmcgdGhlIHN0YW5kYXJkIFIgc3ludGF4Lg0KDQpgYGB7cn0NCm1hcF9pbnQoaXJpcywgZnVuY3Rpb24oeCkgbGVuZ3RoKHVuaXF1ZSh4KSkpDQpgYGANCg0KV2UgY291bGQgYWxzbyB1c2UgdGhlIGNvbXBhY3QsIG9uZS1zaWRlZCBmb3JtdWxhIHNob3J0Y3V0IHRoYXQgcHVycnIgcHJvdmlkZXMuDQoNCmBgYHtyfQ0KbWFwX2ludChpcmlzLCB+IGxlbmd0aCh1bmlxdWUoLikpKQ0KYGBgDQoNCkluIHRoZXNlIGV4YW1wbGVzLCB0aGUgbWFwX2ludCgpIGZ1bmN0aW9uIGlzIHVzZWQgc2luY2UgbGVuZ3RoKCkgcmV0dXJucyBhbiBpbnRlZ2VyLiBIb3dldmVyLCB0aGUgbWFwX2RibCgpIGZ1bmN0aW9uIHdpbGwgYWxzbyB3b3JrLg0KDQptYXBfZGJsKGlyaXMsIH4gbGVuZ3RoKHVuaXF1ZSguKSkpDQoNCioqNC4qKiBUbyBnZW5lcmF0ZSAxMCByYW5kb20gbm9ybWFscyBmb3IgZWFjaCBvZiAkXG11ID0g4oiSMTAsMCwxMCwkIGFuZCAkMTAwJDogVGhlIHJlc3VsdCBpcyBhIGxpc3Qgb2YgbnVtZXJpYyB2ZWN0b3JzLg0KDQpgYGB7cn0NCm1hcChjKC0xMCwgMCwgMTAsIDEwMCksIH4gcm5vcm0obiA9IDEwLCBtZWFuID0gLikpDQpgYGANCg0KU2luY2UgYSBzaW5nbGUgY2FsbCBvZiBgcm5vcm0oKWAgcmV0dXJucyBhIG51bWVyaWMgdmVjdG9yIHdpdGggYSBsZW5ndGggZ3JlYXRlciB0aGFuIG9uZSB3ZSBjYW5ub3QgdXNlIGBtYXBfZGJsYCwgd2hpY2ggcmVxdWlyZXMgdGhlIGZ1bmN0aW9uIHRvIHJldHVybiBhIG51bWVyaWMgdmVjdG9yIHRoYXQgaXMgb25seSBsZW5ndGggb25lLiBUaGUgbWFwIGZ1bmN0aW9ucyBwYXNzIGFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byB0aGUgZnVuY3Rpb24gYmVpbmcgY2FsbGVkLg0KDQojIyMgMi4gSG93IGNhbiB5b3UgY3JlYXRlIGEgc2luZ2xlIHZlY3RvciB0aGF0IGZvciBlYWNoIGNvbHVtbiBpbiBhIGRhdGEgZnJhbWUgaW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IGl04oCZcyBhIGZhY3Rvcj8NCg0KVGhlIGZ1bmN0aW9uIGBpcy5mYWN0b3IoKWAgaW5kaWNhdGVzIHdoZXRoZXIgYSB2ZWN0b3IgaXMgYSBmYWN0b3IuDQoNCmBgYHtyfQ0KaXMuZmFjdG9yKGRpYW1vbmRzJGNvbG9yKQ0KYGBgDQoNClRvIGNoZWNrIGFsbCBjb2x1bW5zIGluIGEgZmFjdG9yIGZvciB3aGV0aGVyIGl0IGlzIGEgZmFjdG9yIGlzIGEgam9iIGZvciBhIG1hcF8qKCkgZnVuY3Rpb24uIFNpbmNlIHRoZSByZXN1bHQgb2YgYGlzLmZhY3RvcigpYCBpcyBsb2dpY2FsLCB3ZSB3aWxsIHVzZSBgbWFwX2xnbCgpYCB0byBhcHBseSBgaXMuZmFjdG9yKClgIHRvIHRoZSBjb2x1bW5zIG9mIHRoZSBkYXRhIGZyYW1lLg0KDQpgYGB7cn0NCm1hcF9sZ2woZGlhbW9uZHMsIGlzLmZhY3RvcikNCmBgYA0KDQojIyMgMy4gV2hhdCBoYXBwZW5zIHdoZW4geW91IHVzZSB0aGUgbWFwIGZ1bmN0aW9ucyBvbiB2ZWN0b3JzIHRoYXQgYXJlbuKAmXQgbGlzdHM/IFdoYXQgZG9lcyBgbWFwKDE6NSwgcnVuaWYpYCBkbz8gV2h5Pw0KDQpNYXAgZnVuY3Rpb25zIHdvcmsgd2l0aCBhbnkgdmVjdG9ycywgbm90IGp1c3QgbGlzdHMuIEFzIHdpdGggbGlzdHMsIHRoZSBtYXAgZnVuY3Rpb25zIHdpbGwgYXBwbHkgdGhlIGZ1bmN0aW9uIHRvIGVhY2ggZWxlbWVudCBvZiB0aGUgdmVjdG9yLiBJbiB0aGUgZm9sbG93aW5nIGV4YW1wbGVzLCB0aGUgaW5wdXRzIHRvIGBtYXAoKWAgYXJlIGF0b21pYyB2ZWN0b3JzIChsb2dpY2FsLCBjaGFyYWN0ZXIsIGludGVnZXIsIGRvdWJsZSkuDQoNCmBgYHtyfQ0KbWFwKGMoVFJVRSwgRkFMU0UsIFRSVUUpLCB+ICEuKQ0KbWFwKGMoIkhlbGxvIiwgIldvcmxkIiksIHN0cl90b191cHBlcikNCm1hcCgxOjUsIH4gcm5vcm0oLikpDQptYXAoYygtMC41LCAwLCAxKSwgfiBybm9ybSgxLCBtZWFuID0gLikpDQpgYGANCg0KSXQgaXMgaW1wb3J0YW50IHRvIGJlIGF3YXJlIHRoYXQgd2hpbGUgdGhlIGlucHV0IG9mIGBtYXAoKWAgY2FuIGJlIGFueSB2ZWN0b3IsIHRoZSBvdXRwdXQgaXMgYWx3YXlzIGEgbGlzdC4NCg0KYGBge3J9DQptYXAoMTo1LCBydW5pZikNCmBgYA0KDQpUaGlzIGV4cHJlc3Npb24gaXMgZXF1aXZhbGVudCB0byBydW5uaW5nIHRoZSBmb2xsb3dpbmcuDQoNCmBgYHtyfQ0KbGlzdCgNCiAgcnVuaWYoMSksDQogIHJ1bmlmKDIpLA0KICBydW5pZigzKSwNCiAgcnVuaWYoNCksDQogIHJ1bmlmKDUpDQopDQpgYGANCg0KVGhlIGBtYXAoKWAgZnVuY3Rpb24gbG9vcHMgdGhyb3VnaCB0aGUgbnVtYmVycyAxIHRvIDUuIEZvciBlYWNoIHZhbHVlLCBpdCBjYWxscyB0aGUgYHJ1bmlmKClgIHdpdGggdGhhdCBudW1iZXIgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LCB3aGljaCBpcyB0aGUgbnVtYmVyIG9mIHNhbXBsZSB0byBkcmF3LiBUaGUgcmVzdWx0IGlzIGEgbGVuZ3RoIGZpdmUgbGlzdCB3aXRoIG51bWVyaWMgdmVjdG9ycyBvZiBzaXplcyBvbmUgdGhyb3VnaCBmaXZlLCBlYWNoIHdpdGggcmFuZG9tIHNhbXBsZXMgZnJvbSBhIHVuaWZvcm0gZGlzdHJpYnV0aW9uLiBOb3RlIHRoYXQgYWx0aG91Z2ggaW5wdXQgdG8gYG1hcCgpYCB3YXMgYW4gaW50ZWdlciB2ZWN0b3IsIHRoZSByZXR1cm4gdmFsdWUgd2FzIGEgbGlzdC4NCg0KIyMjIDQuIFdoYXQgZG9lcyBgbWFwKC0yOjIsIHJub3JtLCBuID0gNSlgIGRvPyBXaHk/IFdoYXQgZG9lcyBgbWFwX2RibCgtMjoyLCBybm9ybSwgbiA9IDUpYCBkbz8gV2h5Pw0KDQpDb25zaWRlciB0aGUgZmlyc3QgZXhwcmVzc2lvbi4NCg0KYGBge3J9DQptYXAoLTI6Miwgcm5vcm0sIG4gPSA1KQ0KYGBgDQoNClRoaXMgZXhwcmVzc2lvbiB0YWtlcyBzYW1wbGVzIG9mIHNpemUgZml2ZSBmcm9tIGZpdmUgbm9ybWFsIGRpc3RyaWJ1dGlvbnMsIHdpdGggbWVhbnMgb2YgKC0yLCAtMSwgMCwgMSwgYW5kIDIpLCBidXQgdGhlIHNhbWUgc3RhbmRhcmQgZGV2aWF0aW9uICgxKS4gSXQgcmV0dXJucyBhIGxpc3Qgd2l0aCBlYWNoIGVsZW1lbnQgYSBudW1lcmljIHZlY3RvcnMgb2YgbGVuZ3RoIDUuDQoNCkhvd2V2ZXIsIGlmIGluc3RlYWQsIHdlIHVzZSBgbWFwX2RibCgpYCwgdGhlIGV4cHJlc3Npb24gcmFpc2VzIGFuIGVycm9yLg0KDQpgYGB7cn0NCiMgIG1hcF9kYmwoLTI6Miwgcm5vcm0sIG4gPSA1KQ0KIz4gUmVzdWx0IDEgbXVzdCBiZSBhIHNpbmdsZSBkb3VibGUsIG5vdCBhIGRvdWJsZSB2ZWN0b3Igb2YgbGVuZ3RoIDUNCmBgYA0KDQpUaGlzIGlzIGJlY2F1c2UgdGhlIGBtYXBfZGJsKClgIGZ1bmN0aW9uIHJlcXVpcmVzIHRoZSBmdW5jdGlvbiBpdCBhcHBsaWVzIHRvIGVhY2ggZWxlbWVudCB0byByZXR1cm4gYSBudW1lcmljIHZlY3RvciBvZiBsZW5ndGggb25lLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyBlaXRoZXIgYSBub24tbnVtZXJpYyB2ZWN0b3Igb3IgYSBudW1lcmljIHZlY3RvciB3aXRoIGEgbGVuZ3RoIGdyZWF0ZXIgdGhhbiBvbmUsIGBtYXBfZGJsKClgIHdpbGwgcmFpc2UgYW4gZXJyb3IuIFRoZSByZWFzb24gZm9yIHRoaXMgc3RyaWN0bmVzcyBpcyB0aGF0IGBtYXBfZGJsKClgIGd1YXJhbnRlZXMgdGhhdCBpdCB3aWxsIHJldHVybiBhIG51bWVyaWMgdmVjdG9yIG9mIHRoZSBzYW1lIGxlbmd0aCBhcyBpdHMgaW5wdXQgdmVjdG9yLg0KDQpUaGlzIGNvbmNlcHQgYXBwbGllcyB0byB0aGUgb3RoZXIgYG1hcF8qKClgIGZ1bmN0aW9ucy4gVGhlIGZ1bmN0aW9uIGBtYXBfY2hyKClgIHJlcXVpcmVzIHRoYXQgdGhlIGZ1bmN0aW9uIGFsd2F5cyByZXR1cm4gYSBjaGFyYWN0ZXIgdmVjdG9yIG9mIGxlbmd0aCBvbmU7IGBtYXBfaW50KClgIHJlcXVpcmVzIHRoYXQgdGhlIGZ1bmN0aW9uIGFsd2F5cyByZXR1cm4gYW4gaW50ZWdlciB2ZWN0b3Igb2YgbGVuZ3RoIG9uZTsgYG1hcF9sZ2woKWAgcmVxdWlyZXMgdGhhdCB0aGUgZnVuY3Rpb24gYWx3YXlzIHJldHVybiBhbiBsb2dpY2FsIHZlY3RvciBvZiBsZW5ndGggb25lLiBVc2UgdGhlIGBtYXAoKWAgZnVuY3Rpb24gaWYgdGhlIGZ1bmN0aW9uIHdpbGwgcmV0dXJuIHZhbHVlcyBvZiB2YXJ5aW5nIHR5cGVzIG9yIGxlbmd0aHMuDQoNClRvIHJldHVybiBhIGRvdWJsZSB2ZWN0b3IsIHdlIGNvdWxkIHVzZSBgbWFwKClgIGZvbGxvd2VkIGJ5IGBmbGF0dGVuX2RibCgpYCwNCg0KYGBge3J9DQpmbGF0dGVuX2RibChtYXAoLTI6Miwgcm5vcm0sIG4gPSA1KSkNCmBgYA0KDQojIyMgNS4gUmV3cml0ZSBgbWFwKHgsIGZ1bmN0aW9uKGRmKSBsbShtcGcgfiB3dCwgZGF0YSA9IGRmKSlgIHRvIGVsaW1pbmF0ZSB0aGUgYW5vbnltb3VzIGZ1bmN0aW9uLg0KDQpUaGlzIGNvZGUgaW4gdGhpcyBxdWVzdGlvbiBkb2VzIG5vdCBydW4sIHNvIEkgd2lsbCB1c2UgdGhlIGZvbGxvd2luZyBjb2RlLg0KDQpgYGB7cn0NCnggPC0gc3BsaXQobXRjYXJzLCBtdGNhcnMkY3lsKQ0KbWFwKHgsIGZ1bmN0aW9uKGRmKSBsbShtcGcgfiB3dCwgZGF0YSA9IGRmKSkNCmBgYA0KDQpXZSBjYW4gZWxpbWluYXRlIHRoZSB1c2Ugb2YgYW4gYW5vbnltb3VzIGZ1bmN0aW9uIHVzaW5nIHRoZSBgfmAgc2hvcnRjdXQuDQoNCmBgYHtyfQ0KbWFwKHgsIH4gbG0obXBnIH4gd3QsIGRhdGEgPSAuKSkNCmBgYA0KDQpUaG91Z2ggbm90IHRoZSBpbnRlbnQgb2YgdGhpcyBxdWVzdGlvbiwgdGhlIG90aGVyIHdheSB0byBlbGltaW5hdGUgYW5vbnltb3VzIGZ1bmN0aW9uIGlzIHRvIGNyZWF0ZSBhIG5hbWVkIG9uZS4NCg0KYGBge3J9DQpydW5fcmVnIDwtIGZ1bmN0aW9uKGRmKSB7DQogIGxtKG1wZyB+IHd0LCBkYXRhID0gZGYpDQp9DQptYXAoeCwgcnVuX3JlZykNCmBgYA0K