1 R The calculator

The simplest way to use R is as a calculator.

For example, the code below calculates \(1+1\). Click “run” (the green play button) to see:

1+1 # add one and one
[1] 2

Notice the part after “#” (inside a code chunk) is not executed because it as a comment. Write comments to remind yourself (or rather, your future self, who will read the code later) what the code does.

Here is another example. This code calculates \(2^3 + 4 \times 5 + \frac{5}{6}\):

2^3 + 4*5 + 5/6 # two to the third plus four times five plus five divided by six
[1] 28.83333

1.1 Checkpoint

Calculate \(2^2 \times 3^3\):

2^2 * 3^3
[1] 108

Calculate \(2/3 + 4/5 + 6/7\):

2/3 + 4/5 + 6/7
[1] 2.32381

Calculate \(2^3 + 4*5 + 6^7\):

2^3 + 4*5 + 6^7
[1] 279964

1.2 Objects

OK, we can use R to make calculations.

But what if we want to save the output of one calculation and use it in another calculation?

R has memory. What does it remember? Whatever you tell it to! This is called defining objects.

Suppose we want to calculate \(1+1\) and store it in an object. We have to give it a name. Let’s call it “x”:

x = 1 + 1

Notice two things:

  1. = is the assignment operator. It says: "take 1+1 and assign its output to x.
  2. When we run the code, x = 1 + 1, nothing spits out. That’s because the output is stored in x.

What happens if we calculate \(x+2\)

x + 2
[1] 4

It’s the same as calculating \((1+1)+2\).

Let’s create another object called “my_object” equal to \(x \times 4\):

my_object = x * 4

1.3 Vectors

Vectors are objects with multiple values.

For example, here is a vector with the values \(1,2,3,4\) called “data_vector”:

my_vector = c(1,2,3,4) # create a vector
my_vector # then print it to the screen
[1] 1 2 3 4

We can multiply each value by 2:

my_vector * 2
[1] 2 4 6 8

and we multiply each value by 2 and create a new vector (e.g., “data_new_vector”):

data_new_vector = my_vector * 2

Vectors can also contain words – also referred to as “strings” or “characters”.

For instance, here is a vector with the words “hello” and “world”:

character_vector <- c("hello", "world") # make the vector
character_vector # view it!
[1] "hello" "world"

1.4 Functions

Objects are nouns. Functions are verbs, acting on those nouns. That is programming in R in a nutshell. You have a data set (object). You do things to that data set (e.g., analyze with functions).

All functions in R have parentheses: function(). When we created a vector we used the function c().

If we have a vector of data, like data_new_vector, we can calculate the sum with sum():

sum(data_new_vector)
[1] 20

Or find the maximum value with max():

max(data_new_vector)
[1] 8

Or find the minimum value with min():

min(data_new_vector)
[1] 2

Or calculate the average or mean with mean():

mean(data_new_vector)
[1] 5

1.5 Checkpoint

Recall that you create a vector with c() and assign it with =. For example, the chunk below creates a vector called “v” with values \(1,2,3\):

v = c(1,2,3)

Create a vector called “x” with the values \(5, 9, 4, 8, 40, 22\):

x <- c(5,9,4,8,40,22)

Multiply x by 2:

x*2
[1] 10 18  8 16 80 44

Calculate the sum of x with the function sum():

sum(x)
[1] 88

Calculate the average of x with mean():

mean(x)
[1] 14.66667

Calculate the median of x with median():

median(x)
[1] 8.5

Calculate the standard deviation of x with sd():

sd(x)
[1] 13.99524

2 Dataframes

Dataframes – like what you see in an Excel sheet – are just vectors chained together.

Let’s load the tidyverse:

library(tidyverse)

and then load a built-in dataset called “diamonds” with prices of over 50,000 round cut diamonds:

data("diamonds") # use the function data() to load a built-in dataset

You can view the data inside the notebook like so:

diamonds

or you can click on in the “Environment” window pane in the top-right corner of RStudio.

Notice the data contains a variety of data types, such as:

  • price, carat, depth, table: continuous, numerical variables (scale: ratio)
  • color: categorical variable (scale: nominal, i.e. a classification with no ranking)
  • cut: categorical variable (scale: ordinal, i.e. you can rank them)

2.1 Summarizing data

Suppose you wanted to calculate the average price of a diamond. You would

  1. take the data, THEN
  2. summarize it by calculating mean miles per gallon

In R those two steps are:

diamonds %>% # take the data, THEN
  summarise(mean(price)) # summarize it by calculating average price

But not all diamonds are created equal! (According to De Beers.)

Let’s group diamonds by their cut class and then calculate the mean price:

diamonds %>% # take the data, THEN
  group_by(cut) %>%  # group the diamonds by cut, THEN
  summarise(mean(price)) # summarize the data by calculating average price by cut

2.1.1 Checkpoint

Group the diamonds by clarity (clarity) and then calculate average price:

diamonds %>% 
  group_by(clarity) %>% 
  summarise(mean(price))

Now group diamonds by cut and calculate average (mean()), median (median()) and standard deviation (sd()) price. Hint: you only need one call to summarise()!

diamonds %>% 
  group_by(cut) %>% 
  summarise(mean(price), median(price), sd(price))

2.2 Visualizing data

One of the most important plots is the histogram. This tells you how observations are distributed. Understanding distributions is the bedrock of statistical modeling.

Let’s plot the distribution of prices:

ggplot(data = diamonds, aes(x = price)) + 
  geom_histogram()

The distribution is heavily skewed. Clearly the average price is not meaningful! Why? Because if you were to randomly draw from this distribution, you would not get a diamond close to the average.

To see this let’s re-plot the distribution but now with a vertical line at the average price:

ggplot(data = diamonds, aes(x = price)) + 
  geom_histogram() + 
  geom_vline(xintercept = 3932.8, color = "red")

Another key plot type is the scatter plot. Use this to study relationships.

Let’s make a scatter plot of cty by hwy:

Is there a relationship between a diamond’s carats (carat) and its price?

We might think about a model in which carats determine prices (and not the other way round). That is, prices are a function of carats:

\[ \text{price} = f(\text{carats}) \] This model implies carat should be on the x-axis and price on the y-axis:

ggplot(data = diamonds, aes(x = carat, y = price)) + 
  geom_point()

Looks so!

2.2.1 Checkpoint

Plot the distribution of table (another diamond attribute)L

ggplot(data = diamonds, aes(x = table)) + 
  geom_histogram()

Replicate the code above but now plot the distribution of depth with geom_density() so you have kernel density estimate (basically a smooth histogram):

ggplot(data = diamonds, aes(x = depth)) + 
  geom_density()

Based on this plot do you think the average depth of a diamond is meaningful?

2.3 Plots by category

Many times we care about outcomes conditional on some category.

Just like dplyr makes it easy to ggplot makes it very easy to plot by a grouping variables.

There are two approaches.

2.3.1 Fill and color

First, create a single panel, and fill (histograms, boxplots, kernel densities) or color (scatter plots) by the group:

ggplot(data = diamonds, aes(x = price, fill = cut)) + 
  geom_histogram()

and for a scatterplot:

ggplot(data = diamonds, aes(x = carat, y = price, color = cut)) + 
  geom_point()

2.3.2 Facetting

But these types of plots are usually hard to read

Instead you can put each group in its own panel with facet_wrap():

ggplot(data = diamonds, aes(x = price)) + 
  geom_histogram() + 
  facet_wrap(~cut)

ggplot(data = diamonds, aes(x = carat, y = price)) + 
  geom_point() + 
  facet_wrap(~cut) # note the "~" before the grouping variable

or you can even make a grid of plots by two categories using facet_grid():

ggplot(data = diamonds, aes(x = price)) + 
  geom_histogram() + 
  facet_grid(color~cut)

LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFIgKENvbXBsZXRlZCBOb3RlYm9vaykiCnN1YnRpdGxlOiAiUiBmb3IgRGF0YSBTY2llbmNlIgphdXRob3I6ICJMREciCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgdGhlbWU6IHJlYWRhYmxlCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogCiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKIyBSIFRoZSBjYWxjdWxhdG9yCgpUaGUgc2ltcGxlc3Qgd2F5IHRvIHVzZSBSIGlzIGFzIGEgY2FsY3VsYXRvci4gCgpGb3IgZXhhbXBsZSwgdGhlIGNvZGUgYmVsb3cgY2FsY3VsYXRlcyAkMSsxJC4gQ2xpY2sgInJ1biIgKHRoZSBncmVlbiBwbGF5IGJ1dHRvbikgdG8gc2VlOgoKYGBge3IgY2FsYzF9CjErMSAjIGFkZCBvbmUgYW5kIG9uZQpgYGAKCk5vdGljZSB0aGUgcGFydCBhZnRlciAiIyIgKGluc2lkZSBhIGNvZGUgY2h1bmspIGlzIG5vdCBleGVjdXRlZCBiZWNhdXNlIGl0IGFzIGEgKipjb21tZW50LioqIFdyaXRlIGNvbW1lbnRzIHRvIHJlbWluZCB5b3Vyc2VsZiAob3IgcmF0aGVyLCB5b3VyIGZ1dHVyZSBzZWxmLCB3aG8gd2lsbCByZWFkIHRoZSBjb2RlIGxhdGVyKSB3aGF0IHRoZSBjb2RlIGRvZXMuCgpIZXJlIGlzIGFub3RoZXIgZXhhbXBsZS4gVGhpcyBjb2RlIGNhbGN1bGF0ZXMgJDJeMyArIDQgXHRpbWVzIDUgKyBcZnJhY3s1fXs2fSQ6CgpgYGB7ciBjYWxjMn0KMl4zICsgNCo1ICsgNS82ICMgdHdvIHRvIHRoZSB0aGlyZCBwbHVzIGZvdXIgdGltZXMgZml2ZSBwbHVzIGZpdmUgZGl2aWRlZCBieSBzaXgKYGBgCgojIyBDaGVja3BvaW50CgpDYWxjdWxhdGUgJDJeMiBcdGltZXMgM14zJDoKCmBgYHtyIGNoZWNrcG9pbnQgY2FsYzF9CjJeMiAqIDNeMwpgYGAKCkNhbGN1bGF0ZSAkMi8zICsgNC81ICsgNi83JDoKCmBgYHtyIGNoZWNrcG9pbnQgY2FsYzJ9CjIvMyArIDQvNSArIDYvNwpgYGAKCkNhbGN1bGF0ZSAkMl4zICsgNCo1ICsgNl43JDoKCmBgYHtyIGNoZWNrcG9pbnQgY2FsYzN9CjJeMyArIDQqNSArIDZeNwpgYGAKCiMjIE9iamVjdHMKCk9LLCB3ZSBjYW4gdXNlIFIgdG8gbWFrZSBjYWxjdWxhdGlvbnMuCgpCdXQgd2hhdCBpZiB3ZSB3YW50IHRvIHNhdmUgdGhlIG91dHB1dCBvZiBvbmUgY2FsY3VsYXRpb24gYW5kIHVzZSBpdCBpbiBhbm90aGVyIGNhbGN1bGF0aW9uPwoKUiBoYXMgbWVtb3J5LiBXaGF0IGRvZXMgaXQgcmVtZW1iZXI/IFdoYXRldmVyIHlvdSB0ZWxsIGl0IHRvISBUaGlzIGlzIGNhbGxlZCAqKmRlZmluaW5nIG9iamVjdHMqKi4KClN1cHBvc2Ugd2Ugd2FudCB0byBjYWxjdWxhdGUgJDErMSQgYW5kIHN0b3JlIGl0IGluIGFuIG9iamVjdC4gV2UgaGF2ZSB0byBnaXZlIGl0IGEgbmFtZS4gTGV0J3MgY2FsbCBpdCAieCI6CgpgYGB7ciBvYmplY3RzMX0KeCA9IDEgKyAxCmBgYAoKTm90aWNlIHR3byB0aGluZ3M6CgoxLiBgPWAgaXMgdGhlICoqYXNzaWdubWVudCBvcGVyYXRvcioqLiBJdCBzYXlzOiAidGFrZSAxKzEgYW5kIGFzc2lnbiBpdHMgKm91dHB1dCogdG8gYHhgLgoyLiBXaGVuIHdlIHJ1biB0aGUgY29kZSwgYHggPSAxICsgMWAsIG5vdGhpbmcgc3BpdHMgb3V0LiBUaGF0J3MgYmVjYXVzZSB0aGUgb3V0cHV0IGlzICoqc3RvcmVkKiogaW4gYHhgLgoKV2hhdCBoYXBwZW5zIGlmIHdlIGNhbGN1bGF0ZSAkeCsyJAoKYGBge3Igb2JqZWN0czJ9CnggKyAyCmBgYAoKSXQncyB0aGUgc2FtZSBhcyBjYWxjdWxhdGluZyAkKDErMSkrMiQuIAoKTGV0J3MgY3JlYXRlIGFub3RoZXIgb2JqZWN0IGNhbGxlZCAibXlfb2JqZWN0IiBlcXVhbCB0byAkeCBcdGltZXMgNCQ6CgpgYGB7ciBvYmplY3RzM30KbXlfb2JqZWN0ID0geCAqIDQKYGBgCgojIyBWZWN0b3JzCgpWZWN0b3JzIGFyZSBvYmplY3RzIHdpdGggbXVsdGlwbGUgdmFsdWVzLiAKCkZvciBleGFtcGxlLCBoZXJlIGlzIGEgdmVjdG9yIHdpdGggdGhlIHZhbHVlcyAkMSwyLDMsNCQgY2FsbGVkICJkYXRhX3ZlY3RvciI6CgpgYGB7ciB2ZWMxfQpteV92ZWN0b3IgPSBjKDEsMiwzLDQpICMgY3JlYXRlIGEgdmVjdG9yCm15X3ZlY3RvciAjIHRoZW4gcHJpbnQgaXQgdG8gdGhlIHNjcmVlbgpgYGAKCldlIGNhbiBtdWx0aXBseSBlYWNoIHZhbHVlIGJ5IDI6CgpgYGB7ciB2ZWMyfQpteV92ZWN0b3IgKiAyCmBgYAoKYW5kIHdlIG11bHRpcGx5IGVhY2ggdmFsdWUgYnkgMiBhbmQgY3JlYXRlIGEgbmV3IHZlY3RvciAoZS5nLiwgImRhdGFfbmV3X3ZlY3RvciIpOgoKYGBge3IgdmVjM30KZGF0YV9uZXdfdmVjdG9yID0gbXlfdmVjdG9yICogMgpgYGAKClZlY3RvcnMgY2FuIGFsc28gY29udGFpbiB3b3JkcyAtLSBhbHNvIHJlZmVycmVkIHRvIGFzICJzdHJpbmdzIiBvciAiY2hhcmFjdGVycyIuIAoKRm9yIGluc3RhbmNlLCBoZXJlIGlzIGEgdmVjdG9yIHdpdGggdGhlIHdvcmRzICJoZWxsbyIgYW5kICJ3b3JsZCI6CgpgYGB7ciB2ZWM0fQpjaGFyYWN0ZXJfdmVjdG9yIDwtIGMoImhlbGxvIiwgIndvcmxkIikgIyBtYWtlIHRoZSB2ZWN0b3IKY2hhcmFjdGVyX3ZlY3RvciAjIHZpZXcgaXQhCmBgYAoKCiMjIEZ1bmN0aW9ucwoKT2JqZWN0cyBhcmUgbm91bnMuIEZ1bmN0aW9ucyBhcmUgdmVyYnMsIGFjdGluZyBvbiB0aG9zZSBub3Vucy4gVGhhdCBpcyBwcm9ncmFtbWluZyBpbiBSIGluIGEgbnV0c2hlbGwuIFlvdSBoYXZlIGEgZGF0YSBzZXQgKG9iamVjdCkuIFlvdSBkbyB0aGluZ3MgdG8gdGhhdCBkYXRhIHNldCAoZS5nLiwgYW5hbHl6ZSB3aXRoIGZ1bmN0aW9ucykuCgpBbGwgZnVuY3Rpb25zIGluIFIgaGF2ZSBwYXJlbnRoZXNlczogYGZ1bmN0aW9uKClgLiBXaGVuIHdlIGNyZWF0ZWQgYSB2ZWN0b3Igd2UgdXNlZCB0aGUgZnVuY3Rpb24gYGMoKWAuCgpJZiB3ZSBoYXZlIGEgdmVjdG9yIG9mIGRhdGEsIGxpa2UgYGRhdGFfbmV3X3ZlY3RvcmAsIHdlIGNhbiBjYWxjdWxhdGUgdGhlIHN1bSB3aXRoIGBzdW0oKWA6CgpgYGB7ciBmdW5jdGlvbjF9CnN1bShkYXRhX25ld192ZWN0b3IpCmBgYAoKT3IgZmluZCB0aGUgbWF4aW11bSB2YWx1ZSB3aXRoIGBtYXgoKWA6CgpgYGB7ciBmdW5jdGlvbjJ9Cm1heChkYXRhX25ld192ZWN0b3IpCmBgYAoKT3IgZmluZCB0aGUgbWluaW11bSB2YWx1ZSB3aXRoIGBtaW4oKWA6CgpgYGB7ciBmdW5jdGlvbjN9Cm1pbihkYXRhX25ld192ZWN0b3IpCmBgYAoKT3IgY2FsY3VsYXRlIHRoZSBhdmVyYWdlIG9yIG1lYW4gd2l0aCBgbWVhbigpYDoKCmBgYHtyIGZ1bmN0aW9uNH0KbWVhbihkYXRhX25ld192ZWN0b3IpCmBgYAoKCiMjIENoZWNrcG9pbnQgCgpSZWNhbGwgdGhhdCB5b3UgY3JlYXRlIGEgdmVjdG9yIHdpdGggYGMoKWAgYW5kIGFzc2lnbiBpdCB3aXRoIGA9YC4gRm9yIGV4YW1wbGUsIHRoZSBjaHVuayBiZWxvdyBjcmVhdGVzIGEgdmVjdG9yIGNhbGxlZCAidiIgd2l0aCB2YWx1ZXMgJDEsMiwzJDoKCmBgYHtyfQp2ID0gYygxLDIsMykKYGBgCgpDcmVhdGUgYSB2ZWN0b3IgY2FsbGVkICJ4IiB3aXRoIHRoZSB2YWx1ZXMgJDUsIDksIDQsIDgsIDQwLCAyMiQ6CgpgYGB7ciBjaGVja3BvaW50IG9iamVjdHNfZnVuY3Rpb25zXzF9CnggPC0gYyg1LDksNCw4LDQwLDIyKQpgYGAKCk11bHRpcGx5IGB4YCBieSAyOgoKYGBge3IgY2hlY2twb2ludCBvYmplY3RzX2Z1bmN0aW9uc18yfQp4KjIKYGBgCgpDYWxjdWxhdGUgdGhlIHN1bSBvZiBgeGAgd2l0aCB0aGUgZnVuY3Rpb24gYHN1bSgpYDoKCmBgYHtyIGNoZWNrcG9pbnQgb2JqZWN0c19mdW5jdGlvbnNfM30Kc3VtKHgpCmBgYAoKQ2FsY3VsYXRlIHRoZSBhdmVyYWdlIG9mIGB4YCB3aXRoIGBtZWFuKClgOgoKYGBge3IgY2hlY2twb2ludCBvYmplY3RzX2Z1bmN0aW9uc180fQptZWFuKHgpCmBgYAoKQ2FsY3VsYXRlIHRoZSBtZWRpYW4gb2YgYHhgIHdpdGggYG1lZGlhbigpYDoKCmBgYHtyIGNoZWNrcG9pbnQgb2JqZWN0c19mdW5jdGlvbnNfNX0KbWVkaWFuKHgpCmBgYAoKQ2FsY3VsYXRlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYHhgIHdpdGggYHNkKClgOgoKYGBge3IgY2hlY2twb2ludCBvYmplY3RzX2Z1bmN0aW9uc182fQpzZCh4KQpgYGAKCiMgRGF0YWZyYW1lcwoKRGF0YWZyYW1lcyAtLSBsaWtlIHdoYXQgeW91IHNlZSBpbiBhbiBFeGNlbCBzaGVldCAtLSBhcmUganVzdCB2ZWN0b3JzIGNoYWluZWQgdG9nZXRoZXIuIAoKTGV0J3MgbG9hZCB0aGUgYHRpZHl2ZXJzZWA6CgpgYGB7ciBsb2FkIHRpZHl2ZXJzZSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKYW5kIHRoZW4gbG9hZCBhIGJ1aWx0LWluIGRhdGFzZXQgY2FsbGVkICJkaWFtb25kcyIgd2l0aCBwcmljZXMgb2Ygb3ZlciA1MCwwMDAgcm91bmQgY3V0IGRpYW1vbmRzOgoKYGBge3IgbG9hZCBkaWFtb25kc30KZGF0YSgiZGlhbW9uZHMiKSAjIHVzZSB0aGUgZnVuY3Rpb24gZGF0YSgpIHRvIGxvYWQgYSBidWlsdC1pbiBkYXRhc2V0CmBgYAoKWW91IGNhbiB2aWV3IHRoZSBkYXRhIGluc2lkZSB0aGUgbm90ZWJvb2sgbGlrZSBzbzoKCmBgYHtyIHZpZXcgZGlhbW9uZHN9CmRpYW1vbmRzCmBgYAoKb3IgeW91IGNhbiBjbGljayBvbiBpbiB0aGUgIkVudmlyb25tZW50IiB3aW5kb3cgcGFuZSBpbiB0aGUgdG9wLXJpZ2h0IGNvcm5lciBvZiBSU3R1ZGlvLgoKTm90aWNlIHRoZSBkYXRhIGNvbnRhaW5zIGEgdmFyaWV0eSBvZiBkYXRhICoqdHlwZXMqKiwgc3VjaCBhczoKCiogYHByaWNlYCwgYGNhcmF0YCwgYGRlcHRoYCwgYHRhYmxlYDogY29udGludW91cywgbnVtZXJpY2FsIHZhcmlhYmxlcyAoc2NhbGU6IHJhdGlvKQoqIGBjb2xvcmA6IGNhdGVnb3JpY2FsIHZhcmlhYmxlIChzY2FsZTogbm9taW5hbCwgaS5lLiBhIGNsYXNzaWZpY2F0aW9uIHdpdGggbm8gcmFua2luZykKKiBgY3V0YDogY2F0ZWdvcmljYWwgdmFyaWFibGUgKHNjYWxlOiBvcmRpbmFsLCBpLmUuIHlvdSBjYW4gcmFuayB0aGVtKQoKIyMgU3VtbWFyaXppbmcgZGF0YQoKU3VwcG9zZSB5b3Ugd2FudGVkIHRvIGNhbGN1bGF0ZSB0aGUgYXZlcmFnZSBwcmljZSBvZiBhIGRpYW1vbmQuIFlvdSB3b3VsZAoKMS4gdGFrZSB0aGUgZGF0YSwgVEhFTgoyLiBzdW1tYXJpemUgaXQgYnkgY2FsY3VsYXRpbmcgbWVhbiBtaWxlcyBwZXIgZ2FsbG9uCgpJbiBSIHRob3NlIHR3byBzdGVwcyBhcmU6CgpgYGB7ciBkcGx5cjF9CmRpYW1vbmRzICU+JSAjIHRha2UgdGhlIGRhdGEsIFRIRU4KICBzdW1tYXJpc2UobWVhbihwcmljZSkpICMgc3VtbWFyaXplIGl0IGJ5IGNhbGN1bGF0aW5nIGF2ZXJhZ2UgcHJpY2UKYGBgCgpCdXQgbm90IGFsbCBkaWFtb25kcyBhcmUgY3JlYXRlZCBlcXVhbCEgKEFjY29yZGluZyB0byBEZSBCZWVycy4pCgpMZXQncyBncm91cCBkaWFtb25kcyBieSB0aGVpciBgY3V0YCBgY2xhc3NgIGFuZCB0aGVuIGNhbGN1bGF0ZSB0aGUgbWVhbiBwcmljZToKCmBgYHtyIGRwbHlyMiwgbWVzc2FnZT1GQUxTRX0KZGlhbW9uZHMgJT4lICMgdGFrZSB0aGUgZGF0YSwgVEhFTgogIGdyb3VwX2J5KGN1dCkgJT4lICAjIGdyb3VwIHRoZSBkaWFtb25kcyBieSBjdXQsIFRIRU4KICBzdW1tYXJpc2UobWVhbihwcmljZSkpICMgc3VtbWFyaXplIHRoZSBkYXRhIGJ5IGNhbGN1bGF0aW5nIGF2ZXJhZ2UgcHJpY2UgYnkgY3V0CmBgYAoKIyMjIENoZWNrcG9pbnQKCkdyb3VwIHRoZSBkaWFtb25kcyBieSBjbGFyaXR5IChgY2xhcml0eWApIGFuZCB0aGVuIGNhbGN1bGF0ZSBhdmVyYWdlIHByaWNlOgoKYGBge3IgY2hlY2twb2ludCBkcGx5cjEsIG1lc3NhZ2UgPSBGQUxTRX0KZGlhbW9uZHMgJT4lIAogIGdyb3VwX2J5KGNsYXJpdHkpICU+JSAKICBzdW1tYXJpc2UobWVhbihwcmljZSkpCmBgYAoKTm93IGdyb3VwIGRpYW1vbmRzIGJ5IGBjdXRgIGFuZCBjYWxjdWxhdGUgYXZlcmFnZSAoYG1lYW4oKWApLCBtZWRpYW4gKGBtZWRpYW4oKWApIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gKGBzZCgpYCkgcHJpY2UuIEhpbnQ6IHlvdSBvbmx5IG5lZWQgb25lIGNhbGwgdG8gYHN1bW1hcmlzZSgpYCEKCmBgYHtyIGNoZWNrcG9pbnQgZHBseXIyLCBtZXNzYWdlPUZBTFNFfQpkaWFtb25kcyAlPiUgCiAgZ3JvdXBfYnkoY3V0KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW4ocHJpY2UpLCBtZWRpYW4ocHJpY2UpLCBzZChwcmljZSkpCmBgYAoKIyMgVmlzdWFsaXppbmcgZGF0YQoKT25lIG9mIHRoZSBtb3N0IGltcG9ydGFudCBwbG90cyBpcyB0aGUgKipoaXN0b2dyYW0qKi4gVGhpcyB0ZWxscyB5b3UgaG93IG9ic2VydmF0aW9ucyBhcmUgKipkaXN0cmlidXRlZCoqLiBVbmRlcnN0YW5kaW5nIGRpc3RyaWJ1dGlvbnMgaXMgdGhlIGJlZHJvY2sgb2Ygc3RhdGlzdGljYWwgbW9kZWxpbmcuCgpMZXQncyBwbG90IHRoZSAqKmRpc3RyaWJ1dGlvbioqIG9mIHByaWNlczoKCmBgYHtyIGdncGxvdDF9CmdncGxvdChkYXRhID0gZGlhbW9uZHMsIGFlcyh4ID0gcHJpY2UpKSArIAogIGdlb21faGlzdG9ncmFtKCkKYGBgCgpUaGUgZGlzdHJpYnV0aW9uIGlzIGhlYXZpbHkgc2tld2VkLiBDbGVhcmx5IHRoZSAqKmF2ZXJhZ2UgcHJpY2UqKiBpcyBub3QgbWVhbmluZ2Z1bCEgV2h5PyBCZWNhdXNlIGlmIHlvdSB3ZXJlIHRvIHJhbmRvbWx5IGRyYXcgZnJvbSB0aGlzIGRpc3RyaWJ1dGlvbiwgeW91IHdvdWxkIG5vdCBnZXQgYSBkaWFtb25kIGNsb3NlIHRvIHRoZSBhdmVyYWdlLgoKVG8gc2VlIHRoaXMgbGV0J3MgcmUtcGxvdCB0aGUgZGlzdHJpYnV0aW9uIGJ1dCBub3cgd2l0aCBhIHZlcnRpY2FsIGxpbmUgYXQgdGhlIGF2ZXJhZ2UgcHJpY2U6CgpgYGB7ciBnZ3Bsb3QxIGNvbnRpbnVlZH0KZ2dwbG90KGRhdGEgPSBkaWFtb25kcywgYWVzKHggPSBwcmljZSkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDM5MzIuOCwgY29sb3IgPSAicmVkIikKYGBgCkFub3RoZXIga2V5IHBsb3QgdHlwZSBpcyB0aGUgKipzY2F0dGVyIHBsb3QqKi4gVXNlIHRoaXMgdG8gc3R1ZHkgKipyZWxhdGlvbnNoaXBzKiouCgpMZXQncyBtYWtlIGEgc2NhdHRlciBwbG90IG9mIGBjdHlgIGJ5IGBod3lgOgoKSXMgdGhlcmUgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIGRpYW1vbmQncyBjYXJhdHMgKGBjYXJhdGApIGFuZCBpdHMgcHJpY2U/CgpXZSBtaWdodCB0aGluayBhYm91dCBhIG1vZGVsIGluIHdoaWNoIGNhcmF0cyBkZXRlcm1pbmUgcHJpY2VzIChhbmQgbm90IHRoZSBvdGhlciB3YXkgcm91bmQpLiBUaGF0IGlzLCBwcmljZXMgYXJlIGEgKipmdW5jdGlvbioqIG9mIGNhcmF0czoKCiQkClx0ZXh0e3ByaWNlfSA9IGYoXHRleHR7Y2FyYXRzfSkKJCQKVGhpcyBtb2RlbCBpbXBsaWVzIGBjYXJhdGAgc2hvdWxkIGJlIG9uIHRoZSB4LWF4aXMgYW5kIGBwcmljZWAgb24gdGhlIHktYXhpczoKCmBgYHtyIGdncGxvdDJ9CmdncGxvdChkYXRhID0gZGlhbW9uZHMsIGFlcyh4ID0gY2FyYXQsIHkgPSBwcmljZSkpICsgCiAgZ2VvbV9wb2ludCgpCmBgYApMb29rcyBzbyEKCiMjIyBDaGVja3BvaW50CgpQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgYHRhYmxlYCAoYW5vdGhlciBkaWFtb25kIGF0dHJpYnV0ZSlMCgpgYGB7ciBjaGVja3BvaW50IGdncGxvdCAxfQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzLCBhZXMoeCA9IHRhYmxlKSkgKyAKICBnZW9tX2hpc3RvZ3JhbSgpCmBgYAoKClJlcGxpY2F0ZSB0aGUgY29kZSBhYm92ZSBidXQgbm93IHBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBgZGVwdGhgIHdpdGggYGdlb21fZGVuc2l0eSgpYCBzbyB5b3UgaGF2ZSBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSAoYmFzaWNhbGx5IGEgc21vb3RoIGhpc3RvZ3JhbSk6CgpgYGB7ciBjaGVja3BvaW50IGdncGxvdCAyfQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzLCBhZXMoeCA9IGRlcHRoKSkgKyAKICBnZW9tX2RlbnNpdHkoKQpgYGAKQmFzZWQgb24gdGhpcyBwbG90IGRvIHlvdSB0aGluayB0aGUgYXZlcmFnZSBkZXB0aCBvZiBhIGRpYW1vbmQgaXMgbWVhbmluZ2Z1bD8KCiMjIFBsb3RzIGJ5IGNhdGVnb3J5CgpNYW55IHRpbWVzIHdlIGNhcmUgYWJvdXQgb3V0Y29tZXMgY29uZGl0aW9uYWwgb24gc29tZSBjYXRlZ29yeS4gCgpKdXN0IGxpa2UgYGRwbHlyYCBtYWtlcyBpdCBlYXN5IHRvIGBnZ3Bsb3RgIG1ha2VzIGl0IHZlcnkgZWFzeSB0byBwbG90IGJ5IGEgZ3JvdXBpbmcgdmFyaWFibGVzLiAKClRoZXJlIGFyZSB0d28gYXBwcm9hY2hlcy4gCgojIyMgRmlsbCBhbmQgY29sb3IKCkZpcnN0LCBjcmVhdGUgYSBzaW5nbGUgcGFuZWwsIGFuZCBgZmlsbGAgKGhpc3RvZ3JhbXMsIGJveHBsb3RzLCBrZXJuZWwgZGVuc2l0aWVzKSBvciBgY29sb3JgIChzY2F0dGVyIHBsb3RzKSBieSB0aGUgZ3JvdXA6CgpgYGB7ciBnZ3Bsb3QgZmlsbH0KZ2dwbG90KGRhdGEgPSBkaWFtb25kcywgYWVzKHggPSBwcmljZSwgZmlsbCA9IGN1dCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oKQpgYGAKCmFuZCBmb3IgYSBzY2F0dGVycGxvdDoKCmBgYHtyIGdncGxvdCBjb2xvcn0KZ2dwbG90KGRhdGEgPSBkaWFtb25kcywgYWVzKHggPSBjYXJhdCwgeSA9IHByaWNlLCBjb2xvciA9IGN1dCkpICsgCiAgZ2VvbV9wb2ludCgpCmBgYAoKIyMjIEZhY2V0dGluZwoKQnV0IHRoZXNlIHR5cGVzIG9mIHBsb3RzIGFyZSB1c3VhbGx5IGhhcmQgdG8gcmVhZCAKCkluc3RlYWQgeW91IGNhbiBwdXQgZWFjaCBncm91cCBpbiBpdHMgb3duIHBhbmVsIHdpdGggYGZhY2V0X3dyYXAoKWA6CgpgYGB7ciBmYWNldCBoaXN0b2dyYW19CmdncGxvdChkYXRhID0gZGlhbW9uZHMsIGFlcyh4ID0gcHJpY2UpKSArIAogIGdlb21faGlzdG9ncmFtKCkgKyAKICBmYWNldF93cmFwKH5jdXQpCmBgYAoKCmBgYHtyIGZhY2V0IHNjYXR0ZXJwbG90fQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzLCBhZXMoeCA9IGNhcmF0LCB5ID0gcHJpY2UpKSArIAogIGdlb21fcG9pbnQoKSArIAogIGZhY2V0X3dyYXAofmN1dCkgIyBub3RlIHRoZSAifiIgYmVmb3JlIHRoZSBncm91cGluZyB2YXJpYWJsZQpgYGAKCm9yIHlvdSBjYW4gZXZlbiBtYWtlIGEgKipncmlkKiogb2YgcGxvdHMgYnkgdHdvIGNhdGVnb3JpZXMgdXNpbmcgYGZhY2V0X2dyaWQoKWA6CgpgYGB7ciBmYWNldF9ncmlkfQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzLCBhZXMoeCA9IHByaWNlKSkgKyAKICBnZW9tX2hpc3RvZ3JhbSgpICsgCiAgZmFjZXRfZ3JpZChjb2xvcn5jdXQpCmBgYAoK