House buying
r
r a <- 1 b <- NA is.na(a)
[1] FALSE
r
r is.na(b)
[1] TRUE
r
r 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
r
r monthly.cost(2970000, 3210)
[1] 11594
Tidyverse vs. base R
The read_csv is the tidyverse version of read.csv.
We’re working in the tidyverse library(tidyverse)
at the beginning of every script!
r
r # 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
r
r m[1,1] # a cell
[1] 1
r
r class(m[1,]) # a vector
[1] \integer\
r
r m[1,1] # a cell
[1] 1
r
r 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.
r
r 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)
r
r 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:
r
r 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
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 <-
r
r 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
r
r rnorm(100) %>% tibble(id=1:100, n=.)
Renaming columns
r
r # geom_col() # geom_line()
mutate() adds columns
r
r 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:
r
r 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:
r
r tibble(values=rnorm(10000, 10, 2.5)) %>% ggplot(aes(x=values)) + geom_histogram(binwidth=1)
r
r toy.data <- tibble(rank=1:10) toy.data\(freq <- 1 / toy.data\) rank toy.data
Some statistical distributions
Normal distribution
Galton Board
VIDEO
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
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
Here’s how you can visualise these:
r
r 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:
r
r toy.data %>% ggplot(aes(x=log10(rank), y=log10(freq))) + geom_point() + geom_line()
LS0tCnRpdGxlOiAiVmlzdWFsaXNhdGlvbiBhbmQgc3RhdGlzdGljYWwgYW5hbHlzaXMiCmF1dGhvcjogIk1pY2hhZWwgRHVubiwgRGVwdC4gb2YgTGluZ3Vpc3RpY3MgYW5kIFBoaWxvbG9neSwgVXBwc2FsYSBVbml2ZXJzaXR5IgpkYXRlOiAiU2Vzc2lvbiAzLCAyMDE4LTEwLTA4IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBlY2hvPUZBTFNFfQpvcHRpb25zKHNjaXBlbj05OTkpICMgZGlzYWJsZSBzY2llbnRpZmljIG5vdGF0aW9uIChpLmUuIDEwMDAgPT0gMWUwNCkKYGBgCgpUb3BpY3MKCi0gSG9tZXdvcmsKICAqIHdyaXRpbmcgYSBmdW5jdGlvbgogICogaW1wb3J0aW5nIHRoZSBLZWxseSBkYXRhCi0gR2V0dGluZyB0aGUgcGFydHMgb2YgeW91ciBkYXRhIHlvdSBhcmUgaW50ZXJlc3RlZCBpbjoKICAqIGZpbHRlcigpCiAgKiBzZWxlY3QoKQotIFNvcnRpbmcsIHJlbmFtaW5nLCBhbmQgbXV0YXRpbmcgKGFkZGluZykKLSBQbG90dGluZyBzaW1wbGUgdGFidWxhciBkYXRhCi0gRGlzdHJpYnV0aW9ucyBhbmQgaGlzdG9ncmFtcwogICogcm5vcm0KICAqIHJ1bmlmCi0gbG9nIHZhbHVlcwotIFppcGYgZGlzdHJpYnV0aW9uCgojIyBIb3VzZSBidXlpbmcKCmBgYHtyfQphIDwtIDEKYiA8LSBOQQppcy5uYShhKQppcy5uYShiKQpgYGAKCgpgYGB7cn0KbW9udGhseS5jb3N0IDwtIGZ1bmN0aW9uKGNvc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgZmVlLCAKICAgICAgICAgICAgICAgICAgICAgICAgIG9wZXJhdGluZz1OQSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkZXBvc2l0PU5BLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyZXN0PTAuMDE3LCAKICAgICAgICAgICAgICAgICAgICAgICAgIGFtb3J0aXphdGlvbj0wLjAyLAogICAgICAgICAgICAgICAgICAgICAgICAgbi5yZXNpZGVudHM9Mil7CiAgaWYgKGlzLm5hKGRlcG9zaXQpKXsgZGVwb3NpdCA8LSBjb3N0ICogMC4xNX0KICBpZiAoaXMubmEob3BlcmF0aW5nKSkge29wZXJhdGluZyA8LSAzMDAgKiBuLnJlc2lkZW50c30KICBsb2FuIDwtIGNvc3QgLSBkZXBvc2l0CiAgaW50ZXJlc3QgPC0gKGxvYW4gKiAoaW50ZXJlc3QgKyBhbW9ydGl6YXRpb24pKSAvIDEyCiAgaW50ZXJlc3QgKyBmZWUgKyBvcGVyYXRpbmcKfQoKbW9udGhseS5jb3N0KDQ0OTAwMDAsIDQ2OTUsIDE3NDAwLzEyKQptb250aGx5LmNvc3QoMjk3MDAwMCwgMzIxMCkKYGBgCgojIFRpZHl2ZXJzZSB2cy4gYmFzZSBSCgotIFRoZSByZWFkX2NzdiBpcyB0aGUgdGlkeXZlcnNlIHZlcnNpb24gb2YgcmVhZC5jc3YuIAotIFdlJ3JlIHdvcmtpbmcgaW4gdGhlIHRpZHl2ZXJzZSBgbGlicmFyeSh0aWR5dmVyc2UpYCBhdCB0aGUgYmVnaW5uaW5nIG9mIGV2ZXJ5IHNjcmlwdCEKCmBgYHtyfQojIEJhc2UgUgoKbSA8LSBtYXRyaXgoMTo5LCBucm93PTMpCm0gIyBhIG1hdHJpeApgYGAKYGBge3J9Cm1bMSwxXSAjIGEgY2VsbApgYGAKYGBge3J9Cm1bMSxdICMgYSB2ZWN0b3IKYGBgCgojIyBQcmVsaW1pbmFyaWVzCgotIFBsZWFzZSBpbnN0YWxsIHRoZSBgYmFieW5hbWVzYCBwYWNrYWdlLiBBbGwgbG9hZGluZyB0aGlzIHBhY2thZ2UgZG9lcyBpcyBnaXZlIHlvdSBvbmUgYmlnIHRpYmJsZSBjYWxsZWQgYGJhYnluYW1lc2Agd2l0aCBzb21lIGludGVyZXN0aW5nIHNhbXBsZSBkYXRhIGZvciB1cyB0byBwbGF5IHdpdGgKLSBUbyBpbnN0YWxsIHRoZSBwYWNrYWdlIHVzZSBSU3R1ZGlvICJUb29scyIgLT4gIkluc3RhbGwgcGFja2FnZXMuLi4iCgpJdCdzIGdvb2Qgc3R5bGUgdG8gZG8gYWxsIHlvdXIgbGlicmFyeSBmdW5jdGlvbiBjYWxscyBhdCB0aGUgYmVnaW5uaW5nIG9mIHlvdXIgc2NyaXB0cywgbm90ZWJvb2tzLCBldGMuIEZvciBleGFtcGxlLCB0aWR5dmVyc2UgcmVkZWZpbmVzIGBmaWx0ZXJgLCBhbmQgeW91IGRvbid0IHdhbnQgYGZpbHRlcmAgdG8gbWVhbiBvbmUgdGhpbmcgZm9yIG9uZSBoYWxmIG9mIHlvdXIgc2NyaXB0IGFuZCBzb21ldGhpbmcgZWxzZSBmb3IgdGhlIG90aGVyLiBJdCBhbHNvIG1lYW5zIHRoYXQgaWYgeW91IGN1dC1hbmQtcGFzdGUgc29tZXRoaW5nIHlvdSBrbm93IHdoZXJlIHRvIGxvb2sgZm9yIGFueSBsaWJyYXJpZXMgaXQgbWlnaHQgZGVwZW5kIG9uLgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoYmFieW5hbWVzKSAKYGBgCi0gbG9hZGluZyBiYWJ5bmFtZXMgZ2l2ZXMgeW91IGFjY2VzcyB0byBhIGh1Z2UgdGliYmxlICh0YWJsZSBvZiB0ZXh0IGFuZCBudW1lcmljYWwgZGF0YSkgY2FsbGVkIGBiYWJ5bmFtZXNgCi0gWW91IGNhbiBlbnRlciBgaGVscChiYWJ5bmFtZXMpYCBpbiB0aGUgY29uc29sZSB0byBnZXQgYSBkZXNjcmlwdGlvbiBvZiB0aGUgZGF0YSAoU1NBIGlzIHRoZSBVUyBTb2NpYWwgU2VjdXJpdHkgQWRtaW5pc3RyYXRpb24pLiBOZXh0IHdlZWsgd2UnbGwgbG9vayBhdCBTd2VkaXNoIG5hbWVzIGluc3RlYWQhCgpMb25nIGRhdGE6IGV2ZXJ5IG9ic2VydmF0aW9uIGlzIGl0cyBvd24gcm93LiBOZXh0IHdlZWsgd2UnbGwgbG9vayBhdCBTd2VkaXNoIG5hbWUgZGF0YSBmcm9tIFN0YXRpc3Rpc2thIENlbnRyYWxieXLDpW4sIHdoaWNoIGlzIGluICJ3aWRlIiBmb3JtYXQgKG11bHRpcGxlIG9ic2VydmF0aW9ucyBwZXIgcm93KQpgYGB7cn0KaGVhZChiYWJ5bmFtZXMpCmBgYAoKIyMgRmlyc3Qgc3RlcHMgd2l0aCBkcGx5ciAocGFydCBvZiB0aWR5dmVyc2UpCgpEcGx5ciBhaW1zIHRvIHByb3ZpZGUgYSBmdW5jdGlvbiBmb3IgZWFjaCBiYXNpYyB2ZXJiIG9mIGRhdGEgbWFuaXB1bGF0aW9uLiBUaGVzZSBpbmNsdWRlOgoKICAgIC0gZmlsdGVyKCkgdG8gc2VsZWN0IGNhc2VzIGJhc2VkIG9uIHRoZWlyIHZhbHVlcy4KICAgIC0gYXJyYW5nZSgpIHRvIHJlb3JkZXIgdGhlIGNhc2VzLgogICAgLSBzZWxlY3QoKSBhbmQgcmVuYW1lKCkgdG8gc2VsZWN0IHZhcmlhYmxlcyBiYXNlZCBvbiB0aGVpciBuYW1lcy4KICAgIC0gbXV0YXRlKCkgYW5kIHRyYW5zbXV0ZSgpIHRvIGFkZCBuZXcgdmFyaWFibGVzIHRoYXQgYXJlIGZ1bmN0aW9ucyBvZiBleGlzdGluZyB2YXJpYWJsZXMuCgpUaGUgZHBseXIgdmVyYnM6IGZpbHRlciwgc2VsZWN0OgoKRmlsdGVyaW5nIHJvd3M6CmBgYHtyfQojIHRoZSBmaWx0ZXIgZnVuY3Rpb24gaXMgYXdhcmUgb2YgdGhlIG5hbWVzIG9mIHRoZSBjb2x1bW5zIGluIHRoZSB0YWJsZQpmaWx0ZXIoYmFieW5hbWVzLCBuYW1lPT0iTWljaGFlbCIsIHNleD09IkYiKQpgYGAKYGBge3J9CmZpbHRlcihiYWJ5bmFtZXMsIG5hbWU9PSJMZW5hIiwgeWVhcj09MjAwMCkKYGBgClVzZSB8IGZvciAib3IiCmBgYHtyfQpmaWx0ZXIoYmFieW5hbWVzLCBuYW1lPT0iUmltYSIgfCBuYW1lPT0iTWFqYSIsIHllYXIgPiAxOTU5LCB5ZWFyIDwgMTk2NikKYGBgCgotIGBmaWx0ZXIoYSwgYilgIGlzIHRoZSBzYW1lIGFzIHRoZSAiYW5kIiByZWxhdGlvbnNoaXAgYGZpbHRlcihhICYgYilgOyBjZi4gIm9yIiBgZmlsdGVyKGEgfCBiKWAKCmBgYHtyfQpmaWx0ZXIoYmFieW5hbWVzLCBuYW1lPT0iWGF2aWVyIiB8IG5hbWUgPT0iQW5hc3Rhc2lhIikKYGBgCgpTZWxlY3RpbmcgY29sdW1uczoKYGBge3J9CnNlbGVjdChiYWJ5bmFtZXMsIHllYXIsIG5hbWUsIG4pCmBgYAoKIyMgUGlwaW5nICU+JQoKYGZ1bmN0KGEsIGIpYCBpcyB0aGUgc2FtZSBhcyBgYSAlPiUgZnVuY3QoYilgCgpgYGB7cn0KYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09IkxlbmEiLCB5ZWFyPT0yMDAwKQpgYGAKClRoaXMgY2FuIHNpbXBsaWZ5IHRoaW5nczoKCmBgYHtyfQpiYWJ5bmFtZXMgJT4lIGZpbHRlcihuYW1lPT0iTWljaGFlbCIpICU+JSBmaWx0ZXIoeWVhciA8PSAxOTAwKSAlPiUgZmlsdGVyKHNleD09IkYiKQpgYGAKCmh0dHA6Ly9yNGRzLmhhZC5jby5uei9waXBlcy5odG1sCgpGdW5jdGlvbnMgYXJlIHZlcmJzLCBhcmd1bWVudHMgYXJlIG5vdW5zCgpIb3cgdG8gZGVhbCB3aXRoIG11bHRpcGxlIHN0ZXBzIG9mIGFuIGFuYWx5c2lzCgotIHNhdmUgaW50ZXJtZWRpYXRlIHN0ZXBzIChjbHV0dGVycyB0aGUgbmFtZXNwYWNlLCBsb3RzIG9mIG1lbW9yeSkKCmBgYHtyfQptaWNoYWVsMCA8LSBmaWx0ZXIoYmFieW5hbWVzLCBuYW1lPT0iTWljaGFlbCIpCm1pY2hhZWwxIDwtIHNlbGVjdChtaWNoYWVsMCwgbmFtZSwgbiwgeWVhcikKYGBgCi0gb3ZlcndyaXRlIHRoZSBvcmlnaW5hbCAoaGFyZCB0byBkZWJ1ZykKYGBge3J9Cm1pY2hhZWwgPC0gZmlsdGVyKGJhYnluYW1lcywgbmFtZT09Ik1pY2hhZWwiKQptaWNoYWVsIDwtIHNlbGVjdChtaWNoYWVsLCBuYW1lLCBuLCB5ZWFyKQpgYGAKLSBuZXN0ZWQgZnVuY3Rpb25zIChoYXZlIHRvIHJlYWQgaW4gaW5zaWRlLW91dCBvcmRlciwgYXJndW1lbnRzIGFyZSBzcHJlYWQgb3V0KQpgYGB7cn0KbWljaGFlbCA8LSBzZWxlY3QoCiAgZmlsdGVyKGJhYnluYW1lcywgbmFtZT09Ik1pY2hhZWwiKSwgCiAgbmFtZSwgbiwgeWVhcgopCmBgYAoKLSB0aGUgcGlwZSBzeW50YXggKHRoZSBodW1hbiB3YXkhKQpgYGB7cn0KYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ik1pY2hhZWwiKQojIFNBTUUgQVMgZmlsdGVyKGJhYnluYW1lcywgbmFtZT09Ik1pY2hhZWwiKQpgYGAKCi0gcGlwZWQgZnVuY3Rpb25zIGNhbiBiZSBjaGFpbmVkIHRvZ2V0aGVyOiAKYGBge3J9CmJhYnluYW1lcyAlPiUgZmlsdGVyKG5hbWU9PSJNaWNoYWVsIikgJT4lIHNlbGVjdCh5ZWFyLCBzZXgsIG5hbWUpICMgJT4lIHNvbWVfcGxvdF9mdW5jdGlvbigpCgpgYGAKV29ya3MgYmVzdCAKCi0gd2l0aCBvbmUgaW5wdXQsIG9uZSBvdXRwdXQKLSBub3QgdG9vIG1hbnkgc3RlcHMgKDwxMCkKLSBOb3RpY2UgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgcGlwZTogYGEgJT4lIGJgICJzZW5kcyIgYSB0byBiLCBhbmQgdGhlbiB0aGUgc3RhdGVtZW50IHJldHVybnMgc29tZXRoaW5nLCB3aGljaCBjYW4gYmUgc2VudCBhbG9uZyB0byB0aGUgbmV4dCB0aGluZyBgYSAlPiUgYiAlPiUgY2AKLSBUaGUgdGhpbmcgdGhhdCB5b3UncmUgcGlwaW5nIGluIGlzIHRoZSBmaXJzdCwgZGVmYXVsdCBhcmd1bWVudCBvZiB0aGUgZnVuY3Rpb24uIFRpZHl2ZXJzZSBmdW5jdGlvbnMgbWFyayB0aGlzIGluIHRoZSBoZWxwIGZpbGVzIHdpdGggYSBsZWFkaW5nIGRvdCwgZS5nLiBgLmRhdGFgIGluIGBoZWxwKGZpbHRlcilgCi0gQ2hhaW5pbmcgcGlwZXMgdG9nZXRoZXIKCi0gKipUT0RPKiogQ2xhc3MgdGltZSB0byBleHBlcmltZW50CgojIyMgQXNzaWduaW5nIHBpcGVkIGRhdGEKClRoZSBmaW5hbCByZXN1bHRzIG9mIHBpcGVzIGNhbiBiZSBhc3NpZ25lZCB0byB2YXJpYWJsZXMgYXMgbm9ybWFsIG9mIGNvdXJzZQpgYGB7cn0KbWljaGFlbCA8LSBiYWJ5bmFtZXMgJT4lIGZpbHRlcihuYW1lPT0iTWljaGFlbCIpCmBgYAoKVGhlcmUncyBhbHNvIGEgcmlnaHQgYXJyb3cgYC0+YCB2ZXJzaW9uIG9mIHRoZSBhc3NpZ25tZW50IG9wZXJhdG9yIGA8LWAKYGBge3J9CnggPC0gNAojIGlzIHRoZSBzYW1lIGFzIAo0IC0+IHgKYGBgCi0gVGhpcyBpcyBjb252ZW5pZW50IG9uIHRoZSBjb25zb2xlIHNvbWV0aW1lcywgd2hlbiB5b3Ugd2FudCB0byByZXVzZSBzb21ldGhpbmcgZnJvbSB5b3VyIGhpc3RvcnkgYW5kIGFzc2lnbiBpdCB0byBhIHZhcmlhYmxlCi0gSXQncyBnZW5lcmFsbHkgZGlzY291cmFnZWQgb3RoZXJ3aXNlCi0gQnV0IGl0IGRvZXMgbWFrZSBuaWNlIGxvZ2ljYWwgc2Vuc2Ugd2l0aCBwaXBlLXNlcXVlbmNlcwoKYGBge3J9CiNtaWNoYWVsIDwtIGJhYnluYW1lcyAlPiUgZmlsdGVyKG5hbWU9PSJNaWNoYWVsIikKYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ik1pY2hhZWwiKSAtPiBtaWNoYWVsCm1pY2hhZWwKYGBgCmBgYApkYXRhICU+JSBhKCkgJT4lIGIoKSAtPiByZXN1bHQKYGBgCiAgQ29tcGFyZSB0aGUgIm5vcm1hbCIgd2F5OgpgYGAKcmVzdWx0IDwtIGRhdGEgJT4lIGEoKSAlPiUgYigpCmBgYAojIyMgc29ydGluZyBjb2x1bW5zIHdpdGggYXJyYW5nZQoKYGRlc2NgIG1lYW5zIGRlc2NlbmRpbmcKCmBgYHtyfQojIFdoZW4gd2FzICJYYXZpZXIiIHBvcHVsYXI/CmJhYnluYW1lcyAlPiUgZmlsdGVyKG5hbWU9PSJYYXZpZXIiKSAlPiUgYXJyYW5nZShkZXNjKG4pKQpgYGAKCiMjIyBSZW5hbWluZyBjb2x1bW5zCmBgYHtyfQojIHJlbmFtZQptaWNoYWVsICU+JSByZW5hbWUocG9wdWxhcml0eT1wcm9wKQoKIyBzZWxlY3Qgd2l0aCByZW5hbWUKbWljaGFlbCAlPiUgc2VsZWN0KG5hbWUsIGdlbmRlcj1zZXgpCmBgYAoKIyMjIG11dGF0ZSgpIGFkZHMgY29sdW1ucwpgYGB7cn0KYmFieW5hbWVzICU+JSBtdXRhdGUobG9nX249bG9nMTAobikpICU+JSBzZWxlY3QoeWVhciwgc2V4LCBuYW1lLCBsb2dfbikKYGBgCmBgYHtyfQojIFJlbWVtYmVyIHRoZSBzeW50YXggZm9yIG1ha2luZyBhIHZlY3RvciAxIHRvIDEwOgoxOjEwCiMgVXNlIHRoaXMgdG8gYWRkIGEgInJhbmsiIGNvbHVtbgptaWNoYWVsICU+JSBtdXRhdGUocmFuaz0xOm5yb3cobWljaGFlbCkpCgojTk9URSBtb3JlIGVmZmVjaWVudCwgcm9idXN0IHdheSB0byBkbyB0aGlzOgptaWNoYWVsICU+JSBtdXRhdGUocmFuaz0xOm5yb3coLikpCiMgdGhpcyBpcyBiZXR0ZXIgYmVjYXVzZSB5b3UgY291bGQgc3Vic3RpdHV0ZSB0aGUgdGFidWxhciBkYXRhICJtaWNoYWVsIiB3aXRoIGFub3RoZXIgdGFibGUgd2l0aCBkaWZmZXJlbnQgbGVuZ3RoIGFuZCBpdCB3b3VsZCBzdGlsbCB3b3JrCmBgYAoKRG90ICIuIiBzdGFuZHMgZm9yICJ0aGUgdGhpbmcgdGhhdCB5b3UncmUgcGlwaW5nIGluIiAoZm9yIGNhc2VzIHdoZW4gaXQncyBub3QgdGhlIGZpcnN0IGFyZ3VtZW50KQpgYGB7cn0Kcm5vcm0oMTAwKSAlPiUgdGliYmxlKGlkPTE6MTAwLCBuPS4pCmBgYAoKY2YuIGFsc28gYC5kYXRhYCBpbiBkb2NzIChzZWUgZS5nLiBgaGVscChmaWx0ZXIpYCkKCiMjIGdncGxvdAoKLSBDYWxsaW5nIHRoZSBmdW5jdGlvbiBgZ2dwbG90YCBzdGFydHMgYXNzZW1ibGluZyB0aGUgZ3JhcGg7IGl0IGhhcyB0aGUgZGVmYXVsdCBhcmd1bWVudCBgZGF0YWAsIHdoaWNoIHlvdSBjYW4gcGlwZSB0byB0aGUgZnVuY3Rpb24KLSB0aGUgYGFlcygpYCAoImFlc3RoZXRpYyIpIGZ1bmN0aW9uIG1hcHMgZGF0YSBvbnRvIGdyYXBoIGF0dHJpYnV0ZXMKLSBZb3UgYnVpbGQgdXAgdGhlIHBsb3QgaW4gbGF5ZXJzIHVzaW5nIGArYAotIGdlb21ldGljIGxheWVycyBoYXZlIG5hbWVzIHN0YXJ0aW5nIHdpdGggYGdlb21fYC4gVGhlc2UgaW5jbHVkZSBgZ2VvbV9wb2ludGAgKHNjYXR0ZXJwbG90cyksIGBnZW9tX2JveGAgKGJveHBsb3RzKSwgYGdlb21faGlzdG9ncmFtYCAoaGlzdG9ncmFtcylgLCBhbmQgbWF5IG90aGVycy4gVGhlcmUgaXMgYSBkZWZhdWx0IHNldCB0aGF0IGl0IHBhcnQgb2YgdGlkeXZlcnNlLCBhbmQgdGhlbiBvdGhlcnMgY2FuIGJlIGFkZGVkIGJ5IGNhbGxpbmcgbGlicmFyaWVzLgotIFRoZXJlIGFyZSBsb3RzIG1vcmUgdGhpbmdzIHlvdSBjYW4gY2hhbmdlLCBidXQgdGhlc2UgdGhyZWUgc3RlcHMgYXJlIHRoZSBiYXNpYyBpZGVhOiB0YWtlIGRhdGEsIG1hcCB0byBhbiBhZXN0aGV0aWMsIGFuZCBwbG90IGFzIGEgZ2VvbWV0cmljIGxheWVyCgpgYGB7cn0KIyBnZW9tX3BvaW50KCkKYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ik1hcmlhIiwgc2V4PT0iRiIpICU+JSBnZ3Bsb3QoYWVzKHg9eWVhciwgeT1wcm9wKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKQojIGdlb21fY29sKCkKIyBnZW9tX2xpbmUoKQpgYGAKTnVtYmVycyBsaWtlIDEuNWUtMDUgYXJlIHNjaWVudGlmaWMgbm90YXRpb24sIHNob3J0aGFuZCBmb3IgIjEuNSB0aW1lcyAxMCB0byB0aGUgcG93ZXIgb2YgLTUiLCB3aGljaCBtZWFucyAwLjAwMDAxNQoKVG8gZGlzYWJsZSB0aGlzLCB1c2UgdGhlIGZvbGxvd2luZyBhdCB0aGUgc3RhcnQgb2YgeW91ciBub3RlYm9vazoKYGBge3J9Cm9wdGlvbnMoc2NpcGVuPTk5OSkgIyBkaXNhYmxlIHNjaWVudGlmaWMgbm90YXRpb24gKGkuZS4gMTAwMCA9PSAxZTA0KQpgYGAKCioqUHJldmlldyoqICh3ZSB3aWxsIGxvb2sgYXQgdGhpcyBuZXh0IHdlZWspOiB5b3UgY2FuIHNwZWNpZnkgb3RoZXIgZWxlbWVudHMgb2YgdGhlIHBsb3QgYWVzdGhldGljIHRvIGJlIGRldGVybWluZWQgYnkgdmFsdWVzIGluIHlvdXIgZGF0YS4gTGV0J3MganVzdCB1c2UgY29sb3VyIGZvciBub3c6CgpgYGB7cn0KYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ikxlc2xpZSIpICU+JSBnZ3Bsb3QoYWVzKHg9eWVhciwgeT1wcm9wLCBjb2xvdXI9c2V4KSkgKyBnZW9tX2xpbmUoKQpgYGAKYGBge3J9CiMgYmFieW5hbWVzICU+JSBmaWx0ZXIobmFtZT09Ik1hcmlhIikgJT4lIG11dGF0ZShsb2dfbj1sb2cxMChuKSkgJT4lIGdncGxvdChhZXMoeD15ZWFyLCB5PWxvZ19uLCBjb2xvdXI9c2V4KSkgKyBnZW9tX2xpbmUoKQpiYWJ5bmFtZXMgJT4lIGZpbHRlcihuYW1lPT0iTWFyaWEiKSAgJT4lIGdncGxvdChhZXMoeD15ZWFyLCB5PWxvZzEwKG4pLCBjb2xvdXI9c2V4KSkgKyBnZW9tX2xpbmUoKQpgYGAKCmBgYHtyfQpiYWJ5bmFtZXMgJT4lIGZpbHRlcihuYW1lPT0iTWFyaWEiKSAgJT4lIGdncGxvdChhZXMoeD15ZWFyLCB5PWxvZzEwKG4pLCBjb2xvdXI9c2V4KSkgKyBnZW9tX2NvbCgpCmBgYAoKIyBTb21lIHN0YXRpc3RpY2FsIGRpc3RyaWJ1dGlvbnMKCiMjIE5vcm1hbCBkaXN0cmlidXRpb24KCkdhbHRvbiBCb2FyZAoKPGlmcmFtZSB3aWR0aD0iODU0IiBoZWlnaHQ9IjQ4MCIgc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC80SHB2QlpuSE9WSSIgZnJhbWVib3JkZXI9IjAiIGFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgpJbiBhIG5vcm1hbCBkaXN0cmlidXRpb246Ci0gNjguMiUgb2YgdmFsdWVzIHdpdGhpbiBvbmUgc3RhbmRhcmQgZGV2aWF0aW9uCi0gOTUuNCUgd2l0aGluIHR3byBzdGFuZGFyZCBkZXZpYXRpb25zCi0gOTkuNyUgd2l0aGluIDMKLSA5OS45OSUgd2l0aGluIDQKCiFbU3RhbmRhcmQgZGV2aWF0aW9uc10oU3RhbmRhcmRfZGV2aWF0aW9uX2RpYWdyYW0uc3ZnLnBuZykKCk5vcm1hbCBkaXN0cmlidXRpb25zIGNhbiBiZSBkZXNjcmliZWQgYnkgdHdvIHBhcmFtZXRlcnMsIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbi4gVGhlIGBybm9ybSgpYCBmdW5jdGlvbiBnZW5lcmF0ZXMgdmVjdG9ycyBvZiByYW5kb20gbnVtYmVycyBhY2NvcmRpbmduIHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KCioqVE9ETyoqIFJlYWQgdGhlIGhlbHAgZm9yIHRoZSBgcm5vcm0oKWAgZnVuY3Rpb24uIEdlbmVyYXRlIHNvbWUgdmVjdG9ycyBvZiBub3JtYWxseSBkaXN0cmlidXRlZCByYW5kb20gbnVtYmVycyBnaXZlbiBkaWZmZXJlbnQgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMuCgojIyBIaXN0b2dyYW0KCi0gcm5vcm0oTiwgbWVhbiwgc2QpCgpIZXJlJ3MgaG93IHlvdSBjYW4gdmlzdWFsaXNlIHRoZXNlOgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkgIyBzaG91bGQgZG8gdGhpcyBhdCB0aGUgYmVnaW5uaW5nCm15LmRhdGEgPC0gdGliYmxlKHZhbHVlcz1ybm9ybSgxMDAsIDEwLCAyLjUpKQpteS5kYXRhICU+JSBnZ3Bsb3QoYWVzKHg9dmFsdWVzKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0xKQpgYGAKCkEgc21hbGwgc2FtcGxlIHdpbGwgYmUgamFnZ2VkLCBidXQgdGhlIGxhcmdlciB0aGUgc2FtcGxlIHRoZSBzbW9vdGhlciBpdCBnZXRzOgpgYGB7cn0KdGliYmxlKHZhbHVlcz1ybm9ybSgxMDAwMCwgMTAsIDIuNSkpICU+JSBnZ3Bsb3QoYWVzKHg9dmFsdWVzKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0xKQpgYGAKCiMjIFVuaWZvcm0gZGlzdHJpYnV0aW9uClRoZXJlIGFyZSBtYW55IGtpbmRzIG9mIGRpc3RyaWJ1dGlvbnMuCgotIHJ1bmlmKE4sIG1pbiwgbWF4KQoKSW4gdGhlICpVbmlmb3JtIGRpc3RyaWJ1dGlvbiogdGhlcmUgaXMgYW4gZXF1YWwgY2hhbmNlIG9mIGdldHRpbmcgYW55IHZhbHVlIGJldHdlZW4gdGhlIG1pbmltdW0gYW5kIHRoZSBtYXhpbXVtCmBgYHtyfQpteS5kYXRhIDwtIHRpYmJsZSh2YWx1ZXM9cnVuaWYoMTAwMCwgbWluPTUsIG1heD05KSkKI3FwbG90KHZhbHVlcywgZGF0YT1teS5kYXRhLCBnZW9tPSJoaXN0b2dyYW0iLCBicmVha3M9MToxMCkKbXkuZGF0YSAlPiUgZ2dwbG90KGFlcyh4PXZhbHVlcykpICsgZ2VvbV9oaXN0b2dyYW0oYnJlYWtzPTE6MTApCmBgYAo=