pacman::p_load(tidyverse, gapminder)
pacman::p_load(tidyverse, 
               gapminder)

Dataset

gapminder
# Look at the gapminder dataset
gapminder

How many observations (rows) are in the dataset?

glimpse(gapminder)
Rows: 1,704
Columns: 6
$ country   <fct> Afghanistan, Afghanistan, Afghani…
$ continent <fct> Asia, Asia, Asia, Asia, Asia, Asi…
$ year      <int> 1952, 1957, 1962, 1967, 1972, 197…
$ lifeExp   <dbl> 28.801, 30.332, 31.997, 34.020, 3…
$ pop       <int> 8425333, 9240934, 10267083, 11537…
$ gdpPercap <dbl> 779.4453, 820.8530, 853.1007, 836…

Filter

Add a filter() line after the pipe (%>%) to extract only the observations from the year 1957. Remember that you use == to compare two values.

gapminder %>% 
  filter(year == 1957)
# Filter the gapminder dataset for the year 1957
gapminder %>%
  filter(year == 1957)
gapminder %>% 
  filter(year == 1957 & continent == "Europe")

Arrange

gapminder %>% 
  filter(year == 1957 & continent == "Europe") %>% 
  arrange(gdpPercap) 

Select

gapminder %>% 
  filter(year == 1957 & continent == "Europe") %>% 
  arrange(gdpPercap)  %>% 
  select(country, gdpPercap)
gapminder %>% 
  filter(year == 2002) %>% 
  arrange(desc(lifeExp)) %>% 
  select(country, lifeExp, continent) 

Mutate

gapminder

1 United States Dollar equals 0.85 Euro

gapminder %>% 
  mutate( gdpEuros = gdpPercap *.85  ) %>% 
  select(country, gdpEuros)

Use mutate to create a new column called lifeExpMonths

gapminder %>% 
  mutate(lifeExpMonths = lifeExp * 12)

In this exercise, you’ll combine all three of the verbs you’ve learned in this chapter, to find the countries with the highest life expectancy, in months, in the year 2007.

In one sequence of pipes on the gapminder dataset: - filter() for observations from the year 2007, - mutate() to create a column lifeExpMonths, calculated as 12 * lifeExp, and - arrange() in descending order of that new column - select and show only country and lifeExpMonths

gapminder %>%                        # my df
  filter(year == 2007) %>%           # here I filter because this year is ....
  mutate (lifeExpMonth = lifeExp * 12 ) %>% # Create a new var
  arrange(desc(lifeExp)) %>% 
  select (country, lifeExpMonth)

Summarize

Filter for the year 1957, then use the mean() function within a summarize() to calculate the median life expectancy into a column called meanLifeExp.

Which was the mean gpdPerCap in 1957

group_by

What is the gdpPercat by continent

gapminder %>% 
  group_by(continent) %>% 
  summarize(gdpPerContMedian = median(gdpPercap))
`summarise()` ungrouping output (override with `.groups` argument)

Calculate the mean life expectancy by year

gapminder %>% 
  group_by(year) %>% 
  summarise(lifeExpMean = mean(lifeExp))
`summarise()` ungrouping output (override with `.groups` argument)
gapminder %>% 
  group_by(year, continent) %>% 
  summarise(lifeExpMean = mean(lifeExp)) %>% 
  ggplot(aes(x = year, 
             y = lifeExpMean)) + 
  geom_line() + 
  aes(color = continent) +
  expand_limits(y = 0)
`summarise()` regrouping output by 'year' (override with `.groups` argument)

Change of the gdp by year and continent

gapminder %>% 
  group_by(year, continent) %>% 
  summarise(meanGdpPercap = mean(gdpPercap)) %>% 
  ggplot(aes(x = year,
             y = meanGdpPercap, color = continent)) +
  geom_line() +
  expand_limits(y = 0) + 
  scale_y_log10()
`summarise()` regrouping output by 'year' (override with `.groups` argument)

Arrange

# Sort in ascending order of lifeExp
gapminder %>% 
  arrange(lifeExp)
NA
NA
# Sort in descending order of lifeExp
gapminder %>% 
  arrange(desc(lifeExp))

Use filter() to extract observations from just the year 1957, then use arrange() to sort in descending order of population (pop).

# Filter for the year 1957, then arrange in descending order of population
gapminder %>% 
  filter(year == 1957) %>% 
  arrange(desc(pop))

Mutate

Suppose we want life expectancy to be measured in months instead of years: you’d have to multiply the existing value by 12. You can use the mutate() verb to change this column, or to create a new column that’s calculated this way.

# Use mutate to change lifeExp to be in months
gapminder %>% 
        mutate(lifeExp = lifeExp * 12)

In this exercise, you’ll combine all three of the verbs you’ve learned in this chapter, to find the countries with the highest life expectancy, in months, in the year 2007.

In one sequence of pipes on the gapminder dataset: filter() for observations from the year 2007, mutate() to create a column lifeExpMonths, calculated as 12 * lifeExp, and arrange() in descending order of that new column

# Filter, mutate, and arrange the gapminder dataset
gapminder %>%
  filter(year == 2007) %>%
  mutate(lifeExpMonths = 12 * lifeExp) %>%
  arrange(desc(lifeExpMonths))

summarize

Use the median() function within a summarize() to find the median life expectancy. Save it into a column called medianLifeExp.

Filter for the year 1957, then use the median() function within a summarize() to calculate the median life expectancy into a column called medianLifeExp.

Find both the median life expectancy (lifeExp) and the maximum GDP per capita (gdpPercap) in the year 1957, calling them medianLifeExp and maxGdpPercap respectively. You can use the max() function to find the maximum.

The group_by verb

gapminder %>% 
  group_by(year) %>% 
  summarise(meanLifeExp = mean(lifeExp), 
            totalPop = sum(pop))
`summarise()` ungrouping output (override with `.groups` argument)
gapminder %>% 
  group_by(year, continent) %>% 
  summarise(meanLifeExp = mean(lifeExp), 
            totalPop = sum(pop))
`summarise()` regrouping output by 'year' (override with `.groups` argument)
gapminder %>% 
  group_by(year, continent) %>% 
  summarise(meanLifeExp = mean(lifeExp), 
            totalPop = sum(pop)) %>% 
  ggplot(aes(x = year, 
             y = meanLifeExp, 
             size = totalPop, 
             color = continent)) + 
  geom_line()
`summarise()` regrouping output by 'year' (override with `.groups` argument)

Exercise

Find the median life expectancy (lifeExp) and maximum GDP per capita (gdpPercap) within each year, saving them into medianLifeExp and maxGdpPercap, respectively.

gapminder %>% 
  group_by(year) %>% 
  summarize(medianLifeExp = median(lifeExp),
            maxGdpPercap = max(gdpPercap))

Filter the gapminder data for the year 1957. Then find the median life expectancy (lifeExp) and maximum GDP per capita (gdpPercap) within each continent, saving them into medianLifeExp and maxGdpPercap, respectively.

Find the median life expectancy (lifeExp) and maximum GDP per capita (gdpPercap) within each combination of continent and year, saving them into medianLifeExp and maxGdpPercap, respectively.

gapminder %>% 
        group_by(continent, year) %>% 
        summarize(medianLifeExp = median(lifeExp), 
                  maxGdpPercap = max(gdpPercap))
`summarise()` regrouping output by 'continent' (override with `.groups` argument)

Visualizing

Visualize population over time

gapminder %>%
  group_by(year) %>% 
  summarise(totalPop = sum(pop)) %>% 
  ggplot(aes(x = year, 
             y = totalPop )) + 
  geom_point()
`summarise()` ungrouping output (override with `.groups` argument)

gapminder %>%
  group_by(year) %>% 
  summarise(totalPop = sum(pop)) %>% 
  ggplot(aes(x = year, 
             y = totalPop )) + 
  geom_point() + 
  expand_limits(y = 0)
`summarise()` ungrouping output (override with `.groups` argument)

gapminder %>%
  group_by(year, continent) %>% 
  summarise(totalPop = sum(pop)) %>% 
  ggplot(aes(x = year, 
             y = totalPop )) + 
  geom_point() + 
  expand_limits(y = 0)
`summarise()` regrouping output by 'year' (override with `.groups` argument)

gapminder %>%
  group_by(year, continent) %>% 
  summarise(totalPop = sum(pop)) %>% 
  ggplot(aes(x = year, 
             y = totalPop, 
             color = continent)) + 
  geom_point() + 
  expand_limits(y = 0)
`summarise()` regrouping output by 'year' (override with `.groups` argument)

gapminder %>%
  group_by(year, continent) %>% 
  summarise(totalPop = sum(pop)) %>% 
  ggplot(aes(x = year, 
             y = totalPop, 
             color = continent)) + 
  geom_point() + 
  expand_limits(y = 0) + 
  scale_y_log10()
`summarise()` regrouping output by 'year' (override with `.groups` argument)

Use the by_year dataset to create a scatter plot showing the change of median life expectancy over time, with year on the x-axis and medianLifeExp on the y-axis. Be sure to add expand_limits(y = 0) to make sure the plot’s y-axis includes zero.

Summarize the gapminder dataset by continent and year, finding the median GDP per capita (gdpPercap) within each and putting it into a column called medianGdpPercap. Use the assignment operator <- to save this summarized data as by_year_continent. Create a scatter plot showing the change in medianGdpPercap by continent over time. Use color to distinguish between continents, and be sure to add expand_limits(y = 0) so that the y-axis starts at zero.

LS0tCnRpdGxlOiAiM3JkIFNlc3Npb246IERhdGEgd3JhbmdsaW5nIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgoKCgoKYGBge3J9CnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSwgZ2FwbWluZGVyKQpgYGAKCmBgYHtyfQpwYWNtYW46OnBfbG9hZCh0aWR5dmVyc2UsIAogICAgICAgICAgICAgICBnYXBtaW5kZXIpCmBgYAoKCgojIERhdGFzZXQKCgpgYGB7cn0KZ2FwbWluZGVyCmBgYAoKCgpgYGB7cn0KIyBMb29rIGF0IHRoZSBnYXBtaW5kZXIgZGF0YXNldApnYXBtaW5kZXIKYGBgCgpIb3cgbWFueSBvYnNlcnZhdGlvbnMgKHJvd3MpIGFyZSBpbiB0aGUgZGF0YXNldD8KCmBgYHtyfQpnbGltcHNlKGdhcG1pbmRlcikKYGBgCgoKIyMgRmlsdGVyCgpBZGQgYSBmaWx0ZXIoKSBsaW5lIGFmdGVyIHRoZSBwaXBlICglPiUpIHRvIGV4dHJhY3Qgb25seSB0aGUgb2JzZXJ2YXRpb25zIGZyb20gdGhlIHllYXIgMTk1Ny4gUmVtZW1iZXIgdGhhdCB5b3UgdXNlID09IHRvIGNvbXBhcmUgdHdvIHZhbHVlcy4KCgpgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBmaWx0ZXIoeWVhciA9PSAxOTU3KQpgYGAKCgoKCgpgYGB7cn0KIyBGaWx0ZXIgdGhlIGdhcG1pbmRlciBkYXRhc2V0IGZvciB0aGUgeWVhciAxOTU3CmdhcG1pbmRlciAlPiUKICBmaWx0ZXIoeWVhciA9PSAxOTU3KQpgYGAKCmBgYHtyfQpnYXBtaW5kZXIgJT4lIAogIGZpbHRlcih5ZWFyID09IDE5NTcgJiBjb250aW5lbnQgPT0gIkV1cm9wZSIpCmBgYAoKCiMjIEFycmFuZ2UKCmBgYHtyfQpnYXBtaW5kZXIgJT4lIAogIGZpbHRlcih5ZWFyID09IDE5NTcgJiBjb250aW5lbnQgPT0gIkV1cm9wZSIpICU+JSAKICBhcnJhbmdlKGdkcFBlcmNhcCkgCmBgYAoKCiMgU2VsZWN0CmBgYHtyfQpnYXBtaW5kZXIgJT4lIAogIGZpbHRlcih5ZWFyID09IDE5NTcgJiBjb250aW5lbnQgPT0gIkV1cm9wZSIpICU+JSAKICBhcnJhbmdlKGdkcFBlcmNhcCkgICU+JSAKICBzZWxlY3QoY291bnRyeSwgZ2RwUGVyY2FwKQpgYGAKCgpgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBmaWx0ZXIoeWVhciA9PSAyMDAyKSAlPiUgCiAgYXJyYW5nZShkZXNjKGxpZmVFeHApKSAlPiUgCiAgc2VsZWN0KGNvdW50cnksIGxpZmVFeHAsIGNvbnRpbmVudCkgCmBgYAoKCiMgTXV0YXRlCgpgYGB7cn0KZ2FwbWluZGVyCmBgYAoKCgoKMSBVbml0ZWQgU3RhdGVzIERvbGxhciBlcXVhbHMKMC44NSBFdXJvCgpgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBtdXRhdGUoIGdkcEV1cm9zID0gZ2RwUGVyY2FwICouODUgICkgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBnZHBFdXJvcykKYGBgCgogVXNlIG11dGF0ZSB0byBjcmVhdGUgYSBuZXcgY29sdW1uIGNhbGxlZCBsaWZlRXhwTW9udGhzCiAKIApgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBtdXRhdGUobGlmZUV4cE1vbnRocyA9IGxpZmVFeHAgKiAxMikKYGBgCiAKSW4gdGhpcyBleGVyY2lzZSwgeW91J2xsIGNvbWJpbmUgYWxsIHRocmVlIG9mIHRoZSB2ZXJicyB5b3UndmUgbGVhcm5lZCBpbiB0aGlzIGNoYXB0ZXIsIHRvIGZpbmQgdGhlIGNvdW50cmllcyB3aXRoIHRoZSBoaWdoZXN0IGxpZmUgZXhwZWN0YW5jeSwgaW4gbW9udGhzLCBpbiB0aGUgeWVhciAyMDA3LgoKSW4gb25lIHNlcXVlbmNlIG9mIHBpcGVzIG9uIHRoZSBnYXBtaW5kZXIgZGF0YXNldDoKLSBmaWx0ZXIoKSBmb3Igb2JzZXJ2YXRpb25zIGZyb20gdGhlIHllYXIgMjAwNywKLSBtdXRhdGUoKSB0byBjcmVhdGUgYSBjb2x1bW4gbGlmZUV4cE1vbnRocywgY2FsY3VsYXRlZCBhcyAxMiAqIGxpZmVFeHAsIGFuZAotIGFycmFuZ2UoKSBpbiBkZXNjZW5kaW5nIG9yZGVyIG9mIHRoYXQgbmV3IGNvbHVtbgotIHNlbGVjdCBhbmQgc2hvdyBvbmx5IGNvdW50cnkgYW5kIGxpZmVFeHBNb250aHMKCmBgYHtyfQpnYXBtaW5kZXIgJT4lICAgICAgICAgICAgICAgICAgICAgICAgIyBteSBkZgogIGZpbHRlcih5ZWFyID09IDIwMDcpICU+JSAgICAgICAgICAgIyBoZXJlIEkgZmlsdGVyIGJlY2F1c2UgdGhpcyB5ZWFyIGlzIC4uLi4KICBtdXRhdGUgKGxpZmVFeHBNb250aCA9IGxpZmVFeHAgKiAxMiApICU+JSAjIENyZWF0ZSBhIG5ldyB2YXIKICBhcnJhbmdlKGRlc2MobGlmZUV4cCkpICU+JSAKICBzZWxlY3QgKGNvdW50cnksIGxpZmVFeHBNb250aCkKYGBgCgojIFN1bW1hcml6ZQoKYGBge3J9CmdhcG1pbmRlciAlPiUgCiAgZmlsdGVyKHllYXIgPT0gMTk1NykgJT4lIAogIHN1bW1hcmlzZShtZWRpYW5MaWZlRXhwID0gbWVkaWFuKGxpZmVFeHApKQpgYGAKCkZpbHRlciBmb3IgdGhlIHllYXIgMTk1NywgdGhlbiB1c2UgdGhlIG1lYW4oKSBmdW5jdGlvbiB3aXRoaW4gYSBzdW1tYXJpemUoKSB0byBjYWxjdWxhdGUgdGhlIG1lZGlhbiBsaWZlIGV4cGVjdGFuY3kgaW50byBhIGNvbHVtbiBjYWxsZWQgbWVhbkxpZmVFeHAuCmBgYHtyfQpnYXBtaW5kZXIgJT4lCiAgZmlsdGVyKHllYXIgPT0gMTk1NykgJT4lCiAgc3VtbWFyaXNlKG1lYW5MaWZlRXhwID0gbWVhbihsaWZlRXhwKSwKICAgICAgICAgICAgc2QgPSBzZChsaWZlRXhwKSkKYGBgCgpgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBmaWx0ZXIoeWVhciA9PSAxOTU3KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5MaWZlRXhwID0gbWVhbihsaWZlRXhwKSwKICAgICAgICAgICAgc2QgPSBzZChsaWZlRXhwKSwKICAgICAgICAgICAgbWF4ID0gbWF4KGxpZmVFeHApLAogICAgICAgICAgICBtaW4gPSBtaW4obGlmZUV4cCkpCmBgYAoKV2hpY2ggd2FzIHRoZSBtZWFuIGdwZFBlckNhcCBpbiAxOTU3CgpgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBmaWx0ZXIoeWVhciA9PSAxOTU3KSAlPiUgCiAgbXV0YXRlKGdwZFBlcmNhcEV1cm9zID0gZ2RwUGVyY2FwICogLjg1KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5nZHBFdXJvcyA9IG1lYW4oZ3BkUGVyY2FwRXVyb3MpKQpgYGAKCiMgZ3JvdXBfYnkKCldoYXQgaXMgdGhlIGdkcFBlcmNhdCBieSBjb250aW5lbnQKCmBgYHtyfQpnYXBtaW5kZXIgJT4lCiAgZ3JvdXBfYnkoY29udGluZW50KSAlPiUKICBzdW1tYXJpemUoZ2RwUGVyQ29udE1lZGlhbiA9IG1lZGlhbihnZHBQZXJjYXApKQpgYGAKQ2FsY3VsYXRlIHRoZSBtZWFuIGxpZmUgZXhwZWN0YW5jeSBieSB5ZWFyCgpgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBncm91cF9ieSh5ZWFyKSAlPiUgCiAgc3VtbWFyaXNlKGxpZmVFeHBNZWFuID0gbWVhbihsaWZlRXhwKSkKYGBgCmBgYHtyfQpnYXBtaW5kZXIgJT4lIAogIGdyb3VwX2J5KHllYXIsIGNvbnRpbmVudCkgJT4lIAogIHN1bW1hcmlzZShsaWZlRXhwTWVhbiA9IG1lYW4obGlmZUV4cCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCAKICAgICAgICAgICAgIHkgPSBsaWZlRXhwTWVhbikpICsgCiAgZ2VvbV9saW5lKCkgKyAKICBhZXMoY29sb3IgPSBjb250aW5lbnQpICsKICBleHBhbmRfbGltaXRzKHkgPSAwKQpgYGAKCkNoYW5nZSBvZiB0aGUgZ2RwIGJ5IHllYXIgYW5kIGNvbnRpbmVudAoKYGBge3J9CmdhcG1pbmRlciAlPiUgCiAgZ3JvdXBfYnkoeWVhciwgY29udGluZW50KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5HZHBQZXJjYXAgPSBtZWFuKGdkcFBlcmNhcCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgeSA9IG1lYW5HZHBQZXJjYXAsIGNvbG9yID0gY29udGluZW50KSkgKwogIGdlb21fbGluZSgpICsKICBleHBhbmRfbGltaXRzKHkgPSAwKSArIAogIHNjYWxlX3lfbG9nMTAoKQpgYGAKCgoKCgoKCgojIyBBcnJhbmdlCgpgYGB7cn0KIyBTb3J0IGluIGFzY2VuZGluZyBvcmRlciBvZiBsaWZlRXhwCmdhcG1pbmRlciAlPiUgCiAgYXJyYW5nZShsaWZlRXhwKQogIAoKYGBgCmBgYHtyfQojIFNvcnQgaW4gZGVzY2VuZGluZyBvcmRlciBvZiBsaWZlRXhwCmdhcG1pbmRlciAlPiUgCiAgYXJyYW5nZShkZXNjKGxpZmVFeHApKQpgYGAKClVzZSBmaWx0ZXIoKSB0byBleHRyYWN0IG9ic2VydmF0aW9ucyBmcm9tIGp1c3QgdGhlIHllYXIgMTk1NywgdGhlbiB1c2UgYXJyYW5nZSgpIHRvIHNvcnQgaW4gZGVzY2VuZGluZyBvcmRlciBvZiBwb3B1bGF0aW9uIChwb3ApLgoKCmBgYHtyfQojIEZpbHRlciBmb3IgdGhlIHllYXIgMTk1NywgdGhlbiBhcnJhbmdlIGluIGRlc2NlbmRpbmcgb3JkZXIgb2YgcG9wdWxhdGlvbgpnYXBtaW5kZXIgJT4lIAogIGZpbHRlcih5ZWFyID09IDE5NTcpICU+JSAKICBhcnJhbmdlKGRlc2MocG9wKSkKYGBgCgojIyBNdXRhdGUKClN1cHBvc2Ugd2Ugd2FudCBsaWZlIGV4cGVjdGFuY3kgdG8gYmUgbWVhc3VyZWQgaW4gbW9udGhzIGluc3RlYWQgb2YgeWVhcnM6IHlvdSdkIGhhdmUgdG8gbXVsdGlwbHkgdGhlIGV4aXN0aW5nIHZhbHVlIGJ5IDEyLiBZb3UgY2FuIHVzZSB0aGUgbXV0YXRlKCkgdmVyYiB0byBjaGFuZ2UgdGhpcyBjb2x1bW4sIG9yIHRvIGNyZWF0ZSBhIG5ldyBjb2x1bW4gdGhhdCdzIGNhbGN1bGF0ZWQgdGhpcyB3YXkuCgpgYGB7cn0KIyBVc2UgbXV0YXRlIHRvIGNoYW5nZSBsaWZlRXhwIHRvIGJlIGluIG1vbnRocwpnYXBtaW5kZXIgJT4lIAogICAgICAgIG11dGF0ZShsaWZlRXhwID0gbGlmZUV4cCAqIDEyKQpgYGAKCgpgYGB7cn0KIyBVc2UgbXV0YXRlIHRvIGNyZWF0ZSBhIG5ldyBjb2x1bW4gY2FsbGVkIGxpZmVFeHBNb250aHMKZ2FwbWluZGVyICU+JSAKICAgICAgICBtdXRhdGUobGlmZUV4cE1vbnRocyA9IGxpZmVFeHAgKiAxMikKYGBgCgpJbiB0aGlzIGV4ZXJjaXNlLCB5b3UnbGwgY29tYmluZSBhbGwgdGhyZWUgb2YgdGhlIHZlcmJzIHlvdSd2ZSBsZWFybmVkIGluIHRoaXMgY2hhcHRlciwgdG8gZmluZCB0aGUgY291bnRyaWVzIHdpdGggdGhlIGhpZ2hlc3QgbGlmZSBleHBlY3RhbmN5LCBpbiBtb250aHMsIGluIHRoZSB5ZWFyIDIwMDcuCgpJbiBvbmUgc2VxdWVuY2Ugb2YgcGlwZXMgb24gdGhlIGdhcG1pbmRlciBkYXRhc2V0OgpmaWx0ZXIoKSBmb3Igb2JzZXJ2YXRpb25zIGZyb20gdGhlIHllYXIgMjAwNywKbXV0YXRlKCkgdG8gY3JlYXRlIGEgY29sdW1uIGxpZmVFeHBNb250aHMsIGNhbGN1bGF0ZWQgYXMgMTIgKiBsaWZlRXhwLCBhbmQKYXJyYW5nZSgpIGluIGRlc2NlbmRpbmcgb3JkZXIgb2YgdGhhdCBuZXcgY29sdW1uCgpgYGB7cn0KIyBGaWx0ZXIsIG11dGF0ZSwgYW5kIGFycmFuZ2UgdGhlIGdhcG1pbmRlciBkYXRhc2V0CmdhcG1pbmRlciAlPiUKICBmaWx0ZXIoeWVhciA9PSAyMDA3KSAlPiUKICBtdXRhdGUobGlmZUV4cE1vbnRocyA9IDEyICogbGlmZUV4cCkgJT4lCiAgYXJyYW5nZShkZXNjKGxpZmVFeHBNb250aHMpKQpgYGAKCgojIyBzdW1tYXJpemUKClVzZSB0aGUgbWVkaWFuKCkgZnVuY3Rpb24gd2l0aGluIGEgc3VtbWFyaXplKCkgdG8gZmluZCB0aGUgbWVkaWFuIGxpZmUgZXhwZWN0YW5jeS4gU2F2ZSBpdCBpbnRvIGEgY29sdW1uIGNhbGxlZCBtZWRpYW5MaWZlRXhwLgoKYGBge3J9CmdhcG1pbmRlciAlPiUgCiAgc3VtbWFyaXNlKG1lZGlhbkxpZmVFeHAgPSBtZWRpYW4obGlmZUV4cCkpCmBgYAoKRmlsdGVyIGZvciB0aGUgeWVhciAxOTU3LCB0aGVuIHVzZSB0aGUgbWVkaWFuKCkgZnVuY3Rpb24gd2l0aGluIGEgc3VtbWFyaXplKCkgdG8gY2FsY3VsYXRlIHRoZSBtZWRpYW4gbGlmZSBleHBlY3RhbmN5IGludG8gYSBjb2x1bW4gY2FsbGVkIG1lZGlhbkxpZmVFeHAuCgpgYGB7cn0KZ2FwbWluZGVyICU+JQogIGZpbHRlcih5ZWFyID09IDE5NTcpICU+JQogIHN1bW1hcml6ZShtZWRpYW5MaWZlRXhwID0gbWVkaWFuKGxpZmVFeHApKQpgYGAKCkZpbmQgYm90aCB0aGUgbWVkaWFuIGxpZmUgZXhwZWN0YW5jeSAobGlmZUV4cCkgYW5kIHRoZSBtYXhpbXVtIEdEUCBwZXIgY2FwaXRhIChnZHBQZXJjYXApIGluIHRoZSB5ZWFyIDE5NTcsIGNhbGxpbmcgdGhlbSBtZWRpYW5MaWZlRXhwIGFuZCBtYXhHZHBQZXJjYXAgcmVzcGVjdGl2ZWx5LiBZb3UgY2FuIHVzZSB0aGUgbWF4KCkgZnVuY3Rpb24gdG8gZmluZCB0aGUgbWF4aW11bS4KCmBgYHtyfQpnYXBtaW5kZXIgJT4lCiAgZmlsdGVyKHllYXIgPT0gMTk1NykgJT4lIHN1bW1hcml6ZShtZWRpYW5MaWZlRXhwID0gbWVkaWFuKGxpZmVFeHApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4R2RwUGVyY2FwID0gbWF4KGdkcFBlcmNhcCkpCmBgYAojIyBUaGUgZ3JvdXBfYnkgdmVyYgoKYGBge3J9CmdhcG1pbmRlciAlPiUgCiAgZ3JvdXBfYnkoeWVhcikgJT4lIAogIHN1bW1hcmlzZShtZWFuTGlmZUV4cCA9IG1lYW4obGlmZUV4cCksIAogICAgICAgICAgICB0b3RhbFBvcCA9IHN1bShwb3ApKQpgYGAKYGBge3J9CmdhcG1pbmRlciAlPiUgCiAgZ3JvdXBfYnkoeWVhciwgY29udGluZW50KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5MaWZlRXhwID0gbWVhbihsaWZlRXhwKSwgCiAgICAgICAgICAgIHRvdGFsUG9wID0gc3VtKHBvcCkpCmBgYApgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBncm91cF9ieSh5ZWFyLCBjb250aW5lbnQpICU+JSAKICBzdW1tYXJpc2UobWVhbkxpZmVFeHAgPSBtZWFuKGxpZmVFeHApLCAKICAgICAgICAgICAgdG90YWxQb3AgPSBzdW0ocG9wKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIAogICAgICAgICAgICAgeSA9IG1lYW5MaWZlRXhwLCAKICAgICAgICAgICAgIHNpemUgPSB0b3RhbFBvcCwgCiAgICAgICAgICAgICBjb2xvciA9IGNvbnRpbmVudCkpICsgCiAgZ2VvbV9saW5lKCkKYGBgCgoKRXhlcmNpc2UKCkZpbmQgdGhlIG1lZGlhbiBsaWZlIGV4cGVjdGFuY3kgKGxpZmVFeHApIGFuZCBtYXhpbXVtIEdEUCBwZXIgY2FwaXRhIChnZHBQZXJjYXApIHdpdGhpbiBlYWNoIHllYXIsIHNhdmluZyB0aGVtIGludG8gbWVkaWFuTGlmZUV4cCBhbmQgbWF4R2RwUGVyY2FwLCByZXNwZWN0aXZlbHkuCgpgYGB7cn0KZ2FwbWluZGVyICU+JSAKICBncm91cF9ieSh5ZWFyKSAlPiUgCiAgc3VtbWFyaXplKG1lZGlhbkxpZmVFeHAgPSBtZWRpYW4obGlmZUV4cCksCiAgICAgICAgICAgIG1heEdkcFBlcmNhcCA9IG1heChnZHBQZXJjYXApKQpgYGAKCkZpbHRlciB0aGUgZ2FwbWluZGVyIGRhdGEgZm9yIHRoZSB5ZWFyIDE5NTcuIFRoZW4gZmluZCB0aGUgbWVkaWFuIGxpZmUgZXhwZWN0YW5jeSAobGlmZUV4cCkgYW5kIG1heGltdW0gR0RQIHBlciBjYXBpdGEgKGdkcFBlcmNhcCkgd2l0aGluIGVhY2ggY29udGluZW50LCBzYXZpbmcgdGhlbSBpbnRvIG1lZGlhbkxpZmVFeHAgYW5kIG1heEdkcFBlcmNhcCwgcmVzcGVjdGl2ZWx5LgoKYGBge3J9CmdhcG1pbmRlciAlPiUgCiAgICAgICAgZmlsdGVyKHllYXIgPT0gMTk1NykgJT4lIAogICAgICAgIGdyb3VwX2J5KGNvbnRpbmVudCkgJT4lIAogICAgICAgIHN1bW1hcml6ZShtZWRpYW5MaWZlRXhwID0gbWVkaWFuKGxpZmVFeHApLCAKICAgICAgICAgICAgICAgICAgbWF4R2RwUGVyQ2FwID0gbWF4KGdkcFBlcmNhcCkpCmBgYAoKRmluZCB0aGUgbWVkaWFuIGxpZmUgZXhwZWN0YW5jeSAobGlmZUV4cCkgYW5kIG1heGltdW0gR0RQIHBlciBjYXBpdGEgKGdkcFBlcmNhcCkgd2l0aGluIGVhY2ggY29tYmluYXRpb24gb2YgY29udGluZW50IGFuZCB5ZWFyLCBzYXZpbmcgdGhlbSBpbnRvIG1lZGlhbkxpZmVFeHAgYW5kIG1heEdkcFBlcmNhcCwgcmVzcGVjdGl2ZWx5LgoKYGBge3J9CmdhcG1pbmRlciAlPiUgCiAgICAgICAgZ3JvdXBfYnkoY29udGluZW50LCB5ZWFyKSAlPiUgCiAgICAgICAgc3VtbWFyaXplKG1lZGlhbkxpZmVFeHAgPSBtZWRpYW4obGlmZUV4cCksIAogICAgICAgICAgICAgICAgICBtYXhHZHBQZXJjYXAgPSBtYXgoZ2RwUGVyY2FwKSkKYGBgCgojIFZpc3VhbGl6aW5nCgpWaXN1YWxpemUgcG9wdWxhdGlvbiBvdmVyIHRpbWUKCmBgYHtyfQpnYXBtaW5kZXIgJT4lCiAgZ3JvdXBfYnkoeWVhcikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbFBvcCA9IHN1bShwb3ApKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gdG90YWxQb3AgKSkgKyAKICBnZW9tX3BvaW50KCkKYGBgCmBgYHtyfQpnYXBtaW5kZXIgJT4lCiAgZ3JvdXBfYnkoeWVhcikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbFBvcCA9IHN1bShwb3ApKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gdG90YWxQb3AgKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBleHBhbmRfbGltaXRzKHkgPSAwKQpgYGAKCmBgYHtyfQpnYXBtaW5kZXIgJT4lCiAgZ3JvdXBfYnkoeWVhciwgY29udGluZW50KSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsUG9wID0gc3VtKHBvcCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCAKICAgICAgICAgICAgIHkgPSB0b3RhbFBvcCApKSArIAogIGdlb21fcG9pbnQoKSArIAogIGV4cGFuZF9saW1pdHMoeSA9IDApCmBgYApgYGB7cn0KZ2FwbWluZGVyICU+JQogIGdyb3VwX2J5KHllYXIsIGNvbnRpbmVudCkgJT4lIAogIHN1bW1hcmlzZSh0b3RhbFBvcCA9IHN1bShwb3ApKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gdG90YWxQb3AsIAogICAgICAgICAgICAgY29sb3IgPSBjb250aW5lbnQpKSArIAogIGdlb21fcG9pbnQoKSArIAogIGV4cGFuZF9saW1pdHMoeSA9IDApCmBgYApgYGB7cn0KZ2FwbWluZGVyICU+JQogIGdyb3VwX2J5KHllYXIsIGNvbnRpbmVudCkgJT4lIAogIHN1bW1hcmlzZSh0b3RhbFBvcCA9IHN1bShwb3ApKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gdG90YWxQb3AsIAogICAgICAgICAgICAgY29sb3IgPSBjb250aW5lbnQpKSArIAogIGdlb21fcG9pbnQoKSArIAogIGV4cGFuZF9saW1pdHMoeSA9IDApICsgCiAgc2NhbGVfeV9sb2cxMCgpCmBgYApVc2UgdGhlIGJ5X3llYXIgZGF0YXNldCB0byBjcmVhdGUgYSBzY2F0dGVyIHBsb3Qgc2hvd2luZyB0aGUgY2hhbmdlIG9mIG1lZGlhbiBsaWZlIGV4cGVjdGFuY3kgb3ZlciB0aW1lLCB3aXRoIHllYXIgb24gdGhlIHgtYXhpcyBhbmQgbWVkaWFuTGlmZUV4cCBvbiB0aGUgeS1heGlzLiBCZSBzdXJlIHRvIGFkZCBleHBhbmRfbGltaXRzKHkgPSAwKSB0byBtYWtlIHN1cmUgdGhlIHBsb3QncyB5LWF4aXMgaW5jbHVkZXMgemVyby4KCgoKYGBge3J9CmJ5X3llYXIgPC0gZ2FwbWluZGVyICU+JQogIGdyb3VwX2J5KHllYXIpICU+JQogIHN1bW1hcml6ZShtZWRpYW5MaWZlRXhwID0gbWVkaWFuKGxpZmVFeHApLAogICAgICAgICAgICBtYXhHZHBQZXJjYXAgPSBtYXgoZ2RwUGVyY2FwKSkKCiMgQ3JlYXRlIGEgc2NhdHRlciBwbG90IHNob3dpbmcgdGhlIGNoYW5nZSBpbiBtZWRpYW5MaWZlRXhwIG92ZXIgdGltZQpieV95ZWFyICU+JSAKICAgICAgICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gbWVkaWFuTGlmZUV4cCkpICsgCiAgICAgICAgZ2VvbV9wb2ludCgpICsKICAgICAgICBleHBhbmRfbGltaXRzKHkgPSAwKQpgYGAKClN1bW1hcml6ZSB0aGUgZ2FwbWluZGVyIGRhdGFzZXQgYnkgY29udGluZW50IGFuZCB5ZWFyLCBmaW5kaW5nIHRoZSBtZWRpYW4gR0RQIHBlciBjYXBpdGEgKGdkcFBlcmNhcCkgd2l0aGluIGVhY2ggYW5kIHB1dHRpbmcgaXQgaW50byBhIGNvbHVtbiBjYWxsZWQgbWVkaWFuR2RwUGVyY2FwLiBVc2UgdGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IgPC0gdG8gc2F2ZSB0aGlzIHN1bW1hcml6ZWQgZGF0YSBhcyBieV95ZWFyX2NvbnRpbmVudC4KQ3JlYXRlIGEgc2NhdHRlciBwbG90IHNob3dpbmcgdGhlIGNoYW5nZSBpbiBtZWRpYW5HZHBQZXJjYXAgYnkgY29udGluZW50IG92ZXIgdGltZS4gVXNlIGNvbG9yIHRvIGRpc3Rpbmd1aXNoIGJldHdlZW4gY29udGluZW50cywgYW5kIGJlIHN1cmUgdG8gYWRkIGV4cGFuZF9saW1pdHMoeSA9IDApIHNvIHRoYXQgdGhlIHktYXhpcyBzdGFydHMgYXQgemVyby4KCmBgYHtyfQojIFN1bW1hcml6ZSBtZWRpYW5HZHBQZXJjYXAgd2l0aGluIGVhY2ggY29udGluZW50IHdpdGhpbiBlYWNoIHllYXI6IGJ5X3llYXJfY29udGluZW50CmJ5X3llYXJfY29udGluZW50IDwtIGdhcG1pbmRlciAlPiUgCiAgICAgICAgZ3JvdXBfYnkoeWVhciwgY29udGluZW50KSAlPiUgCiAgICAgICAgc3VtbWFyaXplKG1lZGlhbkdkcFBlcmNhcCA9IG1lZGlhbihnZHBQZXJjYXApKQoKIyBQbG90IHRoZSBjaGFuZ2UgaW4gbWVkaWFuR2RwUGVyY2FwIGluIGVhY2ggY29udGluZW50IG92ZXIgdGltZQpieV95ZWFyX2NvbnRpbmVudCAlPiUgCiAgICAgICAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IG1lZGlhbkdkcFBlcmNhcCwgY29sb3I9IGNvbnRpbmVudCkpICsKICAgICAgICBnZW9tX3BvaW50KCkgKyAKICAgICAgICBleHBhbmRfbGltaXRzKHkgPSAwKQpgYGAK