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