Topics

House buying

rr a <- 1 b <- NA is.na(a)

[1] FALSE

rr is.na(b)

[1] TRUE

rr monthly.cost <- function(cost, fee, operating=NA, deposit=NA, interest=0.017, amortization=0.02, n.residents=2){ if (is.na(deposit)){ deposit <- cost * 0.15} if (is.na(operating)) {operating <- 300 * n.residents} loan <- cost - deposit interest <- (loan * (interest + amortization)) / 12 interest + fee + operating } monthly.cost(4490000, 4695, 17400/12)

[1] 17913

rr monthly.cost(2970000, 3210)

[1] 11594

Tidyverse vs. base R

rr # Base R m <- matrix(1:9, nrow=3) m # a matrix

     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

rr m[1,1] # a cell

[1] 1

rr class(m[1,]) # a vector

[1] \integer\

rr m[1,1] # a cell

[1] 1

rr m[1,] # a vector

[1] 1 4 7

Preliminaries

  • Please install the babynames package. All loading this package does is give you one big tibble called babynames with some interesting sample data for us to play with
  • To install the package use RStudio “Tools” -> “Install packages…”

It’s good style to do all your library function calls at the beginning of your scripts, notebooks, etc. For example, tidyverse redefines filter, and you don’t want filter to mean one thing for one half of your script and something else for the other. It also means that if you cut-and-paste something you know where to look for any libraries it might depend on.

rr library(tidyverse) library(babynames)

  • loading babynames gives you access to a huge tibble (table of text and numerical data) called babynames
  • You can enter help(babynames) in the console to get a description of the data (SSA is the US Social Security Administration). Next week we’ll look at Swedish names instead!

Long data: every observation is its own row. Next week we’ll look at Swedish name data from Statistiska Centralbyrån, which is in “wide” format (multiple observations per row)

rr head(babynames)

First steps with dplyr (part of tidyverse)

Dplyr aims to provide a function for each basic verb of data manipulation. These include:

- filter() to select cases based on their values.
- arrange() to reorder the cases.
- select() and rename() to select variables based on their names.
- mutate() and transmute() to add new variables that are functions of existing variables.

The dplyr verbs: filter, select:

Filtering rows:

Use | for “or”

  • filter(a, b) is the same as the “and” relationship filter(a & b); cf. “or” filter(a | b)

Selecting columns:

rr select(babynames, year, name, n)

Piping %>%

funct(a, b) is the same as a %>% funct(b)

This can simplify things:

http://r4ds.had.co.nz/pipes.html

Functions are verbs, arguments are nouns

How to deal with multiple steps of an analysis

  • save intermediate steps (clutters the namespace, lots of memory)
  • overwrite the original (hard to debug)
  • nested functions (have to read in inside-out order, arguments are spread out)
  • the pipe syntax (the human way!)
  • piped functions can be chained together:

Works best

  • with one input, one output
  • not too many steps (<10)
  • Notice the return value of the pipe: a %>% b “sends” a to b, and then the statement returns something, which can be sent along to the next thing a %>% b %>% c
  • The thing that you’re piping in is the first, default argument of the function. Tidyverse functions mark this in the help files with a leading dot, e.g. .data in help(filter)
  • Chaining pipes together

  • TODO Class time to experiment

Assigning piped data

The final results of pipes can be assigned to variables as normal of course

There’s also a right arrow -> version of the assignment operator <-

rr x <- 4 # is the same as 4 -> x

  • This is convenient on the console sometimes, when you want to reuse something from your history and assign it to a variable
  • It’s generally discouraged otherwise
  • But it does make nice logical sense with pipe-sequences
data %>% a() %>% b() -> result

Compare the “normal” way:

result <- data %>% a() %>% b()

sorting columns with arrange

desc means descending

rr rnorm(100) %>% tibble(id=1:100, n=.)

Renaming columns

rr # geom_col() # geom_line()

mutate() adds columns

rr options(scipen=999) # disable scientific notation (i.e. 1000 == 1e04)

Dot “.” stands for “the thing that you’re piping in” (for cases when it’s not the first argument)

cf. also .data in docs (see e.g. help(filter))

ggplot

  • Calling the function ggplot starts assembling the graph; it has the default argument data, which you can pipe to the function
  • the aes() (“aesthetic”) function maps data onto graph attributes
  • You build up the plot in layers using +
  • geometic layers have names starting with geom_. These include geom_point (scatterplots), geom_box (boxplots), geom_histogram (histograms)`, and may others. There is a default set that it part of tidyverse, and then others can be added by calling libraries.
  • There are lots more things you can change, but these three steps are the basic idea: take data, map to an aesthetic, and plot as a geometric layer

Numbers like 1.5e-05 are scientific notation, shorthand for “1.5 times 10 to the power of -5”, which means 0.000015

To disable this, use the following at the start of your notebook:

rr library(tidyverse) # should do this at the beginning my.data <- tibble(values=rnorm(100, 10, 2.5)) my.data %>% ggplot(aes(x=values)) + geom_histogram(binwidth=1)

Preview (we will look at this next week): you can specify other elements of the plot aesthetic to be determined by values in your data. Let’s just use colour for now:

rr tibble(values=rnorm(10000, 10, 2.5)) %>% ggplot(aes(x=values)) + geom_histogram(binwidth=1)

rr toy.data <- tibble(rank=1:10) toy.data\(freq <- 1 / toy.data\)rank toy.data

Some statistical distributions

Normal distribution

Galton Board

In a normal distribution: - 68.2% of values within one standard deviation - 95.4% within two standard deviations - 99.7% within 3 - 99.99% within 4

Standard deviations

Standard deviations

Normal distributions can be described by two parameters, mean and standard deviation. The rnorm() function generates vectors of random numbers accordingn to a normal distribution.

TODO Read the help for the rnorm() function. Generate some vectors of normally distributed random numbers given different means and standard deviations.

Histogram

  • rnorm(N, mean, sd)

Here’s how you can visualise these:

rr toy.data %>% ggplot(aes(x=rank, y=freq)) + geom_point()

A small sample will be jagged, but the larger the sample the smoother it gets:

rr toy.data %>% ggplot(aes(x=log10(rank), y=log10(freq))) + geom_point() + geom_line()

Uniform distribution

There are many kinds of distributions.

  • runif(N, min, max)

In the Uniform distribution there is an equal chance of getting any value between the minimum and the maximum

rr my.data <- tibble(x=1:6, y=10^(1:6)) qplot(x, y, data=my.data)

LS0tCnRpdGxlOiAiVmlzdWFsaXNhdGlvbiBhbmQgc3RhdGlzdGljYWwgYW5hbHlzaXMiCmF1dGhvcjogIk1pY2hhZWwgRHVubiwgRGVwdC4gb2YgTGluZ3Vpc3RpY3MgYW5kIFBoaWxvbG9neSwgVXBwc2FsYSBVbml2ZXJzaXR5IgpkYXRlOiAiU2Vzc2lvbiAzLCAyMDE4LTEwLTA4IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBlY2hvPUZBTFNFfQpvcHRpb25zKHNjaXBlbj05OTkpICMgZGlzYWJsZSBzY2llbnRpZmljIG5vdGF0aW9uIChpLmUuIDEwMDAgPT0gMWUwNCkKYGBgCgpUb3BpY3MKCi0gSG9tZXdvcmsKICAqIHdyaXRpbmcgYSBmdW5jdGlvbgogICogaW1wb3J0aW5nIHRoZSBLZWxseSBkYXRhCi0gR2V0dGluZyB0aGUgcGFydHMgb2YgeW91ciBkYXRhIHlvdSBhcmUgaW50ZXJlc3RlZCBpbjoKICAqIGZpbHRlcigpCiAgKiBzZWxlY3QoKQotIFNvcnRpbmcsIHJlbmFtaW5nLCBhbmQgbXV0YXRpbmcgKGFkZGluZykKLSBQbG90dGluZyBzaW1wbGUgdGFidWxhciBkYXRhCi0gRGlzdHJpYnV0aW9ucyBhbmQgaGlzdG9ncmFtcwogICogcm5vcm0KICAqIHJ1bmlmCi0gbG9nIHZhbHVlcwotIFppcGYgZGlzdHJpYnV0aW9uCgojIyBIb3VzZSBidXlpbmcKCmBgYHtyfQphIDwtIDEKYiA8LSBOQQppcy5uYShhKQppcy5uYShiKQpgYGAKCgpgYGB7cn0KbW9udGhseS5jb3N0IDwtIGZ1bmN0aW9uKGNvc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgZmVlLCAKICAgICAgICAgICAgICAgICAgICAgICAgIG9wZXJhdGluZz1OQSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZXBvc2l0PU5BLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyZXN0PTAuMDE3LCAKICAgICAgICAgICAgICAgICAgICAgICAgIGFtb3J0aXphdGlvbj0wLjAyLAogICAgICAgICAgICAgICAgICAgICAgICAgbi5yZXNpZGVudHM9Mil7CiAgaWYgKGlzLm5hKGRlcG9zaXQpKXsgZGVwb3NpdCA8LSBjb3N0ICogMC4xNX0KICBpZiAoaXMubmEob3BlcmF0aW5nKSkge29wZXJhdGluZyA8LSAzMDAgKiBuLnJlc2lkZW50c30KICBsb2FuIDwtIGNvc3QgLSBkZXBvc2l0CiAgaW50ZXJlc3QgPC0gKGxvYW4gKiAoaW50ZXJlc3QgKyBhbW9ydGl6YXRpb24pKSAvIDEyCiAgaW50ZXJlc3QgKyBmZWUgKyBvcGVyYXRpbmcKfQoKbW9udGhseS5jb3N0KDQ0OTAwMDAsIDQ2OTUsIDE3NDAwLzEyKQptb250aGx5LmNvc3QoMjk3MDAwMCwgMzIxMCkKYGBgCgojIFRpZHl2ZXJzZSB2cy4gYmFzZSBSCgotIFRoZSByZWFkX2NzdiBpcyB0aGUgdGlkeXZlcnNlIHZlcnNpb24gb2YgcmVhZC5jc3YuIAotIFdlJ3JlIHdvcmtpbmcgaW4gdGhlIHRpZHl2ZXJzZSBgbGlicmFyeSh0aWR5dmVyc2UpYCBhdCB0aGUgYmVnaW5uaW5nIG9mIGV2ZXJ5IHNjcmlwdCEKCmBgYHtyfQojIEJhc2UgUgoKbSA8LSBtYXRyaXgoMTo5LCBucm93PTMpCm0gIyBhIG1hdHJpeApgYGAKYGBge3J9Cm1bMSwxXSAjIGEgY2VsbApgYGAKYGBge3J9Cm1bMSxdICMgYSB2ZWN0b3IKYGBgCgojIyBQcmVsaW1pbmFyaWVzCgotIFBsZWFzZSBpbnN0YWxsIHRoZSBgYmFieW5hbWVzYCBwYWNrYWdlLiBBbGwgbG9hZGluZyB0aGlzIHBhY2thZ2UgZG9lcyBpcyBnaXZlIHlvdSBvbmUgYmlnIHRpYmJsZSBjYWxsZWQgYGJhYnluYW1lc2Agd2l0aCBzb21lIGludGVyZXN0aW5nIHNhbXBsZSBkYXRhIGZvciB1cyB0byBwbGF5IHdpdGgKLSBUbyBpbnN0YWxsIHRoZSBwYWNrYWdlIHVzZSBSU3R1ZGlvICJUb29scyIgLT4gIkluc3RhbGwgcGFja2FnZXMuLi4iCgpJdCdzIGdvb2Qgc3R5bGUgdG8gZG8gYWxsIHlvdXIgbGlicmFyeSBmdW5jdGlvbiBjYWxscyBhdCB0aGUgYmVnaW5uaW5nIG9mIHlvdXIgc2NyaXB0cywgbm90ZWJvb2tzLCBldGMuIEZvciBleGFtcGxlLCB0aWR5dmVyc2UgcmVkZWZpbmVzIGBmaWx0ZXJgLCBhbmQgeW91IGRvbid0IHdhbnQgYGZpbHRlcmAgdG8gbWVhbiBvbmUgdGhpbmcgZm9yIG9uZSBoYWxmIG9mIHlvdXIgc2NyaXB0IGFuZCBzb21ldGhpbmcgZWxzZSBmb3IgdGhlIG90aGVyLiBJdCBhbHNvIG1lYW5zIHRoYXQgaWYgeW91IGN1dC1hbmQtcGFzdGUgc29tZXRoaW5nIHlvdSBrbm93IHdoZXJlIHRvIGxvb2sgZm9yIGFueSBsaWJyYXJpZXMgaXQgbWlnaHQgZGVwZW5kIG9uLgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoYmFieW5hbWVzKSAKYGBgCi0gbG9hZGluZyBiYWJ5bmFtZXMgZ2l2ZXMgeW91IGFjY2VzcyB0byBhIGh1Z2UgdGliYmxlICh0YWJsZSBvZiB0ZXh0IGFuZCBudW1lcmljYWwgZGF0YSkgY2FsbGVkIGBiYWJ5bmFtZXNgCi0gWW91IGNhbiBlbnRlciBgaGVscChiYWJ5bmFtZXMpYCBpbiB0aGUgY29uc29sZSB0byBnZXQgYSBkZXNjcmlwdGlvbiBvZiB0aGUgZGF0YSAoU1NBIGlzIHRoZSBVUyBTb2NpYWwgU2VjdXJpdHkgQWRtaW5pc3RyYXRpb24pLiBOZXh0IHdlZWsgd2UnbGwgbG9vayBhdCBTd2VkaXNoIG5hbWVzIGluc3RlYWQhCgpMb25nIGRhdGE6IGV2ZXJ5IG9ic2VydmF0aW9uIGlzIGl0cyBvd24gcm93LiBOZXh0IHdlZWsgd2UnbGwgbG9vayBhdCBTd2VkaXNoIG5hbWUgZGF0YSBmcm9tIFN0YXRpc3Rpc2thIENlbnRyYWxieXLDpW4sIHdoaWNoIGlzIGluICJ3aWRlIiBmb3JtYXQgKG11bHRpcGxlIG9ic2VydmF0aW9ucyBwZXIgcm93KQpgYGB7cn0KaGVhZChiYWJ5bmFtZXMpCmBgYAoKIyMgRmlyc3Qgc3RlcHMgd2l0aCBkcGx5ciAocGFydCBvZiB0aWR5dmVyc2UpCgpEcGx5ciBhaW1zIHRvIHByb3ZpZGUgYSBmdW5jdGlvbiBmb3IgZWFjaCBiYXNpYyB2ZXJiIG9mIGRhdGEgbWFuaXB1bGF0aW9uLiBUaGVzZSBpbmNsdWRlOgoKICAgIC0gZmlsdGVyKCkgdG8gc2VsZWN0IGNhc2VzIGJhc2VkIG9uIHRoZWlyIHZhbHVlcy4KICAgIC0gYXJyYW5nZSgpIHRvIHJlb3JkZXIgdGhlIGNhc2VzLgogICAgLSBzZWxlY3QoKSBhbmQgcmVuYW1lKCkgdG8gc2VsZWN0IHZhcmlhYmxlcyBiYXNlZCBvbiB0aGVpciBuYW1lcy4KICAgIC0gbXV0YXRlKCkgYW5kIHRyYW5zbXV0ZSgpIHRvIGFkZCBuZXcgdmFyaWFibGVzIHRoYXQgYXJlIGZ1bmN0aW9ucyBvZiBleGlzdGluZyB2YXJpYWJsZXMuCgpUaGUgZHBseXIgdmVyYnM6IGZpbHRlciwgc2VsZWN0OgoKRmlsdGVyaW5nIHJvd3M6CmBgYHtyfQojIHRoZSBmaWx0ZXIgZnVuY3Rpb24gaXMgYXdhcmUgb2YgdGhlIG5hbWVzIG9mIHRoZSBjb2x1bW5zIGluIHRoZSB0YWJsZQpmaWx0ZXIoYmFieW5hbWVzLCBuYW1lPT0iTWljaGFlbCIsIHNleD09IkYiKQpgYGAKYGBge3J9CmZpbHRlcihiYWJ5bmFtZXMsIG5hbWU9PSJMZW5hIiwgeWVhcj09MjAwMCkKYGBgClVzZSB8IGZvciAib3IiCmBgYHtyfQpmaWx0ZXIoYmFieW5hbWVzLCBuYW1lPT0iUmltYSIgfCBuYW1lPT0iTWFqYSIsIHllYXIgPiAxOTU5LCB5ZWFyIDwgMTk2NikKYGBgCgotIGBmaWx0ZXIoYSwgYilgIGlzIHRoZSBzYW1lIGFzIHRoZSAiYW5kIiByZWxhdGlvbnNoaXAgYGZpbHRlcihhICYgYilgOyBjZi4gIm9yIiBgZmlsdGVyKGEgfCBiKWAKCmBgYHtyfQpmaWx0ZXIoYmFieW5hbWVzLCBuYW1lPT0iWGF2aWVyIiB8IG5hbWUgPT0iQW5hc3Rhc2lhIikKYGBgCgpTZWxlY3RpbmcgY29sdW1uczoKYGBge3J9CnNlbGVjdChiYWJ5bmFtZXMsIHllYXIsIG5hbWUsIG4pCmBgYAoKIyMgUGlwaW5nICU+JQoKYGZ1bmN0KGEsIGIpYCBpcyB0aGUgc2FtZSBhcyBgYSAlPiUgZnVuY3QoYilgCgpgYGB7cn0KYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09IkxlbmEiLCB5ZWFyPT0yMDAwKQpgYGAKClRoaXMgY2FuIHNpbXBsaWZ5IHRoaW5nczoKCmBgYHtyfQpiYWJ5bmFtZXMgJT4lIGZpbHRlcihuYW1lPT0iTWljaGFlbCIpICU+JSBmaWx0ZXIoeWVhciA8PSAxOTAwKSAlPiUgZmlsdGVyKHNleD09IkYiKQpgYGAKCmh0dHA6Ly9yNGRzLmhhZC5jby5uei9waXBlcy5odG1sCgpGdW5jdGlvbnMgYXJlIHZlcmJzLCBhcmd1bWVudHMgYXJlIG5vdW5zCgpIb3cgdG8gZGVhbCB3aXRoIG11bHRpcGxlIHN0ZXBzIG9mIGFuIGFuYWx5c2lzCgotIHNhdmUgaW50ZXJtZWRpYXRlIHN0ZXBzIChjbHV0dGVycyB0aGUgbmFtZXNwYWNlLCBsb3RzIG9mIG1lbW9yeSkKCmBgYHtyfQptaWNoYWVsMCA8LSBmaWx0ZXIoYmFieW5hbWVzLCBuYW1lPT0iTWljaGFlbCIpCm1pY2hhZWwxIDwtIHNlbGVjdChtaWNoYWVsMCwgbmFtZSwgbiwgeWVhcikKYGBgCi0gb3ZlcndyaXRlIHRoZSBvcmlnaW5hbCAoaGFyZCB0byBkZWJ1ZykKYGBge3J9Cm1pY2hhZWwgPC0gZmlsdGVyKGJhYnluYW1lcywgbmFtZT09Ik1pY2hhZWwiKQptaWNoYWVsIDwtIHNlbGVjdChtaWNoYWVsLCBuYW1lLCBuLCB5ZWFyKQpgYGAKLSBuZXN0ZWQgZnVuY3Rpb25zIChoYXZlIHRvIHJlYWQgaW4gaW5zaWRlLW91dCBvcmRlciwgYXJndW1lbnRzIGFyZSBzcHJlYWQgb3V0KQpgYGB7cn0KbWljaGFlbCA8LSBzZWxlY3QoCiAgZmlsdGVyKGJhYnluYW1lcywgbmFtZT09Ik1pY2hhZWwiKSwgCiAgbmFtZSwgbiwgeWVhcgopCmBgYAoKLSB0aGUgcGlwZSBzeW50YXggKHRoZSBodW1hbiB3YXkhKQpgYGB7cn0KYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ik1pY2hhZWwiKQojIFNBTUUgQVMgZmlsdGVyKGJhYnluYW1lcywgbmFtZT09Ik1pY2hhZWwiKQpgYGAKCi0gcGlwZWQgZnVuY3Rpb25zIGNhbiBiZSBjaGFpbmVkIHRvZ2V0aGVyOiAKYGBge3J9CmJhYnluYW1lcyAlPiUgZmlsdGVyKG5hbWU9PSJNaWNoYWVsIikgJT4lIHNlbGVjdCh5ZWFyLCBzZXgsIG5hbWUpICMgJT4lIHNvbWVfcGxvdF9mdW5jdGlvbigpCgpgYGAKV29ya3MgYmVzdCAKCi0gd2l0aCBvbmUgaW5wdXQsIG9uZSBvdXRwdXQKLSBub3QgdG9vIG1hbnkgc3RlcHMgKDwxMCkKLSBOb3RpY2UgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgcGlwZTogYGEgJT4lIGJgICJzZW5kcyIgYSB0byBiLCBhbmQgdGhlbiB0aGUgc3RhdGVtZW50IHJldHVybnMgc29tZXRoaW5nLCB3aGljaCBjYW4gYmUgc2VudCBhbG9uZyB0byB0aGUgbmV4dCB0aGluZyBgYSAlPiUgYiAlPiUgY2AKLSBUaGUgdGhpbmcgdGhhdCB5b3UncmUgcGlwaW5nIGluIGlzIHRoZSBmaXJzdCwgZGVmYXVsdCBhcmd1bWVudCBvZiB0aGUgZnVuY3Rpb24uIFRpZHl2ZXJzZSBmdW5jdGlvbnMgbWFyayB0aGlzIGluIHRoZSBoZWxwIGZpbGVzIHdpdGggYSBsZWFkaW5nIGRvdCwgZS5nLiBgLmRhdGFgIGluIGBoZWxwKGZpbHRlcilgCi0gQ2hhaW5pbmcgcGlwZXMgdG9nZXRoZXIKCi0gKipUT0RPKiogQ2xhc3MgdGltZSB0byBleHBlcmltZW50CgojIyMgQXNzaWduaW5nIHBpcGVkIGRhdGEKClRoZSBmaW5hbCByZXN1bHRzIG9mIHBpcGVzIGNhbiBiZSBhc3NpZ25lZCB0byB2YXJpYWJsZXMgYXMgbm9ybWFsIG9mIGNvdXJzZQpgYGB7cn0KbWljaGFlbCA8LSBiYWJ5bmFtZXMgJT4lIGZpbHRlcihuYW1lPT0iTWljaGFlbCIpCmBgYAoKVGhlcmUncyBhbHNvIGEgcmlnaHQgYXJyb3cgYC0+YCB2ZXJzaW9uIG9mIHRoZSBhc3NpZ25tZW50IG9wZXJhdG9yIGA8LWAKYGBge3J9CnggPC0gNAojIGlzIHRoZSBzYW1lIGFzIAo0IC0+IHgKYGBgCi0gVGhpcyBpcyBjb252ZW5pZW50IG9uIHRoZSBjb25zb2xlIHNvbWV0aW1lcywgd2hlbiB5b3Ugd2FudCB0byByZXVzZSBzb21ldGhpbmcgZnJvbSB5b3VyIGhpc3RvcnkgYW5kIGFzc2lnbiBpdCB0byBhIHZhcmlhYmxlCi0gSXQncyBnZW5lcmFsbHkgZGlzY291cmFnZWQgb3RoZXJ3aXNlCi0gQnV0IGl0IGRvZXMgbWFrZSBuaWNlIGxvZ2ljYWwgc2Vuc2Ugd2l0aCBwaXBlLXNlcXVlbmNlcwoKYGBge3J9CiNtaWNoYWVsIDwtIGJhYnluYW1lcyAlPiUgZmlsdGVyKG5hbWU9PSJNaWNoYWVsIikKYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ik1pY2hhZWwiKSAtPiBtaWNoYWVsCm1pY2hhZWwKYGBgCmBgYApkYXRhICU+JSBhKCkgJT4lIGIoKSAtPiByZXN1bHQKYGBgCiAgQ29tcGFyZSB0aGUgIm5vcm1hbCIgd2F5OgpgYGAKcmVzdWx0IDwtIGRhdGEgJT4lIGEoKSAlPiUgYigpCmBgYAojIyMgc29ydGluZyBjb2x1bW5zIHdpdGggYXJyYW5nZQoKYGRlc2NgIG1lYW5zIGRlc2NlbmRpbmcKCmBgYHtyfQojIFdoZW4gd2FzICJYYXZpZXIiIHBvcHVsYXI/CmJhYnluYW1lcyAlPiUgZmlsdGVyKG5hbWU9PSJYYXZpZXIiKSAlPiUgYXJyYW5nZShkZXNjKG4pKQpgYGAKCiMjIyBSZW5hbWluZyBjb2x1bW5zCmBgYHtyfQojIHJlbmFtZQptaWNoYWVsICU+JSByZW5hbWUocG9wdWxhcml0eT1wcm9wKQoKIyBzZWxlY3Qgd2l0aCByZW5hbWUKbWljaGFlbCAlPiUgc2VsZWN0KG5hbWUsIGdlbmRlcj1zZXgpCmBgYAoKIyMjIG11dGF0ZSgpIGFkZHMgY29sdW1ucwpgYGB7cn0KYmFieW5hbWVzICU+JSBtdXRhdGUobG9nX249bG9nMTAobikpICU+JSBzZWxlY3QoeWVhciwgc2V4LCBuYW1lLCBsb2dfbikKYGBgCmBgYHtyfQojIFJlbWVtYmVyIHRoZSBzeW50YXggZm9yIG1ha2luZyBhIHZlY3RvciAxIHRvIDEwOgoxOjEwCiMgVXNlIHRoaXMgdG8gYWRkIGEgInJhbmsiIGNvbHVtbgptaWNoYWVsICU+JSBtdXRhdGUocmFuaz0xOm5yb3cobWljaGFlbCkpCgojTk9URSBtb3JlIGVmZmVjaWVudCwgcm9idXN0IHdheSB0byBkbyB0aGlzOgptaWNoYWVsICU+JSBtdXRhdGUocmFuaz0xOm5yb3coLikpCiMgdGhpcyBpcyBiZXR0ZXIgYmVjYXVzZSB5b3UgY291bGQgc3Vic3RpdHV0ZSB0aGUgdGFidWxhciBkYXRhICJtaWNoYWVsIiB3aXRoIGFub3RoZXIgdGFibGUgd2l0aCBkaWZmZXJlbnQgbGVuZ3RoIGFuZCBpdCB3b3VsZCBzdGlsbCB3b3JrCmBgYAoKRG90ICIuIiBzdGFuZHMgZm9yICJ0aGUgdGhpbmcgdGhhdCB5b3UncmUgcGlwaW5nIGluIiAoZm9yIGNhc2VzIHdoZW4gaXQncyBub3QgdGhlIGZpcnN0IGFyZ3VtZW50KQpgYGB7cn0Kcm5vcm0oMTAwKSAlPiUgdGliYmxlKGlkPTE6MTAwLCBuPS4pCmBgYAoKY2YuIGFsc28gYC5kYXRhYCBpbiBkb2NzIChzZWUgZS5nLiBgaGVscChmaWx0ZXIpYCkKCiMjIGdncGxvdAoKLSBDYWxsaW5nIHRoZSBmdW5jdGlvbiBgZ2dwbG90YCBzdGFydHMgYXNzZW1ibGluZyB0aGUgZ3JhcGg7IGl0IGhhcyB0aGUgZGVmYXVsdCBhcmd1bWVudCBgZGF0YWAsIHdoaWNoIHlvdSBjYW4gcGlwZSB0byB0aGUgZnVuY3Rpb24KLSB0aGUgYGFlcygpYCAoImFlc3RoZXRpYyIpIGZ1bmN0aW9uIG1hcHMgZGF0YSBvbnRvIGdyYXBoIGF0dHJpYnV0ZXMKLSBZb3UgYnVpbGQgdXAgdGhlIHBsb3QgaW4gbGF5ZXJzIHVzaW5nIGArYAotIGdlb21ldGljIGxheWVycyBoYXZlIG5hbWVzIHN0YXJ0aW5nIHdpdGggYGdlb21fYC4gVGhlc2UgaW5jbHVkZSBgZ2VvbV9wb2ludGAgKHNjYXR0ZXJwbG90cyksIGBnZW9tX2JveGAgKGJveHBsb3RzKSwgYGdlb21faGlzdG9ncmFtYCAoaGlzdG9ncmFtcylgLCBhbmQgbWF5IG90aGVycy4gVGhlcmUgaXMgYSBkZWZhdWx0IHNldCB0aGF0IGl0IHBhcnQgb2YgdGlkeXZlcnNlLCBhbmQgdGhlbiBvdGhlcnMgY2FuIGJlIGFkZGVkIGJ5IGNhbGxpbmcgbGlicmFyaWVzLgotIFRoZXJlIGFyZSBsb3RzIG1vcmUgdGhpbmdzIHlvdSBjYW4gY2hhbmdlLCBidXQgdGhlc2UgdGhyZWUgc3RlcHMgYXJlIHRoZSBiYXNpYyBpZGVhOiB0YWtlIGRhdGEsIG1hcCB0byBhbiBhZXN0aGV0aWMsIGFuZCBwbG90IGFzIGEgZ2VvbWV0cmljIGxheWVyCgpgYGB7cn0KIyBnZW9tX3BvaW50KCkKYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ik1hcmlhIiwgc2V4PT0iRiIpICU+JSBnZ3Bsb3QoYWVzKHg9eWVhciwgeT1wcm9wKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKQojIGdlb21fY29sKCkKIyBnZW9tX2xpbmUoKQpgYGAKTnVtYmVycyBsaWtlIDEuNWUtMDUgYXJlIHNjaWVudGlmaWMgbm90YXRpb24sIHNob3J0aGFuZCBmb3IgIjEuNSB0aW1lcyAxMCB0byB0aGUgcG93ZXIgb2YgLTUiLCB3aGljaCBtZWFucyAwLjAwMDAxNQoKVG8gZGlzYWJsZSB0aGlzLCB1c2UgdGhlIGZvbGxvd2luZyBhdCB0aGUgc3RhcnQgb2YgeW91ciBub3RlYm9vazoKYGBge3J9Cm9wdGlvbnMoc2NpcGVuPTk5OSkgIyBkaXNhYmxlIHNjaWVudGlmaWMgbm90YXRpb24gKGkuZS4gMTAwMCA9PSAxZTA0KQpgYGAKCioqUHJldmlldyoqICh3ZSB3aWxsIGxvb2sgYXQgdGhpcyBuZXh0IHdlZWspOiB5b3UgY2FuIHNwZWNpZnkgb3RoZXIgZWxlbWVudHMgb2YgdGhlIHBsb3QgYWVzdGhldGljIHRvIGJlIGRldGVybWluZWQgYnkgdmFsdWVzIGluIHlvdXIgZGF0YS4gTGV0J3MganVzdCB1c2UgY29sb3VyIGZvciBub3c6CgpgYGB7cn0KYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ikxlc2xpZSIpICU+JSBnZ3Bsb3QoYWVzKHg9eWVhciwgeT1wcm9wLCBjb2xvdXI9c2V4KSkgKyBnZW9tX2xpbmUoKQpgYGAKYGBge3J9CiMgYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ik1hcmlhIikgJT4lIG11dGF0ZShsb2dfbj1sb2cxMChuKSkgJT4lIGdncGxvdChhZXMoeD15ZWFyLCB5PWxvZ19uLCBjb2xvdXI9c2V4KSkgKyBnZW9tX2xpbmUoKQpiYWJ5bmFtZXMgJT4lIGZpbHRlcihuYW1lPT0iTWFyaWEiKSAgJT4lIGdncGxvdChhZXMoeD15ZWFyLCB5PWxvZzEwKG4pLCBjb2xvdXI9c2V4KSkgKyBnZW9tX2xpbmUoKQpgYGAKCmBgYHtyfQpiYWJ5bmFtZXMgJT4lIGZpbHRlcihuYW1lPT0iTWFyaWEiKSAgJT4lIGdncGxvdChhZXMoeD15ZWFyLCB5PWxvZzEwKG4pLCBjb2xvdXI9c2V4KSkgKyBnZW9tX2NvbCgpCmBgYAoKIyBTb21lIHN0YXRpc3RpY2FsIGRpc3RyaWJ1dGlvbnMKCiMjIE5vcm1hbCBkaXN0cmlidXRpb24KCkdhbHRvbiBCb2FyZAoKPGlmcmFtZSB3aWR0aD0iODU0IiBoZWlnaHQ9IjQ4MCIgc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC80SHB2QlpuSE9WSSIgZnJhbWVib3JkZXI9IjAiIGFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgpJbiBhIG5vcm1hbCBkaXN0cmlidXRpb246Ci0gNjguMiUgb2YgdmFsdWVzIHdpdGhpbiBvbmUgc3RhbmRhcmQgZGV2aWF0aW9uCi0gOTUuNCUgd2l0aGluIHR3byBzdGFuZGFyZCBkZXZpYXRpb25zCi0gOTkuNyUgd2l0aGluIDMKLSA5OS45OSUgd2l0aGluIDQKCiFbU3RhbmRhcmQgZGV2aWF0aW9uc10oU3RhbmRhcmRfZGV2aWF0aW9uX2RpYWdyYW0uc3ZnLnBuZykKCk5vcm1hbCBkaXN0cmlidXRpb25zIGNhbiBiZSBkZXNjcmliZWQgYnkgdHdvIHBhcmFtZXRlcnMsIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbi4gVGhlIGBybm9ybSgpYCBmdW5jdGlvbiBnZW5lcmF0ZXMgdmVjdG9ycyBvZiByYW5kb20gbnVtYmVycyBhY2NvcmRpbmduIHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KCioqVE9ETyoqIFJlYWQgdGhlIGhlbHAgZm9yIHRoZSBgcm5vcm0oKWAgZnVuY3Rpb24uIEdlbmVyYXRlIHNvbWUgdmVjdG9ycyBvZiBub3JtYWxseSBkaXN0cmlidXRlZCByYW5kb20gbnVtYmVycyBnaXZlbiBkaWZmZXJlbnQgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMuCgojIyBIaXN0b2dyYW0KCi0gcm5vcm0oTiwgbWVhbiwgc2QpCgpIZXJlJ3MgaG93IHlvdSBjYW4gdmlzdWFsaXNlIHRoZXNlOgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkgIyBzaG91bGQgZG8gdGhpcyBhdCB0aGUgYmVnaW5uaW5nCm15LmRhdGEgPC0gdGliYmxlKHZhbHVlcz1ybm9ybSgxMDAsIDEwLCAyLjUpKQpteS5kYXRhICU+JSBnZ3Bsb3QoYWVzKHg9dmFsdWVzKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0xKQpgYGAKCkEgc21hbGwgc2FtcGxlIHdpbGwgYmUgamFnZ2VkLCBidXQgdGhlIGxhcmdlciB0aGUgc2FtcGxlIHRoZSBzbW9vdGhlciBpdCBnZXRzOgpgYGB7cn0KdGliYmxlKHZhbHVlcz1ybm9ybSgxMDAwMCwgMTAsIDIuNSkpICU+JSBnZ3Bsb3QoYWVzKHg9dmFsdWVzKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0xKQpgYGAKCiMjIFVuaWZvcm0gZGlzdHJpYnV0aW9uClRoZXJlIGFyZSBtYW55IGtpbmRzIG9mIGRpc3RyaWJ1dGlvbnMuCgotIHJ1bmlmKE4sIG1pbiwgbWF4KQoKSW4gdGhlICpVbmlmb3JtIGRpc3RyaWJ1dGlvbiogdGhlcmUgaXMgYW4gZXF1YWwgY2hhbmNlIG9mIGdldHRpbmcgYW55IHZhbHVlIGJldHdlZW4gdGhlIG1pbmltdW0gYW5kIHRoZSBtYXhpbXVtCmBgYHtyfQpteS5kYXRhIDwtIHRpYmJsZSh2YWx1ZXM9cnVuaWYoMTAwMCwgbWluPTUsIG1heD05KSkKI3FwbG90KHZhbHVlcywgZGF0YT1teS5kYXRhLCBnZW9tPSJoaXN0b2dyYW0iLCBicmVha3M9MToxMCkKbXkuZGF0YSAlPiUgZ2dwbG90KGFlcyh4PXZhbHVlcykpICsgZ2VvbV9oaXN0b2dyYW0oYnJlYWtzPTE6MTApCmBgYAo=