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 for-loops 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.

The answers for each part are below.

1. To compute the mean of every column in mtcars.

output <- vector("double", ncol(mtcars))
names(output) <- names(mtcars)
for (i in names(mtcars)) {
  output[i] <- mean(mtcars[[i]])
}
output
       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. Determine the type of each column in nycflights13::flights.

output <- vector("list", ncol(nycflights13::flights))
names(output) <- names(nycflights13::flights)
for (i in names(nycflights13::flights)) {
  output[[i]] <- class(nycflights13::flights[[i]])
}
output
$year
[1] "integer"

$month
[1] "integer"

$day
[1] "integer"

$dep_time
[1] "integer"

$sched_dep_time
[1] "integer"

$dep_delay
[1] "numeric"

$arr_time
[1] "integer"

$sched_arr_time
[1] "integer"

$arr_delay
[1] "numeric"

$carrier
[1] "character"

$flight
[1] "integer"

$tailnum
[1] "character"

$origin
[1] "character"

$dest
[1] "character"

$air_time
[1] "numeric"

$distance
[1] "numeric"

$hour
[1] "numeric"

$minute
[1] "numeric"

$time_hour
[1] "POSIXct" "POSIXt" 

I used a list, not a character vector, since the class of an object can have multiple values. For example, the class of the time_hour column is POSIXct, POSIXt.

3. To compute the number of unique values in each column of the iris dataset.

data("iris")
iris_uniq <- vector("double", ncol(iris))
names(iris_uniq) <- names(iris)
for (i in names(iris)) {
  iris_uniq[i] <- length(unique(iris[[i]]))
}
iris_uniq
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
          35           23           43           22            3 

4. To generate 10 random normals for each of\(\mu\) = -10, 0, 10, and 100.

# number to draw
n <- 10
# values of the mean
mu <- c(-10, 0, 10, 100)
normals <- vector("list", length(mu))
for (i in seq_along(normals)) {
  normals[[i]] <- rnorm(n, mean = mu[i])
}
normals
[[1]]
 [1] -11.301960 -10.787456  -8.504878  -8.560247 -10.878454 -11.802069  -9.856285 -10.033041
 [9] -10.487465 -10.444151

[[2]]
 [1]  1.1318080  0.1214606 -1.0948844  0.3319064  0.6064221 -1.0515026 -1.1055939 -0.8176861
 [9]  1.0656076 -0.2963882

[[3]]
 [1]  9.867316  9.513627 10.103155 10.013717 11.012158  9.913954  8.780376  9.147940  9.650299
[10] 10.137570

[[4]]
 [1] 100.56303 100.33206  99.73111 100.16658 100.59629 101.34860 100.45599 102.13487  99.94797
[10] 100.96026

However, we don’t need a for loop for this since rnorm() recycle the mean argument.

matrix(rnorm(n * length(mu), mean = mu), ncol = n)
            [,1]       [,2]        [,3]       [,4]       [,5]       [,6]       [,7]
[1,] -10.7890021 -10.517369 -10.3388022 -8.4162341 -10.917389  -8.669234 -9.1940142
[2,]  -0.6077072   1.528000   0.5432409  0.4135426   1.365994   1.059917 -0.4152056
[3,]   9.5732902   8.265746  10.6187696 10.0876048  10.060632  10.662677 10.1650946
[4,]  99.2761925 102.260638  98.4231761 98.7391748 100.815118 102.227429 99.4150481
            [,8]        [,9]       [,10]
[1,] -11.3943881 -11.7160131  -9.9758877
[2,]   0.7688654  -0.1714558  -0.1244736
[3,]   9.9166631   8.6693463   8.3700419
[4,] 100.1034312 100.7393030 101.2005988

2. Eliminate the for loop in each of the following examples by taking advantage of an existing function that works with vectors:

out <- ""
for (x in letters) {
  out <- str_c(out, x)
}
out
[1] "abcdefghijklmnopqrstuvwxyz"

Since str_c() already works with vectors, use str_c() with the collapse argument to return a single string.

str_c(letters, collapse = "")
[1] "abcdefghijklmnopqrstuvwxyz"

For this I’m going to rename the variable sd to something different because sd is the name of the function we want to use.

x <- sample(100)
sd. <- 0
for (i in seq_along(x)) {
  sd. <- sd. + (x[i] - mean(x))^2
}
sd. <- sqrt(sd. / (length(x) - 1))
sd.
[1] 29.01149

We could simply use the sd function.

sd(x)
[1] 29.01149

Or if there was a need to use the equation (e.g. for pedagogical reasons), then the functions mean() and sum() already work with vectors:

sqrt(sum((x - mean(x))^2) / (length(x) - 1))
[1] 29.01149
x <- runif(100)
out <- vector("numeric", length(x))
out[1] <- x[1]
for (i in 2:length(x)) {
  out[i] <- out[i - 1] + x[i]
}
out
  [1]  0.4833509  0.8077550  1.0127418  1.2503234  1.4966745  2.1915957  2.3173779  2.7379348
  [9]  2.9903532  3.0482935  3.5639506  4.1101853  4.3540367  5.1676614  5.7144469  6.6987021
 [17]  7.3820307  8.2657172  8.4502061  9.2645614  9.9807558 10.7306632 11.1992083 11.9814965
 [25] 11.9867543 12.7651612 13.5853558 14.2413672 14.5115867 15.2931017 15.9463368 16.3811986
 [33] 17.1724166 17.7260300 18.2145337 18.5681511 19.0518730 19.8514935 20.7994761 21.0499754
 [41] 21.1728297 21.4745846 22.4434905 23.1533761 24.0195966 24.1118162 24.8609800 25.0203300
 [49] 25.5815511 25.6669226 26.2015690 26.8971049 27.0402187 27.4926847 27.5202339 27.6769189
 [57] 27.8098773 28.6871063 29.2832005 29.8781336 30.0260197 30.6875630 31.0150237 31.3600089
 [65] 31.8426292 32.0962825 32.1631060 33.0791059 33.5415238 33.7258625 34.5294342 34.6437064
 [73] 35.3488485 35.5583893 36.0890030 36.6555182 37.2343482 37.7418275 38.3071753 39.1159896
 [81] 39.9678348 40.8432187 40.9079630 41.0413575 41.8735347 42.4966863 43.4119003 43.6073202
 [89] 43.7900745 44.2615420 45.1341480 46.1037213 46.2536270 46.6308035 47.5119712 47.7761518
 [97] 47.8230047 48.1972253 48.6512495 49.6029852

The code above is calculating a cumulative sum. Use the function cumsum()

all.equal(cumsum(x), out)
[1] TRUE

3. Combine your function writing and for loop skills:

1. Write a for loop that prints() the lyrics to the children’s song “Alice the camel”.
2. Convert the nursery rhyme “ten in the bed” to a function. Generalize it to any number of people in any sleeping structure.
3. Convert the song “99 bottles of beer on the wall” to a function. Generalize to any number of any vessel containing any liquid on surface.

The answers to each part follow.

1. The lyrics for Alice the Camel are:

Alice the camel has five humps. Alice the camel has five humps. Alice the camel has five humps. So go, Alice, go.

This verse is repeated, each time with one fewer hump, until there are no humps. The last verse, with no humps, is:

Alice the camel has no humps. Alice the camel has no humps. Alice the camel has no humps. Now Alice is a horse.

We’ll iterate from five to no humps, and print out a different last line if there are no humps.

humps <- c("five", "four", "three", "two", "one", "no")
for (i in humps) {
  cat(str_c("Alice the camel has ", rep(i, 3), " humps.",
    collapse = "\n"
  ), "\n")
  if (i == "no") {
    cat("Now Alice is a horse.\n")
  } else {
    cat("So go, Alice, go.\n")
  }
  cat("\n")
}
Alice the camel has five humps.
Alice the camel has five humps.
Alice the camel has five humps. 
So go, Alice, go.

Alice the camel has four humps.
Alice the camel has four humps.
Alice the camel has four humps. 
So go, Alice, go.

Alice the camel has three humps.
Alice the camel has three humps.
Alice the camel has three humps. 
So go, Alice, go.

Alice the camel has two humps.
Alice the camel has two humps.
Alice the camel has two humps. 
So go, Alice, go.

Alice the camel has one humps.
Alice the camel has one humps.
Alice the camel has one humps. 
So go, Alice, go.

Alice the camel has no humps.
Alice the camel has no humps.
Alice the camel has no humps. 
Now Alice is a horse.

The lyrics for Ten in the Bed are:

Here we go! There were ten in the bed and the little one said, “Roll over, roll over.” So they all rolled over and one fell out.

This verse is repeated, each time with one fewer in the bed, until there is one left. That last verse is:

One! There was one in the bed and the little one said, “I’m lonely…”

numbers <- c(
  "ten", "nine", "eight", "seven", "six", "five",
  "four", "three", "two", "one"
)
for (i in numbers) {
  cat(str_c("There were ", i, " in the bed\n"))
  cat("and the little one said\n")
  if (i == "one") {
    cat("I'm lonely...")
  } else {
    cat("Roll over, roll over\n")
    cat("So they all rolled over and one fell out.\n")
  }
  cat("\n")
}
There were ten in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were nine in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were eight in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were seven in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were six in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were five in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were four in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were three in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were two in the bed
and the little one said
Roll over, roll over
So they all rolled over and one fell out.

There were one in the bed
and the little one said
I'm lonely...

The lyrics of Ninety-Nine Bottles of Beer on the Wall are

99 bottles of beer on the wall, 99 bottles of beer. Take one down, pass it around, 98 bottles of beer on the wall

This verse is repeated, each time with one few bottle, until there are no more bottles of beer. The last verse is

No more bottles of beer on the wall, no more bottles of beer. We’ve taken them down and passed them around; now we’re drunk and passed out!

For the bottles of beer, I define a helper function to correctly print the number of bottles.

bottles <- function(n) {
  if (n > 1) {
    str_c(n, " bottles")
  } else if (n == 1) {
    "1 bottle"
  } else {
    "no more bottles"
  }
}

beer_bottles <- function(total_bottles) {
  # print each lyric
  for (current_bottles in seq(total_bottles, 0)) {
    # first line
    cat(str_to_sentence(str_c(bottles(current_bottles), " of beer on the wall, ", bottles(current_bottles), " of beer.\n")))
    # second line
    if (current_bottles > 0) {
      cat(str_c(
        "Take one down and pass it around, ", bottles(current_bottles - 1),
        " of beer on the wall.\n"
      ))
    } else {
      cat(str_c("Go to the store and buy some more, ", bottles(total_bottles), " of beer on the wall.\n"))
    }
    cat("\n")
  }
}
beer_bottles(3)
3 bottles of beer on the wall, 3 bottles of beer.
Take one down and pass it around, 2 bottles of beer on the wall.

2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.

1 bottle of beer on the wall, 1 bottle of beer.
Take one down and pass it around, no more bottles of beer on the wall.

No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 3 bottles of beer on the wall.

4. It’s common to see for loops that don’t preallocate the output and instead increase the length of a vector at each step:

output <- vector("integer", 0)
for (i in seq_along(x)) {
  output <- c(output, lengths(x[[i]]))
}
output
  [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 [46] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 [91] 1 1 1 1 1 1 1 1 1 1

How does this affect performance? Design and execute an experiment.

In order to compare these two approaches, I’ll define two functions: add_to_vector will append to a vector, like the example in the question, and add_to_vector_2 which pre-allocates a vector.

add_to_vector <- function(n) {
  output <- vector("integer", 0)
  for (i in seq_len(n)) {
    output <- c(output, i)
  }
  output
}
add_to_vector_2 <- function(n) {
  output <- vector("integer", n)
  for (i in seq_len(n)) {
    output[[i]] <- i
  }
  output
}

I’ll use the package microbenchmark to run these functions several times and compare the time it takes. The package microbenchmark contains utilities for benchmarking R expressions. In particular, the microbenchmark() function will run an R expression a number of times and time it.

timings <- microbenchmark(add_to_vector(10000), add_to_vector_2(10000), times = 10)
timings
Unit: microseconds

In this example, appending to a vector takes 207 times longer than pre-allocating the vector. You may get different answers, but the longer the vector and the larger the objects, the more that pre-allocation will outperform appending.

LS0tDQp0aXRsZTogIkZvciBsb29wcyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQotLS0NCg0KYGBge3J9DQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeSgidGlkeXZlcnNlIikpDQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeSgic3RyaW5nciIpKQ0KI1RoZSBwYWNrYWdlIG1pY3JvYmVuY2htYXJrIGlzIHVzZWQgZm9yIHRpbWluZyBjb2RlLg0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoIm1pY3JvYmVuY2htYXJrIikpDQpgYGANCg0KIyMjIDEgV3JpdGUgZm9yLWxvb3BzIHRvOg0KDQoqKjEuIENvbXB1dGUgdGhlIG1lYW4gb2YgZXZlcnkgY29sdW1uIGluIGBtdGNhcnNgLioqICANCioqMi4gRGV0ZXJtaW5lIHRoZSB0eXBlIG9mIGVhY2ggY29sdW1uIGluIGBueWNmbGlnaHRzMTM6OmZsaWdodHNgLioqICANCioqMy4gQ29tcHV0ZSB0aGUgbnVtYmVyIG9mIHVuaXF1ZSB2YWx1ZXMgaW4gZWFjaCBjb2x1bW4gb2YgYGlyaXNgLioqICANCioqNC4gR2VuZXJhdGUgMTAgcmFuZG9tIG5vcm1hbHMgZm9yIGVhY2ggb2YkXG11JCA9IC0xMCwgMCwgMTAsIGFuZCAxMDAuKiogIA0KDQpUaGUgYW5zd2VycyBmb3IgZWFjaCBwYXJ0IGFyZSBiZWxvdy4NCg0KKioxLioqIFRvIGNvbXB1dGUgdGhlIG1lYW4gb2YgZXZlcnkgY29sdW1uIGluIGBtdGNhcnNgLg0KDQpgYGB7cn0NCm91dHB1dCA8LSB2ZWN0b3IoImRvdWJsZSIsIG5jb2wobXRjYXJzKSkNCm5hbWVzKG91dHB1dCkgPC0gbmFtZXMobXRjYXJzKQ0KZm9yIChpIGluIG5hbWVzKG10Y2FycykpIHsNCiAgb3V0cHV0W2ldIDwtIG1lYW4obXRjYXJzW1tpXV0pDQp9DQpvdXRwdXQNCmBgYA0KDQoqKjIuKiogRGV0ZXJtaW5lIHRoZSB0eXBlIG9mIGVhY2ggY29sdW1uIGluIGBueWNmbGlnaHRzMTM6OmZsaWdodHNgLg0KDQpgYGB7cn0NCm91dHB1dCA8LSB2ZWN0b3IoImxpc3QiLCBuY29sKG55Y2ZsaWdodHMxMzo6ZmxpZ2h0cykpDQpuYW1lcyhvdXRwdXQpIDwtIG5hbWVzKG55Y2ZsaWdodHMxMzo6ZmxpZ2h0cykNCmZvciAoaSBpbiBuYW1lcyhueWNmbGlnaHRzMTM6OmZsaWdodHMpKSB7DQogIG91dHB1dFtbaV1dIDwtIGNsYXNzKG55Y2ZsaWdodHMxMzo6ZmxpZ2h0c1tbaV1dKQ0KfQ0Kb3V0cHV0DQpgYGANCg0KSSB1c2VkIGEgYGxpc3RgLCBub3QgYSBjaGFyYWN0ZXIgdmVjdG9yLCBzaW5jZSB0aGUgY2xhc3Mgb2YgYW4gb2JqZWN0IGNhbiBoYXZlIG11bHRpcGxlIHZhbHVlcy4gRm9yIGV4YW1wbGUsIHRoZSBjbGFzcyBvZiB0aGUgYHRpbWVfaG91cmAgY29sdW1uIGlzIFBPU0lYY3QsIFBPU0lYdC4NCg0KKiozLioqIFRvIGNvbXB1dGUgdGhlIG51bWJlciBvZiB1bmlxdWUgdmFsdWVzIGluIGVhY2ggY29sdW1uIG9mIHRoZSBgaXJpc2AgZGF0YXNldC4NCg0KYGBge3J9DQpkYXRhKCJpcmlzIikNCmlyaXNfdW5pcSA8LSB2ZWN0b3IoImRvdWJsZSIsIG5jb2woaXJpcykpDQpuYW1lcyhpcmlzX3VuaXEpIDwtIG5hbWVzKGlyaXMpDQpmb3IgKGkgaW4gbmFtZXMoaXJpcykpIHsNCiAgaXJpc191bmlxW2ldIDwtIGxlbmd0aCh1bmlxdWUoaXJpc1tbaV1dKSkNCn0NCmlyaXNfdW5pcQ0KYGBgDQoNCioqNC4qKiBUbyBnZW5lcmF0ZSAxMCByYW5kb20gbm9ybWFscyBmb3IgZWFjaCBvZiRcbXUkID0gLTEwLCAwLCAxMCwgYW5kIDEwMC4NCg0KYGBge3J9DQojIG51bWJlciB0byBkcmF3DQpuIDwtIDEwDQojIHZhbHVlcyBvZiB0aGUgbWVhbg0KbXUgPC0gYygtMTAsIDAsIDEwLCAxMDApDQpub3JtYWxzIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aChtdSkpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKG5vcm1hbHMpKSB7DQogIG5vcm1hbHNbW2ldXSA8LSBybm9ybShuLCBtZWFuID0gbXVbaV0pDQp9DQpub3JtYWxzDQpgYGANCg0KSG93ZXZlciwgd2UgZG9u4oCZdCBuZWVkIGEgZm9yIGxvb3AgZm9yIHRoaXMgc2luY2UgYHJub3JtKClgIHJlY3ljbGUgdGhlIG1lYW4gYXJndW1lbnQuDQoNCmBgYHtyfQ0KbWF0cml4KHJub3JtKG4gKiBsZW5ndGgobXUpLCBtZWFuID0gbXUpLCBuY29sID0gbikNCmBgYA0KDQojIyMgMi4gRWxpbWluYXRlIHRoZSBmb3IgbG9vcCBpbiBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgZXhhbXBsZXMgYnkgdGFraW5nIGFkdmFudGFnZSBvZiBhbiBleGlzdGluZyBmdW5jdGlvbiB0aGF0IHdvcmtzIHdpdGggdmVjdG9yczoNCg0KYGBge3J9DQpvdXQgPC0gIiINCmZvciAoeCBpbiBsZXR0ZXJzKSB7DQogIG91dCA8LSBzdHJfYyhvdXQsIHgpDQp9DQpvdXQNCmBgYA0KDQpTaW5jZSBgc3RyX2MoKWAgYWxyZWFkeSB3b3JrcyB3aXRoIHZlY3RvcnMsIHVzZSBgc3RyX2MoKWAgd2l0aCB0aGUgY29sbGFwc2UgYXJndW1lbnQgdG8gcmV0dXJuIGEgc2luZ2xlIHN0cmluZy4NCg0KYGBge3J9DQpzdHJfYyhsZXR0ZXJzLCBjb2xsYXBzZSA9ICIiKQ0KYGBgDQoNCkZvciB0aGlzIEnigJltIGdvaW5nIHRvIHJlbmFtZSB0aGUgdmFyaWFibGUgc2QgdG8gc29tZXRoaW5nIGRpZmZlcmVudCBiZWNhdXNlIGBzZGAgaXMgdGhlIG5hbWUgb2YgdGhlIGZ1bmN0aW9uIHdlIHdhbnQgdG8gdXNlLg0KDQpgYGB7cn0NCnggPC0gc2FtcGxlKDEwMCkNCnNkLiA8LSAwDQpmb3IgKGkgaW4gc2VxX2Fsb25nKHgpKSB7DQogIHNkLiA8LSBzZC4gKyAoeFtpXSAtIG1lYW4oeCkpXjINCn0NCnNkLiA8LSBzcXJ0KHNkLiAvIChsZW5ndGgoeCkgLSAxKSkNCnNkLg0KYGBgDQoNCldlIGNvdWxkIHNpbXBseSB1c2UgdGhlIGBzZGAgZnVuY3Rpb24uDQoNCmBgYHtyfQ0Kc2QoeCkNCmBgYA0KDQpPciBpZiB0aGVyZSB3YXMgYSBuZWVkIHRvIHVzZSB0aGUgZXF1YXRpb24gKGUuZy4gZm9yIHBlZGFnb2dpY2FsIHJlYXNvbnMpLCB0aGVuIHRoZSBmdW5jdGlvbnMgYG1lYW4oKWAgYW5kIGBzdW0oKWAgYWxyZWFkeSB3b3JrIHdpdGggdmVjdG9yczoNCg0KYGBge3J9DQpzcXJ0KHN1bSgoeCAtIG1lYW4oeCkpXjIpIC8gKGxlbmd0aCh4KSAtIDEpKQ0KDQp4IDwtIHJ1bmlmKDEwMCkNCm91dCA8LSB2ZWN0b3IoIm51bWVyaWMiLCBsZW5ndGgoeCkpDQpvdXRbMV0gPC0geFsxXQ0KZm9yIChpIGluIDI6bGVuZ3RoKHgpKSB7DQogIG91dFtpXSA8LSBvdXRbaSAtIDFdICsgeFtpXQ0KfQ0Kb3V0DQpgYGANCg0KVGhlIGNvZGUgYWJvdmUgaXMgY2FsY3VsYXRpbmcgYSBjdW11bGF0aXZlIHN1bS4gVXNlIHRoZSBmdW5jdGlvbiBgY3Vtc3VtKClgDQoNCmBgYHtyfQ0KYWxsLmVxdWFsKGN1bXN1bSh4KSwgb3V0KQ0KYGBgDQoNCiMjIyAzLiBDb21iaW5lIHlvdXIgZnVuY3Rpb24gd3JpdGluZyBhbmQgZm9yIGxvb3Agc2tpbGxzOg0KDQoqKjEuIFdyaXRlIGEgZm9yIGxvb3AgdGhhdCBgcHJpbnRzKClgIHRoZSBseXJpY3MgdG8gdGhlIGNoaWxkcmVu4oCZcyBzb25nIOKAnEFsaWNlIHRoZSBjYW1lbOKAnS4qKiAgDQoqKjIuIENvbnZlcnQgdGhlIG51cnNlcnkgcmh5bWUg4oCcdGVuIGluIHRoZSBiZWTigJ0gdG8gYSBmdW5jdGlvbi4gR2VuZXJhbGl6ZSBpdCB0byBhbnkgbnVtYmVyIG9mIHBlb3BsZSBpbiBhbnkgc2xlZXBpbmcgc3RydWN0dXJlLioqICANCioqMy4gQ29udmVydCB0aGUgc29uZyDigJw5OSBib3R0bGVzIG9mIGJlZXIgb24gdGhlIHdhbGzigJ0gdG8gYSBmdW5jdGlvbi4gR2VuZXJhbGl6ZSB0byBhbnkgbnVtYmVyIG9mIGFueSB2ZXNzZWwgY29udGFpbmluZyBhbnkgbGlxdWlkIG9uIHN1cmZhY2UuKioNCg0KVGhlIGFuc3dlcnMgdG8gZWFjaCBwYXJ0IGZvbGxvdy4NCg0KKioxLioqIFRoZSBseXJpY3MgZm9yIEFsaWNlIHRoZSBDYW1lbCBhcmU6DQoNCj5BbGljZSB0aGUgY2FtZWwgaGFzIGZpdmUgaHVtcHMuDQpBbGljZSB0aGUgY2FtZWwgaGFzIGZpdmUgaHVtcHMuDQpBbGljZSB0aGUgY2FtZWwgaGFzIGZpdmUgaHVtcHMuDQpTbyBnbywgQWxpY2UsIGdvLg0KDQpUaGlzIHZlcnNlIGlzIHJlcGVhdGVkLCBlYWNoIHRpbWUgd2l0aCBvbmUgZmV3ZXIgaHVtcCwgdW50aWwgdGhlcmUgYXJlIG5vIGh1bXBzLiBUaGUgbGFzdCB2ZXJzZSwgd2l0aCBubyBodW1wcywgaXM6DQoNCj5BbGljZSB0aGUgY2FtZWwgaGFzIG5vIGh1bXBzLg0KQWxpY2UgdGhlIGNhbWVsIGhhcyBubyBodW1wcy4NCkFsaWNlIHRoZSBjYW1lbCBoYXMgbm8gaHVtcHMuDQpOb3cgQWxpY2UgaXMgYSBob3JzZS4NCg0KV2XigJlsbCBpdGVyYXRlIGZyb20gZml2ZSB0byBubyBodW1wcywgYW5kIHByaW50IG91dCBhIGRpZmZlcmVudCBsYXN0IGxpbmUgaWYgdGhlcmUgYXJlIG5vIGh1bXBzLg0KDQpgYGB7cn0NCmh1bXBzIDwtIGMoImZpdmUiLCAiZm91ciIsICJ0aHJlZSIsICJ0d28iLCAib25lIiwgIm5vIikNCmZvciAoaSBpbiBodW1wcykgew0KICBjYXQoc3RyX2MoIkFsaWNlIHRoZSBjYW1lbCBoYXMgIiwgcmVwKGksIDMpLCAiIGh1bXBzLiIsDQogICAgY29sbGFwc2UgPSAiXG4iDQogICksICJcbiIpDQogIGlmIChpID09ICJubyIpIHsNCiAgICBjYXQoIk5vdyBBbGljZSBpcyBhIGhvcnNlLlxuIikNCiAgfSBlbHNlIHsNCiAgICBjYXQoIlNvIGdvLCBBbGljZSwgZ28uXG4iKQ0KICB9DQogIGNhdCgiXG4iKQ0KfQ0KYGBgDQoNClRoZSBseXJpY3MgZm9yIFRlbiBpbiB0aGUgQmVkIGFyZToNCg0KPkhlcmUgd2UgZ28hDQpUaGVyZSB3ZXJlIHRlbiBpbiB0aGUgYmVkDQphbmQgdGhlIGxpdHRsZSBvbmUgc2FpZCwNCuKAnFJvbGwgb3Zlciwgcm9sbCBvdmVyLuKAnQ0KU28gdGhleSBhbGwgcm9sbGVkIG92ZXIgYW5kIG9uZSBmZWxsIG91dC4NCg0KVGhpcyB2ZXJzZSBpcyByZXBlYXRlZCwgZWFjaCB0aW1lIHdpdGggb25lIGZld2VyIGluIHRoZSBiZWQsIHVudGlsIHRoZXJlIGlzIG9uZSBsZWZ0LiBUaGF0IGxhc3QgdmVyc2UgaXM6DQoNCj5PbmUhIFRoZXJlIHdhcyBvbmUgaW4gdGhlIGJlZA0KYW5kIHRoZSBsaXR0bGUgb25lIHNhaWQsDQrigJxJ4oCZbSBsb25lbHnigKbigJ0NCg0KYGBge3J9DQpudW1iZXJzIDwtIGMoDQogICJ0ZW4iLCAibmluZSIsICJlaWdodCIsICJzZXZlbiIsICJzaXgiLCAiZml2ZSIsDQogICJmb3VyIiwgInRocmVlIiwgInR3byIsICJvbmUiDQopDQpmb3IgKGkgaW4gbnVtYmVycykgew0KICBjYXQoc3RyX2MoIlRoZXJlIHdlcmUgIiwgaSwgIiBpbiB0aGUgYmVkXG4iKSkNCiAgY2F0KCJhbmQgdGhlIGxpdHRsZSBvbmUgc2FpZFxuIikNCiAgaWYgKGkgPT0gIm9uZSIpIHsNCiAgICBjYXQoIkknbSBsb25lbHkuLi4iKQ0KICB9IGVsc2Ugew0KICAgIGNhdCgiUm9sbCBvdmVyLCByb2xsIG92ZXJcbiIpDQogICAgY2F0KCJTbyB0aGV5IGFsbCByb2xsZWQgb3ZlciBhbmQgb25lIGZlbGwgb3V0LlxuIikNCiAgfQ0KICBjYXQoIlxuIikNCn0NCmBgYA0KDQpUaGUgbHlyaWNzIG9mIE5pbmV0eS1OaW5lIEJvdHRsZXMgb2YgQmVlciBvbiB0aGUgV2FsbCBhcmUNCg0KPjk5IGJvdHRsZXMgb2YgYmVlciBvbiB0aGUgd2FsbCwgOTkgYm90dGxlcyBvZiBiZWVyLg0KVGFrZSBvbmUgZG93biwgcGFzcyBpdCBhcm91bmQsIDk4IGJvdHRsZXMgb2YgYmVlciBvbiB0aGUgd2FsbA0KDQpUaGlzIHZlcnNlIGlzIHJlcGVhdGVkLCBlYWNoIHRpbWUgd2l0aCBvbmUgZmV3IGJvdHRsZSwgdW50aWwgdGhlcmUgYXJlIG5vIG1vcmUgYm90dGxlcyBvZiBiZWVyLiBUaGUgbGFzdCB2ZXJzZSBpcw0KDQo+Tm8gbW9yZSBib3R0bGVzIG9mIGJlZXIgb24gdGhlIHdhbGwsIG5vIG1vcmUgYm90dGxlcyBvZiBiZWVyLg0KV2XigJl2ZSB0YWtlbiB0aGVtIGRvd24gYW5kIHBhc3NlZCB0aGVtIGFyb3VuZDsgbm93IHdl4oCZcmUgZHJ1bmsgYW5kIHBhc3NlZCBvdXQhDQoNCkZvciB0aGUgYm90dGxlcyBvZiBiZWVyLCBJIGRlZmluZSBhIGhlbHBlciBmdW5jdGlvbiB0byBjb3JyZWN0bHkgcHJpbnQgdGhlIG51bWJlciBvZiBib3R0bGVzLg0KDQpgYGB7cn0NCmJvdHRsZXMgPC0gZnVuY3Rpb24obikgew0KICBpZiAobiA+IDEpIHsNCiAgICBzdHJfYyhuLCAiIGJvdHRsZXMiKQ0KICB9IGVsc2UgaWYgKG4gPT0gMSkgew0KICAgICIxIGJvdHRsZSINCiAgfSBlbHNlIHsNCiAgICAibm8gbW9yZSBib3R0bGVzIg0KICB9DQp9DQoNCmJlZXJfYm90dGxlcyA8LSBmdW5jdGlvbih0b3RhbF9ib3R0bGVzKSB7DQogICMgcHJpbnQgZWFjaCBseXJpYw0KICBmb3IgKGN1cnJlbnRfYm90dGxlcyBpbiBzZXEodG90YWxfYm90dGxlcywgMCkpIHsNCiAgICAjIGZpcnN0IGxpbmUNCiAgICBjYXQoc3RyX3RvX3NlbnRlbmNlKHN0cl9jKGJvdHRsZXMoY3VycmVudF9ib3R0bGVzKSwgIiBvZiBiZWVyIG9uIHRoZSB3YWxsLCAiLCBib3R0bGVzKGN1cnJlbnRfYm90dGxlcyksICIgb2YgYmVlci5cbiIpKSkNCiAgICAjIHNlY29uZCBsaW5lDQogICAgaWYgKGN1cnJlbnRfYm90dGxlcyA+IDApIHsNCiAgICAgIGNhdChzdHJfYygNCiAgICAgICAgIlRha2Ugb25lIGRvd24gYW5kIHBhc3MgaXQgYXJvdW5kLCAiLCBib3R0bGVzKGN1cnJlbnRfYm90dGxlcyAtIDEpLA0KICAgICAgICAiIG9mIGJlZXIgb24gdGhlIHdhbGwuXG4iDQogICAgICApKQ0KICAgIH0gZWxzZSB7DQogICAgICBjYXQoc3RyX2MoIkdvIHRvIHRoZSBzdG9yZSBhbmQgYnV5IHNvbWUgbW9yZSwgIiwgYm90dGxlcyh0b3RhbF9ib3R0bGVzKSwgIiBvZiBiZWVyIG9uIHRoZSB3YWxsLlxuIikpDQogICAgfQ0KICAgIGNhdCgiXG4iKQ0KICB9DQp9DQpiZWVyX2JvdHRsZXMoMykNCmBgYA0KDQojIyMgNC4gSXTigJlzIGNvbW1vbiB0byBzZWUgZm9yIGxvb3BzIHRoYXQgZG9u4oCZdCBwcmVhbGxvY2F0ZSB0aGUgb3V0cHV0IGFuZCBpbnN0ZWFkIGluY3JlYXNlIHRoZSBsZW5ndGggb2YgYSB2ZWN0b3IgYXQgZWFjaCBzdGVwOg0KDQpgYGB7cn0NCm91dHB1dCA8LSB2ZWN0b3IoImludGVnZXIiLCAwKQ0KZm9yIChpIGluIHNlcV9hbG9uZyh4KSkgew0KICBvdXRwdXQgPC0gYyhvdXRwdXQsIGxlbmd0aHMoeFtbaV1dKSkNCn0NCm91dHB1dA0KYGBgDQoNCkhvdyBkb2VzIHRoaXMgYWZmZWN0IHBlcmZvcm1hbmNlPyBEZXNpZ24gYW5kIGV4ZWN1dGUgYW4gZXhwZXJpbWVudC4NCg0KSW4gb3JkZXIgdG8gY29tcGFyZSB0aGVzZSB0d28gYXBwcm9hY2hlcywgSeKAmWxsIGRlZmluZSB0d28gZnVuY3Rpb25zOiBgYWRkX3RvX3ZlY3RvcmAgd2lsbCBhcHBlbmQgdG8gYSB2ZWN0b3IsIGxpa2UgdGhlIGV4YW1wbGUgaW4gdGhlIHF1ZXN0aW9uLCBhbmQgYGFkZF90b192ZWN0b3JfMmAgd2hpY2ggcHJlLWFsbG9jYXRlcyBhIHZlY3Rvci4NCg0KYGBge3J9DQphZGRfdG9fdmVjdG9yIDwtIGZ1bmN0aW9uKG4pIHsNCiAgb3V0cHV0IDwtIHZlY3RvcigiaW50ZWdlciIsIDApDQogIGZvciAoaSBpbiBzZXFfbGVuKG4pKSB7DQogICAgb3V0cHV0IDwtIGMob3V0cHV0LCBpKQ0KICB9DQogIG91dHB1dA0KfQ0KYWRkX3RvX3ZlY3Rvcl8yIDwtIGZ1bmN0aW9uKG4pIHsNCiAgb3V0cHV0IDwtIHZlY3RvcigiaW50ZWdlciIsIG4pDQogIGZvciAoaSBpbiBzZXFfbGVuKG4pKSB7DQogICAgb3V0cHV0W1tpXV0gPC0gaQ0KICB9DQogIG91dHB1dA0KfQ0KYGBgDQoNCknigJlsbCB1c2UgdGhlIHBhY2thZ2UgYG1pY3JvYmVuY2htYXJrYCB0byBydW4gdGhlc2UgZnVuY3Rpb25zIHNldmVyYWwgdGltZXMgYW5kIGNvbXBhcmUgdGhlIHRpbWUgaXQgdGFrZXMuIFRoZSBwYWNrYWdlIGBtaWNyb2JlbmNobWFya2AgY29udGFpbnMgdXRpbGl0aWVzIGZvciBiZW5jaG1hcmtpbmcgUiBleHByZXNzaW9ucy4gSW4gcGFydGljdWxhciwgdGhlIGBtaWNyb2JlbmNobWFyaygpYCBmdW5jdGlvbiB3aWxsIHJ1biBhbiBSIGV4cHJlc3Npb24gYSBudW1iZXIgb2YgdGltZXMgYW5kIHRpbWUgaXQuDQoNCmBgYHtyfQ0KdGltaW5ncyA8LSBtaWNyb2JlbmNobWFyayhhZGRfdG9fdmVjdG9yKDEwMDAwKSwgYWRkX3RvX3ZlY3Rvcl8yKDEwMDAwKSwgdGltZXMgPSAxMCkNCnRpbWluZ3MNCmBgYA0KDQpJbiB0aGlzIGV4YW1wbGUsIGFwcGVuZGluZyB0byBhIHZlY3RvciB0YWtlcyAyMDcgdGltZXMgbG9uZ2VyIHRoYW4gcHJlLWFsbG9jYXRpbmcgdGhlIHZlY3Rvci4gWW91IG1heSBnZXQgZGlmZmVyZW50IGFuc3dlcnMsIGJ1dCB0aGUgbG9uZ2VyIHRoZSB2ZWN0b3IgYW5kIHRoZSBsYXJnZXIgdGhlIG9iamVjdHMsIHRoZSBtb3JlIHRoYXQgcHJlLWFsbG9jYXRpb24gd2lsbCBvdXRwZXJmb3JtIGFwcGVuZGluZy4=