suppressPackageStartupMessages(library(nycflights13))
package 㤼㸱nycflights13㤼㸲 was built under R version 3.6.3
suppressPackageStartupMessages(library(tidyverse))
package 㤼㸱tidyverse㤼㸲 was built under R version 3.6.3

1. Find all flights that

(a) Had an arrival delay of two or more hours

Since the arr_delay variable is measured in minutes, find flights with an arrival delay of 120 or more minutes.

filter(flights, arr_delay >= 120)

(b) Flew to Houston (IAH or HOU)

The flights that flew to Houston are those flights where the destination (dest) is either “IAH” or “HOU”.

filter(flights, dest == "IAH" | dest == "HOU")

However, using %in% is more compact and would scale to cases where there were more than two airports we were interested in.

filter(flights, dest %in% c("IAH", "HOU"))

(c) Were operated by United, American, or Delta

In the flights dataset, the column carrier indicates the airline, but it uses two-character carrier codes. We can find the carrier codes for the airlines in the airlines dataset. Since the carrier code dataset only has 16 rows, and the names of the airlines in that dataset are not exactly “United”, “American”, or “Delta”, it is easiest to manually look up their carrier codes in that data.

airlines

The carrier code for Delta is "DL", for American is "AA", and for United is "UA". Using these carriers codes, we check whether carrier is one of those.

filter(flights, carrier %in% c("AA", "DL", "UA"))

(d) Departed in summer (July, August, and September)

The variable month has the month, and it is numeric. So, the summer flights are those that departed in months 7 (July), 8 (August), and 9 (September).

filter(flights, month >= 7, month <= 9)

The %in% operator is an alternative. If the : operator is used to specify the integer range, the expression is readable and compact.

filter(flights, month %in% 7:9)

We could also use the | operator. However, the | does not scale to many choices. Even with only three choices, it is quite verbose.

filter(flights, month == 7 | month == 8 | month == 9)

(e) Arrived more than two hours late, but didn’t leave late

Flights that arrived more than two hours late, but didn’t leave late will have an arrival delay of more than 120 minutes (arr_delay > 120) and a non-positive departure delay (dep_delay <= 0).

filter(flights, arr_delay > 120, dep_delay <= 0)

(f) Were delayed by at least an hour, but made up over 30 minutes in flight

Were delayed by at least an hour, but made up over 30 minutes in flight. If a flight was delayed by at least an hour, then dep_delay >= 60. If the flight didn’t make up any time in the air, then its arrival would be delayed by the same amount as its departure, meaning dep_delay == arr_delay, or alternatively, dep_delay - arr_delay == 0. If it makes up over 30 minutes in the air, then the arrival delay must be at least 30 minutes less than the departure delay, which is stated as dep_delay - arr_delay > 30.

filter(flights, dep_delay >= 60, dep_delay - arr_delay > 30)

(g) Departed between midnight and 6 am (inclusive)

Finding flights that departed between midnight and 6 a.m. is complicated by the way in which times are represented in the data. In dep_time, midnight is represented by 2400, not 0. You can verify this by checking the minimum and maximum of dep_time.

summary(flights$dep_time)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
      1     907    1401    1349    1744    2400    8255 

This is an example of why it is always good to check the summary statistics of your data. Unfortunately, this means we cannot simply check that dep_time < 600, because we also have to consider the special case of midnight.

filter(flights, dep_time <= 600 | dep_time == 2400)

Alternatively, we could use the modulo operator, %%. The modulo operator returns the remainder of division. Let’s see how how this affects our times.

c(600, 1200, 2400) %% 2400
[1]  600 1200    0

Since 2400 %% 2400 == 0 and all other times are left unchanged, we can compare the result of the modulo operation to 600,

filter(flights, dep_time %% 2400 <= 600)

This filter expression is more compact, but its readability will depends on the familiarity of the reader with modular arithmetic.

2. Another useful dplyr filtering helper is between(). What does it do? Can you use it to simplify the code needed to answer the previous challenges?

The expression between(x, left, right) is equivalent to x >= left & x <= right.

Of the answers in the previous question, we could simplify the statement of departed in summer (month >= 7 & month <= 9) using the between() function.

filter(flights, between(month, 7, 9))

3. How many flights have a missing dep_time? What other variables are missing? What might these rows represent?

Find the rows of flights with a missing departure time (dep_time) using the is.na() function.

filter(flights, is.na(dep_time))

Notably, the arrival time (arr_time) is also missing for these rows. These seem to be cancelled flights.

4. Why is NA ^ 0 not missing? Why is NA | TRUE not missing? Why is FALSE & NA not missing? Can you figure out the general rule? (NA * 0 is a tricky counterexample!)

NA ^ 0 == 1 since for all numeric values \(x^0=1\).

NA^0
[1] 1

NA | TRUE is TRUE because the value of the missing TRUE or FALSE,
\(x\) or TRUE is TRUE for all values of \(x\).

NA | TRUE
[1] TRUE

Likewise, anything and FALSE is always FALSE.

NA & FALSE
[1] FALSE

Because the value of the missing element matters in NA | FALSE and NA & TRUE, these are missing:

NA | FALSE
[1] NA
NA & TRUE
[1] NA

Since \(x \times0=0\) for all finite, numeric \(x\), we might expect NA * 0 == 0, but that’s not the case.

NA * 0
[1] NA

The reason that NA * 0 is not equal to 0 is that \(x \times \infty\) and \(x \times -\infty\) is undefined. R represents undefined results as NaN, which is an abbreviation of not a number.

Inf * 0
[1] NaN
-Inf * 0
[1] NaN
LS0tDQp0aXRsZTogIkZpbHRlciByb3dzIHdpdGggZmlsdGVyKCkiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNA0KLS0tDQoNCg0KYGBge3IgbG9hZGxpYnJhcnl9DQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShueWNmbGlnaHRzMTMpKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkodGlkeXZlcnNlKSkNCmBgYA0KDQojIyMgMS4gRmluZCBhbGwgZmxpZ2h0cyB0aGF0DQoNCiMjIyMgKGEpIEhhZCBhbiBhcnJpdmFsIGRlbGF5IG9mIHR3byBvciBtb3JlIGhvdXJzDQoNClNpbmNlIHRoZSBgYXJyX2RlbGF5YCB2YXJpYWJsZSBpcyBtZWFzdXJlZCBpbiBtaW51dGVzLCBmaW5kIGZsaWdodHMgd2l0aCBhbiBhcnJpdmFsIGRlbGF5IG9mIDEyMCBvciBtb3JlIG1pbnV0ZXMuDQoNCmBgYHtyIGRlbGF5fQ0KZmlsdGVyKGZsaWdodHMsIGFycl9kZWxheSA+PSAxMjApDQpgYGANCg0KIyMjIyAoYikgRmxldyB0byBIb3VzdG9uIChJQUggb3IgSE9VKQ0KDQpUaGUgZmxpZ2h0cyB0aGF0IGZsZXcgdG8gSG91c3RvbiBhcmUgdGhvc2UgZmxpZ2h0cyB3aGVyZSB0aGUgZGVzdGluYXRpb24gKGBkZXN0YCkgaXMgZWl0aGVyIOKAnElBSOKAnSBvciDigJxIT1XigJ0uDQoNCmBgYHtyIGRlc3RIT1V9DQpmaWx0ZXIoZmxpZ2h0cywgZGVzdCA9PSAiSUFIIiB8IGRlc3QgPT0gIkhPVSIpDQpgYGANCg0KSG93ZXZlciwgdXNpbmcgYCVpbiVgIGlzIG1vcmUgY29tcGFjdCBhbmQgd291bGQgc2NhbGUgdG8gY2FzZXMgd2hlcmUgdGhlcmUgd2VyZSBtb3JlIHRoYW4gdHdvIGFpcnBvcnRzIHdlIHdlcmUgaW50ZXJlc3RlZCBpbi4NCg0KYGBge3IgaW59DQpmaWx0ZXIoZmxpZ2h0cywgZGVzdCAlaW4lIGMoIklBSCIsICJIT1UiKSkNCmBgYA0KDQojIyMjIChjKSBXZXJlIG9wZXJhdGVkIGJ5IFVuaXRlZCwgQW1lcmljYW4sIG9yIERlbHRhDQoNCkluIHRoZSBgZmxpZ2h0c2AgZGF0YXNldCwgdGhlIGNvbHVtbiBgY2FycmllcmAgaW5kaWNhdGVzIHRoZSBhaXJsaW5lLCBidXQgaXQgdXNlcyB0d28tY2hhcmFjdGVyIGNhcnJpZXIgY29kZXMuIFdlIGNhbiBmaW5kIHRoZSBjYXJyaWVyIGNvZGVzIGZvciB0aGUgYWlybGluZXMgaW4gdGhlIGFpcmxpbmVzIGRhdGFzZXQuIFNpbmNlIHRoZSBjYXJyaWVyIGNvZGUgZGF0YXNldCBvbmx5IGhhcyAxNiByb3dzLCBhbmQgdGhlIG5hbWVzIG9mIHRoZSBhaXJsaW5lcyBpbiB0aGF0IGRhdGFzZXQgYXJlIG5vdCBleGFjdGx5IOKAnFVuaXRlZOKAnSwg4oCcQW1lcmljYW7igJ0sIG9yIOKAnERlbHRh4oCdLCBpdCBpcyBlYXNpZXN0IHRvIG1hbnVhbGx5IGxvb2sgdXAgdGhlaXIgY2FycmllciBjb2RlcyBpbiB0aGF0IGRhdGEuDQoNCmBgYHtyIGFpcmxpbmVzfQ0KYWlybGluZXMNCmBgYA0KDQpUaGUgY2FycmllciBjb2RlIGZvciBEZWx0YSBpcyBgIkRMImAsIGZvciBBbWVyaWNhbiBpcyBgIkFBImAsIGFuZCBmb3IgVW5pdGVkIGlzIGAiVUEiYC4gVXNpbmcgdGhlc2UgY2FycmllcnMgY29kZXMsIHdlIGNoZWNrIHdoZXRoZXIgYGNhcnJpZXJgIGlzIG9uZSBvZiB0aG9zZS4NCg0KYGBge3J9DQpmaWx0ZXIoZmxpZ2h0cywgY2FycmllciAlaW4lIGMoIkFBIiwgIkRMIiwgIlVBIikpDQpgYGANCg0KIyMjIyAoZCkgRGVwYXJ0ZWQgaW4gc3VtbWVyIChKdWx5LCBBdWd1c3QsIGFuZCBTZXB0ZW1iZXIpDQoNClRoZSB2YXJpYWJsZSBgbW9udGhgIGhhcyB0aGUgbW9udGgsIGFuZCBpdCBpcyBudW1lcmljLiBTbywgdGhlIHN1bW1lciBmbGlnaHRzIGFyZSB0aG9zZSB0aGF0IGRlcGFydGVkIGluIG1vbnRocyA3IChKdWx5KSwgOCAoQXVndXN0KSwgYW5kIDkgKFNlcHRlbWJlcikuDQoNCmBgYHtyIG1vbnRofQ0KZmlsdGVyKGZsaWdodHMsIG1vbnRoID49IDcsIG1vbnRoIDw9IDkpDQpgYGANCg0KVGhlIGAlaW4lYCBvcGVyYXRvciBpcyBhbiBhbHRlcm5hdGl2ZS4gSWYgdGhlIGA6YCBvcGVyYXRvciBpcyB1c2VkIHRvIHNwZWNpZnkgdGhlIGludGVnZXIgcmFuZ2UsIHRoZSBleHByZXNzaW9uIGlzIHJlYWRhYmxlIGFuZCBjb21wYWN0Lg0KDQpgYGB7ciBpbmNvbG9ufQ0KZmlsdGVyKGZsaWdodHMsIG1vbnRoICVpbiUgNzo5KQ0KYGBgDQoNCldlIGNvdWxkIGFsc28gdXNlIHRoZSBgfGAgb3BlcmF0b3IuIEhvd2V2ZXIsIHRoZSBgfGAgZG9lcyBub3Qgc2NhbGUgdG8gbWFueSBjaG9pY2VzLiBFdmVuIHdpdGggb25seSB0aHJlZSBjaG9pY2VzLCBpdCBpcyBxdWl0ZSB2ZXJib3NlLg0KDQpgYGB7ciB2ZXJib3NlfQ0KZmlsdGVyKGZsaWdodHMsIG1vbnRoID09IDcgfCBtb250aCA9PSA4IHwgbW9udGggPT0gOSkNCmBgYA0KDQoNCiMjIyMgKGUpIEFycml2ZWQgbW9yZSB0aGFuIHR3byBob3VycyBsYXRlLCBidXQgZGlkbuKAmXQgbGVhdmUgbGF0ZQ0KDQpGbGlnaHRzIHRoYXQgYXJyaXZlZCBtb3JlIHRoYW4gdHdvIGhvdXJzIGxhdGUsIGJ1dCBkaWRu4oCZdCBsZWF2ZSBsYXRlIHdpbGwgaGF2ZSBhbiBhcnJpdmFsIGRlbGF5IG9mIG1vcmUgdGhhbiAxMjAgbWludXRlcyAoYGFycl9kZWxheSA+IDEyMGApIGFuZCBhIG5vbi1wb3NpdGl2ZSBkZXBhcnR1cmUgZGVsYXkgKGBkZXBfZGVsYXkgPD0gMGApLg0KDQpgYGB7ciBub2xlYXZlfQ0KZmlsdGVyKGZsaWdodHMsIGFycl9kZWxheSA+IDEyMCwgZGVwX2RlbGF5IDw9IDApDQpgYGANCg0KIyMjIyAoZikgV2VyZSBkZWxheWVkIGJ5IGF0IGxlYXN0IGFuIGhvdXIsIGJ1dCBtYWRlIHVwIG92ZXIgMzAgbWludXRlcyBpbiBmbGlnaHQNCg0KV2VyZSBkZWxheWVkIGJ5IGF0IGxlYXN0IGFuIGhvdXIsIGJ1dCBtYWRlIHVwIG92ZXIgMzAgbWludXRlcyBpbiBmbGlnaHQuIElmIGEgZmxpZ2h0IHdhcyBkZWxheWVkIGJ5IGF0IGxlYXN0IGFuIGhvdXIsIHRoZW4gYGRlcF9kZWxheSA+PSA2MGAuIElmIHRoZSBmbGlnaHQgZGlkbuKAmXQgbWFrZSB1cCBhbnkgdGltZSBpbiB0aGUgYWlyLCB0aGVuIGl0cyBhcnJpdmFsIHdvdWxkIGJlIGRlbGF5ZWQgYnkgdGhlIHNhbWUgYW1vdW50IGFzIGl0cyBkZXBhcnR1cmUsIG1lYW5pbmcgYGRlcF9kZWxheSA9PSBhcnJfZGVsYXlgLCBvciBhbHRlcm5hdGl2ZWx5LCBgZGVwX2RlbGF5IC0gYXJyX2RlbGF5ID09IDBgLiBJZiBpdCBtYWtlcyB1cCBvdmVyIDMwIG1pbnV0ZXMgaW4gdGhlIGFpciwgdGhlbiB0aGUgYXJyaXZhbCBkZWxheSBtdXN0IGJlIGF0IGxlYXN0IDMwIG1pbnV0ZXMgbGVzcyB0aGFuIHRoZSBkZXBhcnR1cmUgZGVsYXksIHdoaWNoIGlzIHN0YXRlZCBhcyBgZGVwX2RlbGF5IC0gYXJyX2RlbGF5ID4gMzBgLg0KDQpgYGB7ciBtYWtldXAzMH0NCmZpbHRlcihmbGlnaHRzLCBkZXBfZGVsYXkgPj0gNjAsIGRlcF9kZWxheSAtIGFycl9kZWxheSA+IDMwKQ0KYGBgDQoNCiMjIyMgKGcpIERlcGFydGVkIGJldHdlZW4gbWlkbmlnaHQgYW5kIDYgYW0gKGluY2x1c2l2ZSkNCg0KRmluZGluZyBmbGlnaHRzIHRoYXQgZGVwYXJ0ZWQgYmV0d2VlbiBtaWRuaWdodCBhbmQgNiBhLm0uIGlzIGNvbXBsaWNhdGVkIGJ5IHRoZSB3YXkgaW4gd2hpY2ggdGltZXMgYXJlIHJlcHJlc2VudGVkIGluIHRoZSBkYXRhLg0KSW4gYGRlcF90aW1lYCwgbWlkbmlnaHQgaXMgcmVwcmVzZW50ZWQgYnkgYDI0MDBgLCBub3QgYDBgLiBZb3UgY2FuIHZlcmlmeSB0aGlzIGJ5IGNoZWNraW5nIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIG9mIGRlcF90aW1lLg0KDQpgYGB7ciBjaGVja21pZG5pZ2h0fQ0Kc3VtbWFyeShmbGlnaHRzJGRlcF90aW1lKQ0KYGBgDQoNClRoaXMgaXMgYW4gZXhhbXBsZSBvZiB3aHkgaXQgaXMgYWx3YXlzIGdvb2QgdG8gY2hlY2sgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyBvZiB5b3VyIGRhdGEuIFVuZm9ydHVuYXRlbHksIHRoaXMgbWVhbnMgd2UgY2Fubm90IHNpbXBseSBjaGVjayB0aGF0IGBkZXBfdGltZSA8IDYwMGAsIGJlY2F1c2Ugd2UgYWxzbyBoYXZlIHRvIGNvbnNpZGVyIHRoZSBzcGVjaWFsIGNhc2Ugb2YgbWlkbmlnaHQuDQoNCmBgYHtyIGdldG1pZG5pZ2h0fQ0KZmlsdGVyKGZsaWdodHMsIGRlcF90aW1lIDw9IDYwMCB8IGRlcF90aW1lID09IDI0MDApDQpgYGANCg0KDQpBbHRlcm5hdGl2ZWx5LCB3ZSBjb3VsZCB1c2UgdGhlIFttb2R1bG8gb3BlcmF0b3JdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01vZHVsb19vcGVyYXRpb24pLCBgJSVgLiBUaGUgbW9kdWxvIG9wZXJhdG9yIHJldHVybnMgdGhlIHJlbWFpbmRlciBvZiBkaXZpc2lvbi4gTGV04oCZcyBzZWUgaG93IGhvdyB0aGlzIGFmZmVjdHMgb3VyIHRpbWVzLg0KDQpgYGB7ciBtb2R1bG99DQpjKDYwMCwgMTIwMCwgMjQwMCkgJSUgMjQwMA0KYGBgDQoNClNpbmNlIGAyNDAwICUlIDI0MDAgPT0gMGAgYW5kIGFsbCBvdGhlciB0aW1lcyBhcmUgbGVmdCB1bmNoYW5nZWQsIHdlIGNhbiBjb21wYXJlIHRoZSByZXN1bHQgb2YgdGhlIG1vZHVsbyBvcGVyYXRpb24gdG8gYDYwMGAsDQoNCmBgYHtyIG1vZDI0MDB9DQpmaWx0ZXIoZmxpZ2h0cywgZGVwX3RpbWUgJSUgMjQwMCA8PSA2MDApDQpgYGANCg0KVGhpcyBmaWx0ZXIgZXhwcmVzc2lvbiBpcyBtb3JlIGNvbXBhY3QsIGJ1dCBpdHMgcmVhZGFiaWxpdHkgd2lsbCBkZXBlbmRzIG9uIHRoZSBmYW1pbGlhcml0eSBvZiB0aGUgcmVhZGVyIHdpdGggbW9kdWxhciBhcml0aG1ldGljLg0KDQojIyMgMi4gQW5vdGhlciB1c2VmdWwgZHBseXIgZmlsdGVyaW5nIGhlbHBlciBpcyBgYmV0d2VlbigpYC4gV2hhdCBkb2VzIGl0IGRvPyBDYW4geW91IHVzZSBpdCB0byBzaW1wbGlmeSB0aGUgY29kZSBuZWVkZWQgdG8gYW5zd2VyIHRoZSBwcmV2aW91cyBjaGFsbGVuZ2VzPw0KDQpUaGUgZXhwcmVzc2lvbiBgYmV0d2Vlbih4LCBsZWZ0LCByaWdodClgIGlzIGVxdWl2YWxlbnQgdG8gYHggPj0gbGVmdCAmIHggPD0gcmlnaHRgLg0KDQpPZiB0aGUgYW5zd2VycyBpbiB0aGUgcHJldmlvdXMgcXVlc3Rpb24sIHdlIGNvdWxkIHNpbXBsaWZ5IHRoZSBzdGF0ZW1lbnQgb2YgKmRlcGFydGVkIGluIHN1bW1lciogKGBtb250aCA+PSA3ICYgbW9udGggPD0gOWApIHVzaW5nIHRoZSBgYmV0d2VlbigpYCBmdW5jdGlvbi4NCg0KYGBge3Igc3VtbWVyfQ0KZmlsdGVyKGZsaWdodHMsIGJldHdlZW4obW9udGgsIDcsIDkpKQ0KYGBgDQoNCiMjIyAzLiBIb3cgbWFueSBmbGlnaHRzIGhhdmUgYSBtaXNzaW5nIGBkZXBfdGltZWA/IFdoYXQgb3RoZXIgdmFyaWFibGVzIGFyZSBtaXNzaW5nPyBXaGF0IG1pZ2h0IHRoZXNlIHJvd3MgcmVwcmVzZW50Pw0KDQpGaW5kIHRoZSByb3dzIG9mIGZsaWdodHMgd2l0aCBhIG1pc3NpbmcgZGVwYXJ0dXJlIHRpbWUgKGBkZXBfdGltZWApIHVzaW5nIHRoZSBgaXMubmEoKWAgZnVuY3Rpb24uDQoNCmBgYHtyIG1pc3NpbmdfZGVwdGltZX0NCmZpbHRlcihmbGlnaHRzLCBpcy5uYShkZXBfdGltZSkpDQpgYGANCg0KTm90YWJseSwgdGhlIGFycml2YWwgdGltZSAoYGFycl90aW1lYCkgaXMgYWxzbyBtaXNzaW5nIGZvciB0aGVzZSByb3dzLiBUaGVzZSBzZWVtIHRvIGJlIGNhbmNlbGxlZCBmbGlnaHRzLg0KDQojIyMgNC4gV2h5IGlzIGBOQSBeIDBgIG5vdCBtaXNzaW5nPyBXaHkgaXMgYE5BIHwgVFJVRWAgbm90IG1pc3Npbmc/IFdoeSBpcyBgRkFMU0UgJiBOQWAgbm90IG1pc3Npbmc/IENhbiB5b3UgZmlndXJlIG91dCB0aGUgZ2VuZXJhbCBydWxlPyAoYE5BICogMGAgaXMgYSB0cmlja3kgY291bnRlcmV4YW1wbGUhKQ0KDQpgTkEgXiAwID09IDFgIHNpbmNlIGZvciBhbGwgbnVtZXJpYyB2YWx1ZXMgJHheMD0xJC4NCg0KYGBge3IgbmEwfQ0KTkFeMA0KYGBgDQoNCmBOQSB8IFRSVUVgIGlzIGBUUlVFYCBiZWNhdXNlIHRoZSB2YWx1ZSBvZiB0aGUgbWlzc2luZyBgVFJVRWAgb3IgYEZBTFNFYCwgIA0KJHgkIG9yIGBUUlVFYCBpcyBgVFJVRWAgZm9yIGFsbCB2YWx1ZXMgb2YgJHgkLg0KDQpgYGB7ciBuYXRydWV9DQpOQSB8IFRSVUUNCmBgYA0KDQoNCkxpa2V3aXNlLCBhbnl0aGluZyBhbmQgYEZBTFNFYCBpcyBhbHdheXMgYEZBTFNFYC4NCg0KYGBge3IgbmFmYWxzZX0NCk5BICYgRkFMU0UNCmBgYA0KDQpCZWNhdXNlIHRoZSB2YWx1ZSBvZiB0aGUgbWlzc2luZyBlbGVtZW50IG1hdHRlcnMgaW4gYE5BIHwgRkFMU0VgIGFuZCBgTkEgJiBUUlVFYCwgdGhlc2UgYXJlIG1pc3Npbmc6DQoNCmBgYHtyIG5hb3J9DQpOQSB8IEZBTFNFDQpOQSAmIFRSVUUNCmBgYA0KDQpTaW5jZSAkeCBcdGltZXMwPTAkIGZvciBhbGwgZmluaXRlLCBudW1lcmljICR4JCwgd2UgbWlnaHQgZXhwZWN0IGBOQSAqIDAgPT0gMGAsIGJ1dCB0aGF04oCZcyBub3QgdGhlIGNhc2UuDQoNCmBgYHtyIG5hdGltZXMwfQ0KTkEgKiAwDQpgYGANCg0KVGhlIHJlYXNvbiB0aGF0IGBOQSAqIDBgIGlzIG5vdCBlcXVhbCB0byBgMGAgaXMgdGhhdCAkeCBcdGltZXMgXGluZnR5JCBhbmQgJHggXHRpbWVzIC1caW5mdHkkIGlzIHVuZGVmaW5lZC4gUiByZXByZXNlbnRzIHVuZGVmaW5lZCByZXN1bHRzIGFzIGBOYU5gLCB3aGljaCBpcyBhbiBhYmJyZXZpYXRpb24gb2YgW25vdCBhIG51bWJlcl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTmFOKS4NCg0KYGBge3IgaW5mMH0NCkluZiAqIDANCi1JbmYgKiAwDQpgYGANCg0K