Let’s first delete all variables and load our tidyverse library.
Exercise 1
Using the 173 majors listed in fivethirtyeight.com’s College Majors dataset [https://fivethirtyeight.com/features/the-economic-guide-to-picking-a-college-major/], provide code that identifies the majors that contain either “DATA” or “STATISTICS”
ANSWER We will load directly from github using the alternatve site which works for read_csv. I will use regex and the str_detect function in Stringr to match any major whose description either has the word “DATA” or the word “STATISTICS.
Since all descriptions were already CAPITALIZED, I didn’t have to transform any of the columns or adapt the regex to account for it.
# Insert code for Exercise 1 here
college_majors <- read_csv("https://raw.githubusercontent.com/fivethirtyeight/data/master/college-majors/majors-list.csv")
## Rows: 174 Columns: 3
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (3): FOD1P, Major, Major_Category
##
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# I applied a simple FILTER to get requested output
data_majors <- college_majors %>%
filter(str_detect(Major, "DATA|STATISTICS"))
data_majors
## # A tibble: 3 x 3
## FOD1P Major Major_Category
## <chr> <chr> <chr>
## 1 6212 MANAGEMENT INFORMATION SYSTEMS AND STATISTICS Business
## 2 2101 COMPUTER PROGRAMMING AND DATA PROCESSING Computers & Mathematics
## 3 3702 STATISTICS AND DECISION SCIENCE Computers & Mathematics
Exercise 2
Write code that transforms the data below:
[1] “bell pepper” “bilberry” “blackberry” “blood orange” [5] “blueberry” “cantaloupe” “chili pepper” “cloudberry”
[9] “elderberry” “lime” “lychee” “mulberry”
[13] “olive” “salal berry”
Into a format like this:
c(“bell pepper”, “bilberry”, “blackberry”, “blood orange”, “blueberry”, “cantaloupe”, “chili pepper”, “cloudberry”, “elderberry”, “lime”, “lychee”, “mulberry”, “olive”, “salal berry”)
ANSWER This one was more complicated than I thought. The complication is that I was not exactly certain on the format of the output.
The complication was how to threat the quotation chartacters ” since the output has in itself quotations.
So my interpretation was to provide back a string that has quote characters within the string itself, or something like Answer_String <- “c(”word1”,“word2”, “etc”)“.
But this means that the answer string must include escapes and should be something like Answer_String <- “c("word1","word2","etc")”.
This way if I write this code below the output will look like what I think the output should look like:
Answer_String <- "c(\"word1\",\"word2\",\"etc\")"
writeLines(Answer_String)
## c("word1","word2","etc")
So I tried this several ways using variations of REGEX. Let’s first load the text from a file I created. The approach I took in this problems is to read the whole text in a single variable.
my_file <- read_file("words.txt")
my_file
## [1] "[1] \"bell pepper\" \"bilberry\" \"blackberry\" \"blood orange\"\r\n[5] \"blueberry\" \"cantaloupe\" \"chili pepper\" \"cloudberry\" \r\n[9] \"elderberry\" \"lime\" \"lychee\" \"mulberry\" \r\n[13] \"olive\" \"salal berry\""
Then for approach #1 I decided to use REGEX to match the whole word INCLUDING THE QUOTATION characters
# Insert code for Exercise 1 here
pattern <- '["“][A-Za-z ]{2,}["”]'
str_view_all(my_file,pattern)
data1 <- str_match_all(my_file,pattern)
The match was as designed, and the result stored in a LIST.
Next step was to merge the words in quotes.
data1 <- paste(data1,collapse=",")
writeLines((data1))
## c("\"bell pepper\"", "\"bilberry\"", "\"blackberry\"", "\"blood orange\"", "\"blueberry\"", "\"cantaloupe\"", "\"chili pepper\"", "\"cloudberry\"", "\"elderberry\"", "\"lime\"", "\"lychee\"", "\"mulberry\"", "\"olive\"", "\"salal berry\"")
The result looks VERY CLOSE to desired answer, but not exactly as I desired since it added quotation characters around each word. So instead of ending with “word1”, I ended with ““word1”“. Not what I wanted.
So I went the route to match the words inside quotation marks, but without the quotation characters themselves, just the words inside. I used again REGEX to isolate words.
pattern <- '(?<=\")[A-Za-z ]{3,}(?=\")'
str_view_all(my_file,pattern)
data2 <- str_match_all(my_file,pattern)
I almost got what I wanted. Unfortunately it also added some blank spaces between words in quotes. After some experimenting coudlnt’ find a REGEX that would I isolate just rhe words within qoutes.
I decided just to go ahead remove all empty strings added to the list. Not pretty but would get me there
data3 <- data2[[1]][str_count(data2[[1]],pattern=" ") < 2]
data3
## [1] "bell pepper" "bilberry" "blackberry" "blood orange" "blueberry"
## [6] "cantaloupe" "chili pepper" "cloudberry" "elderberry" "lime"
## [11] "lychee" "mulberry" "olive" "salal berry"
So that gives me what I want, a list of the just words in the file, without quotes around them.
My next step was to merge the words in the list with “,” as separator.
data4<- paste(data3,collapse = '\",\"')
writeLines(data4)
## bell pepper","bilberry","blackberry","blood orange","blueberry","cantaloupe","chili pepper","cloudberry","elderberry","lime","lychee","mulberry","olive","salal berry
So this ALMOST completely did the trick. I just need to add “c(” at the beginning and “) at the end and PRESTO.
final_string <- paste0('c(\"',data4,'\")')
writeLines(final_string)
## c("bell pepper","bilberry","blackberry","blood orange","blueberry","cantaloupe","chili pepper","cloudberry","elderberry","lime","lychee","mulberry","olive","salal berry")
Exacty the output requested in the exercise DONE!
Exercise 3
Describe, in words, what these expressions will match:
(.)\1\1
“(.)(.)\2\1”
(..)\1
“(.).\1.\1”
“(.)(.)(.).*\3\2\1”
ANSWER
Let’s start by defining a test vector we can use to test our REGEX.
test <- c("bell pepper", "aaairlines", "bilberry", "blackberry", "blood orange",
"blueberry", "cantaloupe", "chili pepper", "church","cloudberry",
"elderberry", "lime", "rhbbbf", "lychee", "mulberry", "olive",
"salal berry", "1234ab345 ba343", "1234ab345ba343","alibaba", "bereb",
"bbgun", "asdbbb", "balacab", "balacaba", "1234568965443", "erberberbee")
Now lets look and test what each REGEX do
#Searches the whole string and would match 3 continuous of same character
str_view_all(test,"(.)\\1\\1")
#Searches the whole string and looks for 4 characters, where
#the last pair of two is in reverse order than the first pair of two
str_view_all(test,"(.)(.)\\2\\1")
#Searches and look for 4 consecutive characters where the first
#pair of characters is repeated once
str_view_all(test,"(..)\\1")
#Looks for a pattern of same character repeated 3 times with a character
#in between
str_view_all(test,"(.).\\1.\\1")
LS0tDQp0aXRsZTogIkRhdGE2MDcgLSBBc3NpZ25tZW50IFdlZWsgMyINCmF1dGhvcjogIkp1YW4gRmFsY2siDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KLS0tDQoNCkxldCdzIGZpcnN0IGRlbGV0ZSBhbGwgdmFyaWFibGVzIGFuZCBsb2FkIG91ciB0aWR5dmVyc2UgbGlicmFyeS4NCg0KYGBge3IgbG9hZC1wYWNrYWdlcywgbWVzc2FnZT1GQUxTRX0NCnJtKGxpc3Q9bHMoKSkgDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0KDQojIyBFeGVyY2lzZSAxDQoNClVzaW5nIHRoZSAxNzMgbWFqb3JzIGxpc3RlZCBpbiBmaXZldGhpcnR5ZWlnaHQuY29t4oCZcyBDb2xsZWdlIE1ham9ycyBkYXRhc2V0IFtodHRwczovL2ZpdmV0aGlydHllaWdodC5jb20vZmVhdHVyZXMvdGhlLWVjb25vbWljLWd1aWRlLXRvLXBpY2tpbmctYS1jb2xsZWdlLW1ham9yL10sIHByb3ZpZGUgY29kZSB0aGF0IGlkZW50aWZpZXMgdGhlIG1ham9ycyB0aGF0IGNvbnRhaW4gZWl0aGVyICJEQVRBIiBvciAiU1RBVElTVElDUyINCg0KKipBTlNXRVIqKiANCldlIHdpbGwgbG9hZCBkaXJlY3RseSBmcm9tIGdpdGh1YiB1c2luZyB0aGUgYWx0ZXJuYXR2ZSBzaXRlIHdoaWNoIHdvcmtzIGZvciByZWFkX2Nzdi4gSSB3aWxsIHVzZSByZWdleCBhbmQgdGhlIHN0cl9kZXRlY3QgZnVuY3Rpb24gaW4gU3RyaW5nciB0byBtYXRjaCBhbnkgbWFqb3Igd2hvc2UgZGVzY3JpcHRpb24gZWl0aGVyIGhhcyB0aGUgd29yZCAiREFUQSIgb3IgdGhlIHdvcmQgIlNUQVRJU1RJQ1MuDQoNClNpbmNlIGFsbCBkZXNjcmlwdGlvbnMgd2VyZSBhbHJlYWR5IENBUElUQUxJWkVELCBJIGRpZG4ndCBoYXZlIHRvIHRyYW5zZm9ybSBhbnkgb2YgdGhlIGNvbHVtbnMgb3IgYWRhcHQgdGhlIHJlZ2V4IHRvIGFjY291bnQgZm9yIGl0Lg0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsMX0NCiMgSW5zZXJ0IGNvZGUgZm9yIEV4ZXJjaXNlIDEgaGVyZQ0KY29sbGVnZV9tYWpvcnMgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9maXZldGhpcnR5ZWlnaHQvZGF0YS9tYXN0ZXIvY29sbGVnZS1tYWpvcnMvbWFqb3JzLWxpc3QuY3N2IikNCg0KIyBJIGFwcGxpZWQgYSBzaW1wbGUgRklMVEVSIHRvIGdldCByZXF1ZXN0ZWQgb3V0cHV0DQpkYXRhX21ham9ycyA8LSBjb2xsZWdlX21ham9ycyAlPiUNCiAgZmlsdGVyKHN0cl9kZXRlY3QoTWFqb3IsICJEQVRBfFNUQVRJU1RJQ1MiKSkNCg0KZGF0YV9tYWpvcnMNCmBgYA0KDQojIyBFeGVyY2lzZSAyDQoNCldyaXRlIGNvZGUgdGhhdCB0cmFuc2Zvcm1zIHRoZSBkYXRhIGJlbG93Og0KDQpbMV0gImJlbGwgcGVwcGVyIiAgImJpbGJlcnJ5IiAgICAgImJsYWNrYmVycnkiICAgImJsb29kIG9yYW5nZSINCls1XSAiYmx1ZWJlcnJ5IiAgICAiY2FudGFsb3VwZSIgICAiY2hpbGkgcGVwcGVyIiAiY2xvdWRiZXJyeSIgIA0KWzldICJlbGRlcmJlcnJ5IiAgICJsaW1lIiAgICAgICAgICJseWNoZWUiICAgICAgICJtdWxiZXJyeSIgICAgDQpbMTNdICJvbGl2ZSIgICAgICAgICJzYWxhbCBiZXJyeSINCg0KSW50byBhIGZvcm1hdCBsaWtlIHRoaXM6DQoNCmMoImJlbGwgcGVwcGVyIiwgImJpbGJlcnJ5IiwgImJsYWNrYmVycnkiLCAiYmxvb2Qgb3JhbmdlIiwgImJsdWViZXJyeSIsICJjYW50YWxvdXBlIiwgImNoaWxpIHBlcHBlciIsICJjbG91ZGJlcnJ5IiwgImVsZGVyYmVycnkiLCAibGltZSIsICJseWNoZWUiLCAibXVsYmVycnkiLCAib2xpdmUiLCAic2FsYWwgYmVycnkiKQ0KDQoNCioqQU5TV0VSKioNClRoaXMgb25lIHdhcyBtb3JlIGNvbXBsaWNhdGVkIHRoYW4gSSB0aG91Z2h0LiAgVGhlIGNvbXBsaWNhdGlvbiBpcyB0aGF0IEkgd2FzIG5vdCBleGFjdGx5IGNlcnRhaW4gb24gdGhlIGZvcm1hdCBvZiB0aGUgb3V0cHV0Lg0KDQpUaGUgY29tcGxpY2F0aW9uIHdhcyBob3cgdG8gdGhyZWF0IHRoZSBxdW90YXRpb24gY2hhcnRhY3RlcnMgIiBzaW5jZSB0aGUgb3V0cHV0IGhhcyBpbiBpdHNlbGYgcXVvdGF0aW9ucy4gIA0KDQpTbyBteSBpbnRlcnByZXRhdGlvbiB3YXMgdG8gcHJvdmlkZSBiYWNrIGEgc3RyaW5nIHRoYXQgaGFzIHF1b3RlIGNoYXJhY3RlcnMgd2l0aGluIHRoZSBzdHJpbmcgaXRzZWxmLCBvciBzb21ldGhpbmcgbGlrZSANCioqQW5zd2VyX1N0cmluZyA8LSAiYygid29yZDEiLCJ3b3JkMiIsICJldGMiKSIqKi4gIA0KDQpCdXQgdGhpcyBtZWFucyB0aGF0IHRoZSBhbnN3ZXIgc3RyaW5nIG11c3QgaW5jbHVkZSBlc2NhcGVzIGFuZCBzaG91bGQgYmUgc29tZXRoaW5nIGxpa2UgKipBbnN3ZXJfU3RyaW5nIDwtICJjKFwid29yZDFcIixcIndvcmQyXCIsXCJldGNcIikiKiouIA0KDQpUaGlzIHdheSBpZiBJIHdyaXRlIHRoaXMgY29kZSBiZWxvdyB0aGUgb3V0cHV0IHdpbGwgbG9vayBsaWtlIHdoYXQgSSB0aGluayB0aGUgb3V0cHV0IHNob3VsZCBsb29rIGxpa2U6DQoNCmBgYHtyIGNvZGUtY2h1bmstbGFiZWwxMn0NCkFuc3dlcl9TdHJpbmcgPC0gImMoXCJ3b3JkMVwiLFwid29yZDJcIixcImV0Y1wiKSINCiB3cml0ZUxpbmVzKEFuc3dlcl9TdHJpbmcpDQpgYGANCg0KU28gSSB0cmllZCB0aGlzIHNldmVyYWwgd2F5cyB1c2luZyB2YXJpYXRpb25zIG9mIFJFR0VYLiBMZXQncyBmaXJzdCBsb2FkIHRoZSB0ZXh0IGZyb20gYSBmaWxlIEkgY3JlYXRlZC4gVGhlIGFwcHJvYWNoIEkgdG9vayBpbiB0aGlzIHByb2JsZW1zIGlzIHRvIHJlYWQgdGhlICoqd2hvbGUgdGV4dCBpbiBhIHNpbmdsZSB2YXJpYWJsZSoqLg0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsMn0NCm15X2ZpbGUgPC0gcmVhZF9maWxlKCJ3b3Jkcy50eHQiKQ0KbXlfZmlsZQ0KYGBgDQoNClRoZW4gZm9yIGFwcHJvYWNoICMxIEkgZGVjaWRlZCB0byB1c2UgUkVHRVggdG8gbWF0Y2ggdGhlIHdob2xlIHdvcmQgSU5DTFVESU5HIFRIRSBRVU9UQVRJT04gY2hhcmFjdGVycw0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsM30NCiMgSW5zZXJ0IGNvZGUgZm9yIEV4ZXJjaXNlIDEgaGVyZQ0KcGF0dGVybiA8LSAnWyLigJxdW0EtWmEteiBdezIsfVsi4oCdXScNCnN0cl92aWV3X2FsbChteV9maWxlLHBhdHRlcm4pDQpkYXRhMSA8LSBzdHJfbWF0Y2hfYWxsKG15X2ZpbGUscGF0dGVybikNCmBgYA0KDQpUaGUgbWF0Y2ggd2FzIGFzIGRlc2lnbmVkLCBhbmQgdGhlIHJlc3VsdCBzdG9yZWQgaW4gYSBMSVNULiAgDQoNCk5leHQgc3RlcCB3YXMgdG8gbWVyZ2UgdGhlIHdvcmRzIGluIHF1b3Rlcy4NCg0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsNH0NCmRhdGExIDwtIHBhc3RlKGRhdGExLGNvbGxhcHNlPSIsIikNCndyaXRlTGluZXMoKGRhdGExKSkNCmBgYA0KDQpUaGUgcmVzdWx0IGxvb2tzIFZFUlkgQ0xPU0UgdG8gZGVzaXJlZCBhbnN3ZXIsIGJ1dCBub3QgZXhhY3RseSBhcyBJIGRlc2lyZWQgc2luY2UgaXQgYWRkZWQgcXVvdGF0aW9uIGNoYXJhY3RlcnMgYXJvdW5kIGVhY2ggd29yZC4gU28gaW5zdGVhZCBvZiBlbmRpbmcgd2l0aCAid29yZDEiLCBJIGVuZGVkIHdpdGggIiJ3b3JkMSIiLiBOb3Qgd2hhdCBJIHdhbnRlZC4NCg0KU28gSSB3ZW50IHRoZSByb3V0ZSB0byBtYXRjaCB0aGUgd29yZHMgaW5zaWRlIHF1b3RhdGlvbiBtYXJrcywgYnV0IHdpdGhvdXQgdGhlIHF1b3RhdGlvbiBjaGFyYWN0ZXJzIHRoZW1zZWx2ZXMsIGp1c3QgdGhlIHdvcmRzIGluc2lkZS4gIEkgdXNlZCBhZ2FpbiBSRUdFWCB0byBpc29sYXRlIHdvcmRzLg0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsNX0NCnBhdHRlcm4gPC0gJyg/PD1cIilbQS1aYS16IF17Myx9KD89XCIpJw0Kc3RyX3ZpZXdfYWxsKG15X2ZpbGUscGF0dGVybikNCmRhdGEyIDwtIHN0cl9tYXRjaF9hbGwobXlfZmlsZSxwYXR0ZXJuKQ0KYGBgDQogDQpJIGFsbW9zdCBnb3Qgd2hhdCBJIHdhbnRlZC4gVW5mb3J0dW5hdGVseSBpdCBhbHNvIGFkZGVkIHNvbWUgYmxhbmsgc3BhY2VzIGJldHdlZW4gd29yZHMgaW4gcXVvdGVzLiBBZnRlciBzb21lIGV4cGVyaW1lbnRpbmcgY291ZGxudCcgZmluZCBhIFJFR0VYIHRoYXQgd291bGQgSSBpc29sYXRlIGp1c3QgcmhlIHdvcmRzIHdpdGhpbiBxb3V0ZXMuIA0KIA0KSSBkZWNpZGVkIGp1c3QgdG8gZ28gYWhlYWQgcmVtb3ZlIGFsbCBlbXB0eSBzdHJpbmdzIGFkZGVkIHRvIHRoZSBsaXN0LiBOb3QgcHJldHR5IGJ1dCB3b3VsZCBnZXQgbWUgdGhlcmUNCg0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsNn0NCmRhdGEzIDwtIGRhdGEyW1sxXV1bc3RyX2NvdW50KGRhdGEyW1sxXV0scGF0dGVybj0iICIpIDwgMl0NCmRhdGEzDQpgYGANCg0KU28gdGhhdCBnaXZlcyBtZSB3aGF0IEkgd2FudCwgYSBsaXN0IG9mIHRoZSBqdXN0IHdvcmRzIGluIHRoZSBmaWxlLCB3aXRob3V0IHF1b3RlcyBhcm91bmQgdGhlbS4NCg0KTXkgbmV4dCBzdGVwIHdhcyB0byBtZXJnZSB0aGUgd29yZHMgaW4gdGhlIGxpc3Qgd2l0aCAiLCIgYXMgc2VwYXJhdG9yLg0KDQoNCmBgYHtyIGNvZGUtY2h1bmstbGFiZWw4fQ0KZGF0YTQ8LSBwYXN0ZShkYXRhMyxjb2xsYXBzZSA9ICdcIixcIicpDQp3cml0ZUxpbmVzKGRhdGE0KQ0KYGBgDQoNClNvIHRoaXMgQUxNT1NUIGNvbXBsZXRlbHkgZGlkIHRoZSB0cmljay4gSSBqdXN0IG5lZWQgdG8gYWRkICoqImMoIioqIGF0IHRoZSBiZWdpbm5pbmcgYW5kICoqIikqKiBhdCB0aGUgZW5kIGFuZCBQUkVTVE8uDQoNCg0KYGBge3IgY29kZS1jaHVuay1sYWJlbDl9DQpmaW5hbF9zdHJpbmcgPC0gcGFzdGUwKCdjKFwiJyxkYXRhNCwnXCIpJykNCndyaXRlTGluZXMoZmluYWxfc3RyaW5nKQ0KYGBgDQoNCioqRXhhY3R5IHRoZSBvdXRwdXQgcmVxdWVzdGVkIGluIHRoZSBleGVyY2lzZSBET05FISoqDQoNCg0KIyMgRXhlcmNpc2UgMw0KDQpEZXNjcmliZSwgaW4gd29yZHMsIHdoYXQgdGhlc2UgZXhwcmVzc2lvbnMgd2lsbCBtYXRjaDoNCg0KKC4pXDFcMQ0KDQoiKC4pKC4pXFwyXFwxIg0KDQooLi4pXDENCg0KIiguKS5cXDEuXFwxIg0KDQoiKC4pKC4pKC4pLipcXDNcXDJcXDEiDQoNCg0KKipBTlNXRVIqKg0KDQpMZXQncyBzdGFydCBieSBkZWZpbmluZyBhIHRlc3QgdmVjdG9yIHdlIGNhbiB1c2UgdG8gdGVzdCBvdXIgUkVHRVguDQoNCmBgYHtyIGNvZGUtY2h1bmstbGFiZWwxMH0NCnRlc3QgPC0gYygiYmVsbCBwZXBwZXIiLCAiYWFhaXJsaW5lcyIsICJiaWxiZXJyeSIsICJibGFja2JlcnJ5IiwgImJsb29kIG9yYW5nZSIsIA0KICAiYmx1ZWJlcnJ5IiwgImNhbnRhbG91cGUiLCAiY2hpbGkgcGVwcGVyIiwgImNodXJjaCIsImNsb3VkYmVycnkiLCANCiAgImVsZGVyYmVycnkiLCAibGltZSIsICJyaGJiYmYiLCAibHljaGVlIiwgIm11bGJlcnJ5IiwgIm9saXZlIiwNCiAgInNhbGFsIGJlcnJ5IiwgIjEyMzRhYjM0NSBiYTM0MyIsICIxMjM0YWIzNDViYTM0MyIsImFsaWJhYmEiLCAiYmVyZWIiLCANCiAgImJiZ3VuIiwgImFzZGJiYiIsICJiYWxhY2FiIiwgImJhbGFjYWJhIiwgIjEyMzQ1Njg5NjU0NDMiLCAiZXJiZXJiZXJiZWUiKQ0KDQpgYGANCg0KDQpOb3cgbGV0cyBsb29rIGFuZCB0ZXN0IHdoYXQgZWFjaCBSRUdFWCBkbw0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsMTBifQ0KDQojU2VhcmNoZXMgdGhlIHdob2xlIHN0cmluZyBhbmQgd291bGQgbWF0Y2ggMyBjb250aW51b3VzIG9mIHNhbWUgY2hhcmFjdGVyDQoNCnN0cl92aWV3X2FsbCh0ZXN0LCIoLilcXDFcXDEiKQ0KDQojU2VhcmNoZXMgdGhlIHdob2xlIHN0cmluZyBhbmQgbG9va3MgZm9yIDQgY2hhcmFjdGVycywgd2hlcmUNCiN0aGUgbGFzdCBwYWlyIG9mIHR3byBpcyBpbiByZXZlcnNlIG9yZGVyIHRoYW4gdGhlIGZpcnN0IHBhaXIgb2YgdHdvDQoNCnN0cl92aWV3X2FsbCh0ZXN0LCIoLikoLilcXDJcXDEiKQ0KDQojU2VhcmNoZXMgYW5kIGxvb2sgZm9yIDQgY29uc2VjdXRpdmUgY2hhcmFjdGVycyB3aGVyZSB0aGUgZmlyc3QNCiNwYWlyIG9mIGNoYXJhY3RlcnMgaXMgcmVwZWF0ZWQgb25jZQ0KDQpzdHJfdmlld19hbGwodGVzdCwiKC4uKVxcMSIpDQoNCiNMb29rcyBmb3IgYSBwYXR0ZXJuIG9mIHNhbWUgY2hhcmFjdGVyIHJlcGVhdGVkIDMgdGltZXMgd2l0aCBhIGNoYXJhY3Rlcg0KI2luIGJldHdlZW4NCg0Kc3RyX3ZpZXdfYWxsKHRlc3QsIiguKS5cXDEuXFwxIikNCg0KYGBgDQoNCg0KIyMgRXhlcmNpc2UgNA0KDQpDb25zdHJ1Y3QgcmVndWxhciBleHByZXNzaW9ucyB0byBtYXRjaCB3b3JkcyB0aGF0Og0KDQotIFN0YXJ0IGFuZCBlbmQgd2l0aCB0aGUgc2FtZSBjaGFyYWN0ZXIuDQotIENvbnRhaW4gYSByZXBlYXRlZCBwYWlyIG9mIGxldHRlcnMgKGUuZy4gImNodXJjaCIgY29udGFpbnMgImNoIiByZXBlYXRlZCB0d2ljZS4pDQotIENvbnRhaW4gb25lIGxldHRlciByZXBlYXRlZCBpbiBhdCBsZWFzdCB0aHJlZSBwbGFjZXMgKGUuZy4gImVsZXZlbiIgY29udGFpbnMgdGhyZWUgImUicy4pDQoNCg0KKipBTlNXRVIqKg0KTGV0J3MgbG9vayBhdCB0aGUgUkVHRVggSSBjYW1lIHVwIHdpdGggZm9yIGVhY2ggb2YgdGhlIGNhc2VzLg0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsMTF9DQojIFN0YXJ0IGFuZCBlbmQgd2l0aCB0aGUgc2FtZSBjaGFyYWN0ZXIuDQoNCnN0cl92aWV3X2FsbCh0ZXN0LCJeKC4pLipcXDEkIikNCg0KIyBDb250YWluIGEgcmVwZWF0ZWQgcGFpciBvZiBsZXR0ZXJzIChlLmcuICJjaHVyY2giIGNvbnRhaW5zIA0KIyAiY2giIHJlcGVhdGVkIHR3aWNlLikNCg0Kc3RyX3ZpZXdfYWxsKHRlc3QsIiguLikuKlxcMSIpDQoNCiMgb3INCg0Kc3RyX3ZpZXdfYWxsKHRlc3QsICIoW0EtWmEtel1bQS1aYS16XSkuKlxcMSIpDQoNCg0KIyBDb250YWluIG9uZSBsZXR0ZXIgcmVwZWF0ZWQgaW4gYXQgbGVhc3QgdGhyZWUgcGxhY2VzIChlLmcuICJlbGV2ZW4iIGNvbnRhaW5zIHRocmVlICJlInMuKSAgIA0KDQpzdHJfdmlld19hbGwodGVzdCwiKFthLXpdfFtBLVpdKS4qXFwxLipcXDEiKQ0KDQpgYGANCg0KDQoqKlRoYW5rIHlvdSEqKg0KDQoNCi4uLg0KDQo=