Due Date: Sunday, March 24th
Keyboard Shortcuts:
- Assignment operator (<-) is
Alt+- for Windows and Option+- for Mac
- Insert new code chunk
Ctrl+Alt+I for Windows and Command+Option+I for Mac
- Run a line of code
Ctrl+Enter for Windows and Command+Enter for Mac
- Run all the code within a chunk
Ctrl+Shift+Enter for Windows and Command+Shift+Enter for Mac
- Insert a pipe operator (%>%)
Ctrl+Shift+M for Windows and Command+Shift+M for Mac
General Instructions
- Use the cheatsheets and the keyboard shortcuts as you work through the assignment.
- Each task should be answered right below the question.
- The assignment should be submitted via a shareable github link on the assignments channel in Slack.
- Make sure the notebook is neatly formatted and looks good when you preview it.
Task set 1: Data types and structures
- List the 4 most common (data) types of atomic vectors.
- Answer: CHar, Int, Double, Logical
- Create atomic vectors of the 4 common types covered in class. Print their length and type.
[1] "double"
- List the heirarchy of data types for coercion
- Answer: character, double, integer, logical
- Explain why the output of following bits of code is TRUE (explain what is happening in terms of coercion):
[1] TRUE
Answer: == does a comparison and returns T/F. For coercion, 1 is converted to character.
[1] TRUE
Answer: FALSE is converted to 0
- Create a list that holds the 4 common types of atomic vectors you created in task 2.
[[1]]
[1] "Hello" "Test"
[[2]]
[1] 14 15
[[3]]
[1] 1 3
[[4]]
[1] TRUE FALSE
- Create a data frame with 3 columns and 5 rows using the
data.frame() function
- Create the same data frame as above using
tibble() function
- Use the
str(), class() and or glimpse() command to see the difference between the dataframe and tibble create in 4 and 5.
Observations: 5
Variables: 3
$ x [3m[38;5;246m<int>[39m[23m 1, 2, 3, 4, 5
$ y [3m[38;5;246m<int>[39m[23m 11, 12, 13, 14, 15
$ z [3m[38;5;246m<int>[39m[23m 16, 17, 18, 19, 20
Observations: 5
Variables: 3
$ x [3m[38;5;246m<int>[39m[23m 1, 2, 3, 4, 5
$ y [3m[38;5;246m<int>[39m[23m 11, 12, 13, 14, 15
$ z [3m[38;5;246m<int>[39m[23m 16, 17, 18, 19, 20
Fill in the blanks.
- A data frame is a 2__ dimensionsional data structure in R that consists of list__ of _equal__ length
- What is the difference between an atomic vector and a list?
- Answer: atomic verctor is a 1 dimensional array of a single data type - homogeneous. List is also 1d but can be a combimation of different data types - heterogeneous.
Task set 2: Data manipulation using dplyr
INSTRUCTIONS: You will be using the tidyverse and nycflights13 packages for the next set of tasks. Refer to the documentation on tidyverse.org or use the help pages if you do not understand a function fully.
- Load the tidyverse and nycflights13 packages.
library(tidyverse)
library(nycflights13)
Describe two ways in which you can use RStudio confirm that a package has been loaded into your current R session? (Hint: One of them is a dropdown menu and the other a list of checkboxes)
- Answer: 1. Global enviroment dropdown. 2. installed.packages()
Use the distinct() command to identify the unique combinations of airline carriers and origin airports in the flights data.
- Use the
one_of() helper function to select the following columns - year, month, day, dep_time, sched_dep_time, dep_delay, arr_time, from the flights data.
- Use the
slice() function to slice the first 10 rows in the flights data.
- Perform the same operation as the previous task but this time use
filter(). (Hint: Search for how to get the row numbers of a tibble)
- Use the
top_n() command to identify the top 5 flights out of NYC that experienced the greatest arrival delays in 2013.
- Use
top_n() along with arrange() and slice() to pull out the 50th most delayed departure from NYC in 2013 (Not all 50, just the 50th).
- Do the same thing as the previous task using
row_number()
- and
dense_rank()
The result from row_number() and top_n() are the same, while that from dense_rank() is different. Why?
- Answer: dense rank assigns the same rank for the same value of dep_delay, whereas the others are sequentially ranked
Find the top 10 airline carrier that had the highest average departure delays in 2013 using group_by(), summarise() and other functions you have learnt previously.
- Use
group_by() with mutate() to create a new variable called comparativeDelay which is the difference between departure delay and the average delay in each origin airport for every hour in 2013 (checkout the time_hour variable in the flights data). Store the result in a variable called comparativeDelays.
flights %>%
group_by(origin, hour) %>%
mutate(avgDelay = mean(dep_delay, na.rm = T),
comparativeDelay = dep_delay - mean(dep_delay, na.rm = T)) %>%
select(1:3, carrier, hour, flight, tailnum, dep_delay, avgDelay, comparativeDelay)
Adding missing grouping variables: `origin`
- Now group the
comparativeDelays tibble by carriers to print the top 10 airlines with the greatest average comparative delays.
flights %>%
group_by(origin, hour) %>%
mutate(avgDelay = mean(dep_delay, na.rm = T),
comparativeDelay = dep_delay - mean(dep_delay, na.rm = T)) %>%
select(1:3, carrier, hour, flight, tailnum, dep_delay, avgDelay, comparativeDelay) %>%
group_by(carrier) %>%
summarise(avgComparativeDelay = mean(comparativeDelay, na.rm = T)) %>%
top_n(10, avgComparativeDelay) %>%
arrange(desc(avgComparativeDelay))
Adding missing grouping variables: `origin`
- Use
group_by() with filter to print the 5 most delayed flights from each origin. Your printed tibble should have 15 rows.
The air authority in NY wants to penalize carriers for departure delays. Which of the three metrics (task 1, 3 or 4) would you recommend they use to identify the airlines to penalize. Why?
- Answer: Average Comparative Delay seems to be the best, as it summarises by origin and hour
Task set 3: R markdown
- Modify the text below as per the prompt
- Underline me
- Make me bold
Make me a block quote
- Make me italic
Strike through me
Create a level three header called “My level 3 header” under this line ###My level 3 header
Modify the content below so that the bullet points (unordered list) render correctly
Messy bullet points
- Use chunk options to hide the output and the code from the chunk below in the previewed notebook.
LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMSINCmF1dGhvcjogVmluUGhpbA0KZGF0ZTogIkRhdGUgY3JlYXRlZDogYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgaGlnaGxpZ2h0OiBrYXRlDQogICAgc21hcnQ6IHllcw0KICAgIHRoZW1lOiBjb3Ntbw0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCioqRHVlIERhdGUqKjogU3VuZGF5LCBNYXJjaCAyNHRoDQoNCioqS2V5Ym9hcmQgU2hvcnRjdXRzKio6DQoNCjEuIEFzc2lnbm1lbnQgb3BlcmF0b3IgKDwtKSBpcyBgQWx0Ky1gIGZvciBXaW5kb3dzIGFuZCBgT3B0aW9uKy1gIGZvciBNYWMNCjIuIEluc2VydCBuZXcgY29kZSBjaHVuayBgQ3RybCtBbHQrSWAgZm9yIFdpbmRvd3MgYW5kIGBDb21tYW5kK09wdGlvbitJYCBmb3IgTWFjDQozLiBSdW4gYSBsaW5lIG9mIGNvZGUgYEN0cmwrRW50ZXJgIGZvciBXaW5kb3dzIGFuZCBgQ29tbWFuZCtFbnRlcmAgZm9yIE1hYw0KNC4gUnVuIGFsbCB0aGUgY29kZSB3aXRoaW4gYSBjaHVuayBgQ3RybCtTaGlmdCtFbnRlcmAgZm9yIFdpbmRvd3MgYW5kIGBDb21tYW5kK1NoaWZ0K0VudGVyYCBmb3IgTWFjDQo1LiBJbnNlcnQgYSBwaXBlIG9wZXJhdG9yICglPiUpIGBDdHJsK1NoaWZ0K01gIGZvciBXaW5kb3dzIGFuZCBgQ29tbWFuZCtTaGlmdCtNYCBmb3IgTWFjDQoNCioqR2VuZXJhbCBJbnN0cnVjdGlvbnMqKg0KDQoxLiBVc2UgdGhlIGNoZWF0c2hlZXRzIGFuZCB0aGUga2V5Ym9hcmQgc2hvcnRjdXRzIGFzIHlvdSB3b3JrIHRocm91Z2ggdGhlIGFzc2lnbm1lbnQuDQoyLiBFYWNoIHRhc2sgc2hvdWxkIGJlIGFuc3dlcmVkIHJpZ2h0IGJlbG93IHRoZSBxdWVzdGlvbi4NCjMuIFRoZSBhc3NpZ25tZW50IHNob3VsZCBiZSBzdWJtaXR0ZWQgdmlhIGEgc2hhcmVhYmxlIGdpdGh1YiBsaW5rIG9uIHRoZSBhc3NpZ25tZW50cyBjaGFubmVsIGluIFNsYWNrLg0KNC4gTWFrZSBzdXJlIHRoZSBub3RlYm9vayBpcyBuZWF0bHkgZm9ybWF0dGVkIGFuZCBsb29rcyBnb29kIHdoZW4geW91IHByZXZpZXcgaXQuDQoNCiMjVGFzayBzZXQgMTogRGF0YSB0eXBlcyBhbmQgc3RydWN0dXJlcw0KMS4gTGlzdCB0aGUgNCBtb3N0IGNvbW1vbiAoZGF0YSkgdHlwZXMgb2YgYXRvbWljIHZlY3RvcnMuDQogICAgKyBBbnN3ZXI6IENIYXIsIEludCwgRG91YmxlLCBMb2dpY2FsDQoNCjIuIENyZWF0ZSBhdG9taWMgdmVjdG9ycyBvZiB0aGUgNCBjb21tb24gdHlwZXMgY292ZXJlZCBpbiBjbGFzcy4gUHJpbnQgdGhlaXIgbGVuZ3RoIGFuZCB0eXBlLg0KDQpgYGB7cn0NCnZDaGFyIDwtIGMoIkhlbGxvIiwgIlRlc3QiKQ0KdkludCA8LSBjKDFMLCAzTCkNCnZEb3ViIDwtIGMoMTQsIDE1KQ0KdkxvZyA8LSBjKFQsRikNCg0KdHlwZW9mKHZDaGFyKQ0KdHlwZW9mKHZJbnQpDQp0eXBlb2YodkRvdWIpDQp0eXBlb2YodkxvZykNCg0KbGVuZ3RoKHZDaGFyKQ0KbGVuZ3RoKHZJbnQpDQpsZW5ndGgodkRvdWIpDQpsZW5ndGgodkxvZykNCmBgYA0KDQozLiBMaXN0IHRoZSBoZWlyYXJjaHkgb2YgZGF0YSB0eXBlcyBmb3IgY29lcmNpb24NCiAgICArIEFuc3dlcjogY2hhcmFjdGVyLCBkb3VibGUsIGludGVnZXIsIGxvZ2ljYWwNCg0KNC4gRXhwbGFpbiB3aHkgdGhlIG91dHB1dCBvZiBmb2xsb3dpbmcgYml0cyBvZiBjb2RlIGlzIFRSVUUgKGV4cGxhaW4gd2hhdCBpcyBoYXBwZW5pbmcgaW4gdGVybXMgb2YgY29lcmNpb24pOiANCg0KYGBge3J9DQoiMSIgPT0gMQ0KYGBgDQpBbnN3ZXI6ID09IGRvZXMgYSBjb21wYXJpc29uIGFuZCByZXR1cm5zIFQvRi4gDQpGb3IgY29lcmNpb24sIDEgaXMgY29udmVydGVkIHRvIGNoYXJhY3Rlci4NCg0KYGBge3J9DQpGQUxTRSA9PSAwDQpgYGANCkFuc3dlcjogRkFMU0UgaXMgY29udmVydGVkIHRvIDANCg0KMy4gQ3JlYXRlIGEgbGlzdCB0aGF0IGhvbGRzIHRoZSA0IGNvbW1vbiB0eXBlcyBvZiBhdG9taWMgdmVjdG9ycyB5b3UgY3JlYXRlZCBpbiB0YXNrIDIuDQoNCmBgYHtyfQ0KbFZlY3RvcnMgPC0gbGlzdCh2Q2hhciwgdkRvdWIsIHZJbnQsIHZMb2cpDQpsVmVjdG9ycw0KYGBgDQo0LiBDcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggMyBjb2x1bW5zIGFuZCA1IHJvd3MgdXNpbmcgdGhlIGBkYXRhLmZyYW1lKClgIGZ1bmN0aW9uDQoNCmBgYHtyfQ0KZGZUZXN0IDwtIGRhdGEuZnJhbWUoeD1jKDE6NSksIHk9YygxMToxNSksIHo9YygxNjoyMCkpDQpkZlRlc3QNCmBgYA0KNS4gQ3JlYXRlIHRoZSBzYW1lIGRhdGEgZnJhbWUgYXMgYWJvdmUgdXNpbmcgYHRpYmJsZSgpYCBmdW5jdGlvbg0KDQpgYGB7cn0NCnRiVGVzdCA8LSB0aWJibGUoeCA9IDE6NSwgeSA9IDExOjE1LCB6ID0gMTY6MjApDQp0YlRlc3QNCmBgYA0KDQo2LiBVc2UgdGhlIGBzdHIoKWAsIGBjbGFzcygpYCBhbmQgb3IgYGdsaW1wc2UoKWAgY29tbWFuZCB0byBzZWUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgZGF0YWZyYW1lIGFuZCB0aWJibGUgY3JlYXRlIGluIDQgYW5kIDUuDQoNCmBgYHtyfQ0Kc3RyKGRmVGVzdCkNCnN0cih0YlRlc3QpDQoNCmNsYXNzKGRmVGVzdCkNCmNsYXNzKHRiVGVzdCkNCg0KZ2xpbXBzZShkZlRlc3QpDQpnbGltcHNlKHRiVGVzdCkNCmBgYA0KDQo3LiBGaWxsIGluIHRoZSBibGFua3MuIA0KDQogICAgKyBBIGRhdGEgZnJhbWUgaXMgYSBfMl9fXyBkaW1lbnNpb25zaW9uYWwgZGF0YSBzdHJ1Y3R1cmUgaW4gUiB0aGF0IGNvbnNpc3RzIG9mIF9saXN0X19fIG9mIF9lcXVhbF9fIGxlbmd0aA0KDQo4LiBXaGF0IGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gYW4gYXRvbWljIHZlY3RvciBhbmQgYSBsaXN0Pw0KICAgICsgQW5zd2VyOiBhdG9taWMgdmVyY3RvciBpcyBhIDEgZGltZW5zaW9uYWwgYXJyYXkgb2YgYSBzaW5nbGUgZGF0YSB0eXBlIC0gaG9tb2dlbmVvdXMuIExpc3QgaXMgYWxzbyAxZCBidXQgY2FuIGJlIGEgY29tYmltYXRpb24gb2YgZGlmZmVyZW50IGRhdGEgdHlwZXMgLSBoZXRlcm9nZW5lb3VzLg0KDQoNCiMjVGFzayBzZXQgMjogRGF0YSBtYW5pcHVsYXRpb24gdXNpbmcgZHBseXINCg0KKipJTlNUUlVDVElPTlMqKjogWW91IHdpbGwgYmUgdXNpbmcgdGhlIHRpZHl2ZXJzZSBhbmQgbnljZmxpZ2h0czEzIHBhY2thZ2VzIGZvciB0aGUgbmV4dCBzZXQgb2YgdGFza3MuIFJlZmVyIHRvIHRoZSBkb2N1bWVudGF0aW9uIG9uIHRpZHl2ZXJzZS5vcmcgb3IgdXNlIHRoZSBoZWxwIHBhZ2VzIGlmIHlvdSBkbyBub3QgdW5kZXJzdGFuZCBhIGZ1bmN0aW9uIGZ1bGx5Lg0KDQoxLiBMb2FkIHRoZSB0aWR5dmVyc2UgYW5kIG55Y2ZsaWdodHMxMyBwYWNrYWdlcy4NCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobnljZmxpZ2h0czEzKQ0KYGBgDQoNCjIuIERlc2NyaWJlIHR3byB3YXlzIGluIHdoaWNoIHlvdSBjYW4gdXNlIFJTdHVkaW8gY29uZmlybSB0aGF0IGEgcGFja2FnZSBoYXMgYmVlbiBsb2FkZWQgaW50byB5b3VyIGN1cnJlbnQgUiBzZXNzaW9uPyAoSGludDogT25lIG9mIHRoZW0gaXMgYSBkcm9wZG93biBtZW51IGFuZCB0aGUgb3RoZXIgYSBsaXN0IG9mIGNoZWNrYm94ZXMpDQoNCiAgICArIEFuc3dlcjogMS4gR2xvYmFsIGVudmlyb21lbnQgZHJvcGRvd24uIDIuIGluc3RhbGxlZC5wYWNrYWdlcygpDQoNCjMuIFVzZSB0aGUgYGRpc3RpbmN0KClgIGNvbW1hbmQgdG8gaWRlbnRpZnkgdGhlIHVuaXF1ZSBjb21iaW5hdGlvbnMgb2YgYWlybGluZSBjYXJyaWVycyBhbmQgb3JpZ2luIGFpcnBvcnRzIGluIHRoZSBmbGlnaHRzIGRhdGEuDQoNCmBgYHtyfQ0KZmxpZ2h0cw0KZGlzdGluY3QoZmxpZ2h0cywgY2Fycmllciwgb3JpZ2luICkgJT4lDQogIGFycmFuZ2UoY2Fycmllciwgb3JpZ2luKQ0KYGBgDQoNCjQuIFVzZSB0aGUgYG9uZV9vZigpYCBoZWxwZXIgZnVuY3Rpb24gdG8gc2VsZWN0IHRoZSBmb2xsb3dpbmcgY29sdW1ucyAtICB5ZWFyLCBtb250aCwgZGF5LCBkZXBfdGltZSwgc2NoZWRfZGVwX3RpbWUsIGRlcF9kZWxheSwgYXJyX3RpbWUsIGZyb20gdGhlIGZsaWdodHMgZGF0YS4NCg0KYGBge3J9DQpmbGlnaHRzICU+JSANCiAgc2VsZWN0KG9uZV9vZihjKCJ5ZWFyIiwgIm1vbnRoIiwgImRheSIsICJkZXBfdGltZSIsICJzY2hlZF9kZXBfdGltZSIsICJkZXBfZGVsYXkiLCAiYXJyX3RpbWUiKSkpDQoNCmBgYA0KDQo1LiBVc2UgdGhlIGBzbGljZSgpYCBmdW5jdGlvbiB0byBzbGljZSB0aGUgZmlyc3QgMTAgcm93cyBpbiB0aGUgZmxpZ2h0cyBkYXRhLg0KDQpgYGB7cn0NCmZsaWdodHMgJT4lIA0KICBzbGljZSgxOjEwKQ0KYGBgDQoNCjYuIFBlcmZvcm0gdGhlIHNhbWUgb3BlcmF0aW9uIGFzIHRoZSBwcmV2aW91cyB0YXNrIGJ1dCB0aGlzIHRpbWUgdXNlIGBmaWx0ZXIoKWAuIChIaW50OiBTZWFyY2ggZm9yIGhvdyB0byBnZXQgdGhlIHJvdyBudW1iZXJzIG9mIGEgdGliYmxlKQ0KDQpgYGB7cn0NCmZsaWdodHMgJT4lIA0KICBmaWx0ZXIoYmV0d2Vlbihyb3dfbnVtYmVyKCksIDEsIDEwKSkNCmBgYA0KDQo3LiBVc2UgdGhlIGB0b3BfbigpYCBjb21tYW5kIHRvIGlkZW50aWZ5IHRoZSB0b3AgNSBmbGlnaHRzIG91dCBvZiBOWUMgdGhhdCBleHBlcmllbmNlZCB0aGUgZ3JlYXRlc3QgYXJyaXZhbCBkZWxheXMgaW4gMjAxMy4NCg0KYGBge3J9DQpmbGlnaHRzICU+JSANCiAgdG9wX24oNSwgYXJyX2RlbGF5KSAlPiUgDQogIGFycmFuZ2UoZGVzYyhhcnJfZGVsYXkpKQ0KYGBgDQoNCjguIFVzZSBgdG9wX24oKWAgYWxvbmcgd2l0aCBgYXJyYW5nZSgpYCBhbmQgYHNsaWNlKClgIHRvIHB1bGwgb3V0IHRoZSA1MHRoIG1vc3QgZGVsYXllZCBkZXBhcnR1cmUgZnJvbSBOWUMgaW4gMjAxMyAoTm90IGFsbCA1MCwganVzdCB0aGUgNTB0aCkuIA0KYGBge3J9DQpmbGlnaHRzICU+JSANCiAgdG9wX24oNTAsIGRlcF9kZWxheSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoZGVwX2RlbGF5KSkgJT4lIA0KICBzbGljZSg1MCkNCmBgYA0KDQo5LiBEbyB0aGUgc2FtZSB0aGluZyBhcyB0aGUgcHJldmlvdXMgdGFzayB1c2luZyANCiAgICArIGByb3dfbnVtYmVyKClgDQogICAgKyBhbmQgYGRlbnNlX3JhbmsoKWANCmBgYHtyfQ0KZmxpZ2h0cyAlPiUgDQogIGFycmFuZ2UoZGVzYyhkZXBfZGVsYXkpKSAlPiUgDQogIGZpbHRlcihyb3dfbnVtYmVyKCkgPT0gNTApDQpgYGANCg0KYGBge3J9DQpmbGlnaHRzICU+JSANCiAgZmlsdGVyKGRlbnNlX3JhbmsoZGVzYyhkZXBfZGVsYXkpKSA9PSA1MCkNCmBgYA0KDQoNCjEwLiBUaGUgcmVzdWx0IGZyb20gYHJvd19udW1iZXIoKWAgYW5kIGB0b3BfbigpYCBhcmUgdGhlIHNhbWUsIHdoaWxlIHRoYXQgZnJvbSBgZGVuc2VfcmFuaygpYCBpcyBkaWZmZXJlbnQuIFdoeT8NCg0KICAgICsgQW5zd2VyOiBkZW5zZSByYW5rIGFzc2lnbnMgdGhlIHNhbWUgcmFuayBmb3IgdGhlIHNhbWUgdmFsdWUgb2YgZGVwX2RlbGF5LCB3aGVyZWFzIHRoZSBvdGhlcnMgYXJlIHNlcXVlbnRpYWxseSByYW5rZWQNCg0KMTEuIEZpbmQgdGhlIHRvcCAxMCBhaXJsaW5lIGNhcnJpZXIgdGhhdCBoYWQgdGhlIGhpZ2hlc3QgYXZlcmFnZSBkZXBhcnR1cmUgZGVsYXlzIGluIDIwMTMgdXNpbmcgYGdyb3VwX2J5KClgLCBgc3VtbWFyaXNlKClgIGFuZCBvdGhlciBmdW5jdGlvbnMgeW91IGhhdmUgbGVhcm50IHByZXZpb3VzbHkuDQpgYGB7cn0NCmZsaWdodHMgJT4lIA0KICBncm91cF9ieShjYXJyaWVyKSAlPiUgDQogIHN1bW1hcmlzZShhdmdEZXBEZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFQpKSAlPiUgDQogIHRvcF9uKDEwLCBhdmdEZXBEZWxheSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoYXZnRGVwRGVsYXkpKSANCiAgDQpgYGANCg0KMTIuIFVzZSBgZ3JvdXBfYnkoKWAgd2l0aCBgbXV0YXRlKClgIHRvIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBjYWxsZWQgYGNvbXBhcmF0aXZlRGVsYXlgIHdoaWNoIGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gZGVwYXJ0dXJlIGRlbGF5IGFuZCB0aGUgYXZlcmFnZSBkZWxheSBpbiBlYWNoIG9yaWdpbiBhaXJwb3J0IGZvciBldmVyeSBob3VyIGluIDIwMTMgKGNoZWNrb3V0IHRoZSBgdGltZV9ob3VyYCB2YXJpYWJsZSBpbiB0aGUgZmxpZ2h0cyBkYXRhKS4gU3RvcmUgdGhlIHJlc3VsdCBpbiBhIHZhcmlhYmxlIGNhbGxlZCBgY29tcGFyYXRpdmVEZWxheXNgLg0KYGBge3J9DQpmbGlnaHRzICU+JSANCiAgZ3JvdXBfYnkob3JpZ2luLCBob3VyKSAlPiUgDQogIG11dGF0ZShhdmdEZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFQpLCANCiAgICAgICAgIGNvbXBhcmF0aXZlRGVsYXkgPSBkZXBfZGVsYXkgLSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUKSkgJT4lIA0KICBzZWxlY3QoMTozLCBjYXJyaWVyLCBob3VyLCBmbGlnaHQsIHRhaWxudW0sIGRlcF9kZWxheSwgYXZnRGVsYXksIGNvbXBhcmF0aXZlRGVsYXkpDQoNCmBgYA0KDQoxMy4gTm93IGdyb3VwIHRoZSBgY29tcGFyYXRpdmVEZWxheXNgIHRpYmJsZSBieSBjYXJyaWVycyB0byBwcmludCB0aGUgdG9wIDEwIGFpcmxpbmVzIHdpdGggdGhlIGdyZWF0ZXN0IGF2ZXJhZ2UgY29tcGFyYXRpdmUgZGVsYXlzLg0KYGBge3J9DQpmbGlnaHRzICU+JSANCiAgZ3JvdXBfYnkob3JpZ2luLCBob3VyKSAlPiUgDQogIG11dGF0ZShhdmdEZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFQpLCANCiAgICAgICAgIGNvbXBhcmF0aXZlRGVsYXkgPSBkZXBfZGVsYXkgLSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUKSkgJT4lIA0KICBzZWxlY3QoMTozLCBjYXJyaWVyLCBob3VyLCBmbGlnaHQsIHRhaWxudW0sIGRlcF9kZWxheSwgYXZnRGVsYXksIGNvbXBhcmF0aXZlRGVsYXkpICU+JSANCiAgZ3JvdXBfYnkoY2FycmllcikgJT4lIA0KICBzdW1tYXJpc2UoYXZnQ29tcGFyYXRpdmVEZWxheSA9IG1lYW4oY29tcGFyYXRpdmVEZWxheSwgbmEucm0gPSBUKSkgJT4lIA0KICB0b3BfbigxMCwgYXZnQ29tcGFyYXRpdmVEZWxheSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoYXZnQ29tcGFyYXRpdmVEZWxheSkpDQpgYGANCg0KMTQuIFVzZSBgZ3JvdXBfYnkoKWAgd2l0aCBmaWx0ZXIgdG8gcHJpbnQgdGhlIDUgbW9zdCBkZWxheWVkIGZsaWdodHMgZnJvbSBlYWNoIG9yaWdpbi4gWW91ciBwcmludGVkIHRpYmJsZSBzaG91bGQgaGF2ZSAxNSByb3dzLg0KYGBge3J9DQpmbGlnaHRzICU+JQ0KICBncm91cF9ieShvcmlnaW4pICU+JSANCiAgZmlsdGVyKGJldHdlZW4oZGVuc2VfcmFuayhkZXNjKGRlcF9kZWxheSkpLDEsIDUpKSAlPiUgDQogIGFycmFuZ2Uob3JpZ2luLCBkZXNjKGRlcF9kZWxheSkpDQoNCmBgYA0KDQoxNS4gVGhlIGFpciBhdXRob3JpdHkgaW4gTlkgd2FudHMgdG8gcGVuYWxpemUgY2FycmllcnMgZm9yIGRlcGFydHVyZSBkZWxheXMuIFdoaWNoIG9mIHRoZSB0aHJlZSBtZXRyaWNzICh0YXNrIDEsIDMgb3IgNCkgd291bGQgeW91IHJlY29tbWVuZCB0aGV5IHVzZSB0byBpZGVudGlmeSB0aGUgYWlybGluZXMgdG8gcGVuYWxpemUuIFdoeT8NCg0KICAgICsgQW5zd2VyOiBBdmVyYWdlIENvbXBhcmF0aXZlIERlbGF5IHNlZW1zIHRvIGJlIHRoZSBiZXN0LCBhcyBpdCBzdW1tYXJpc2VzIGJ5IG9yaWdpbiBhbmQgaG91ciANCiAgICANCiMjVGFzayBzZXQgMzogUiBtYXJrZG93bg0KDQoxLiBNb2RpZnkgdGhlIHRleHQgYmVsb3cgYXMgcGVyIHRoZSBwcm9tcHQNCiAgICArIFVuZGVybGluZSBtZQ0KICAgICsgKipNYWtlIG1lIGJvbGQqKg0KICAgICsgPk1ha2UgbWUgYSBibG9jayBxdW90ZQ0KICAgICsgKk1ha2UgbWUgaXRhbGljKg0KICAgICsgfn5TdHJpa2UgdGhyb3VnaCBtZX5+DQoNCjIuIENyZWF0ZSBhIGxldmVsIHRocmVlIGhlYWRlciBjYWxsZWQgIk15IGxldmVsIDMgaGVhZGVyIiB1bmRlciB0aGlzIGxpbmUgDQojIyNNeSBsZXZlbCAzIGhlYWRlcg0KDQozLiBNb2RpZnkgdGhlIGNvbnRlbnQgYmVsb3cgc28gdGhhdCB0aGUgYnVsbGV0IHBvaW50cyAodW5vcmRlcmVkIGxpc3QpIHJlbmRlciBjb3JyZWN0bHkNCg0KKipNZXNzeSBidWxsZXQgcG9pbnRzKioNCg0KLSBvbmUNCi0gdHdvDQotIHRocmVlDQoNCjQuIFVzZSBjaHVuayBvcHRpb25zIHRvIGhpZGUgdGhlIG91dHB1dCBhbmQgdGhlIGNvZGUgZnJvbSB0aGUgY2h1bmsgYmVsb3cgaW4gdGhlIHByZXZpZXdlZCBub3RlYm9vay4NCg0KYGBge3IsIHJlc3VsdHM9J2hpZGUnLCBlY2hvPUZBTFNFfQ0KcHJpbnQoIkhpZGUgbWUgYW5kIHRoZSBjb2RlIHRoYXQgY3JlYXRlZCBtZSIpDQpgYGA=