Assignment: Select another news organization and grab 5000 of their tweets. Some possibilities: For Billings Gazette headlines: billingsgazette Wall Street Journal: wsj Washington Post: washingtonpost CNN: cnn CNN breaking news: cnnbrk USA Today: usatoday
- Unnest the words of the tweets, remove stop words and weird web “words”, and create a table and a word cloud of the top words.
- Conduct a sentiment analysis using bing, remove any errors like trump = positive, and create a graph of the words that contribute most to each sentiment.
- Do the same as above but with the nrc sentiment lexicon.
- Unnest the tweets as bigrams, remove stop words and errors, and create a table and word cloud of the most common bigrams.
- Using the bigrams, look for the most common words that follow two different words. You may choose trump and pelosi, or choose your own.
news_tweets <- get_timeline("billingsgazette", n = 5000)
news_words <- news_tweets %>%
unnest_tokens(word, text) %>%
select(screen_name, word)
news_words %>%
count(word, sort = T)
news_words %>%
anti_join(get_stopwords()) %>%
count(word, sort = T)
Joining, by = "word"
news_words %>%
anti_join(get_stopwords()) %>%
filter(!word == "https",
!word == "t.co") %>%
count(word, sort = T)
Joining, by = "word"
news_words %>%
anti_join(get_stopwords()) %>%
filter(!word == "https",
!word == "t.co") %>%
count(word, sort = T) %>%
top_n(200) %>%
wordcloud2(size = .5)
Joining, by = "word"
Selecting by n
bing <- get_sentiments("bing")
bing
news_words %>%
inner_join(bing) %>%
count(word, sentiment, sort = TRUE)
Joining, by = "word"
news_words %>%
inner_join(bing) %>%
filter(!word == "trump") %>%
count(word, sentiment, sort = TRUE)
Joining, by = "word"
news_words %>%
inner_join(bing) %>%
filter(!word == "trump") %>%
count(word, sentiment, sort = TRUE)%>%
group_by(sentiment) %>%
top_n(10) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(word, n, fill = sentiment)) +
geom_col(show.legend = FALSE) +
facet_wrap(vars(sentiment), scales = "free") +
labs(y = "News headlines: Words that contribute the most to each sentiment",
x = NULL) +
coord_flip() +
theme_minimal()
Joining, by = "word"
Selecting by n

nrc <- get_sentiments("nrc")
nrc
nrc %>%
distinct(sentiment)
news_words %>%
inner_join(nrc) %>%
filter(!word == "trump") %>%
count(word, sentiment, sort = TRUE)%>%
group_by(sentiment) %>%
top_n(5) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(word, n, fill = sentiment)) +
geom_col(show.legend = FALSE) +
facet_wrap(vars(sentiment), scales = "free") +
labs(y = "News headlines: Words that contribute the most to each sentiment",
x = NULL) +
coord_flip() +
theme_minimal()
Joining, by = "word"
Selecting by n

news_tweets %>%
select(text) %>% # this selects just the text of the tweets
unnest_tokens(words, text, token = "ngrams", n = 2)
NA
news_tweets %>%
select(text) %>% #
unnest_tokens(words, text, token = "ngrams", n = 2) %>%
count(words, sort = T)
news_tweets %>%
select(text) %>% # this selects just the text of the tweets
unnest_tokens(words, text, token = "ngrams", n = 2) %>%
separate(words, c("word1", "word2"), sep = " ") %>% # separate them temporarily
filter(!word1 %in% stop_words$word) %>% # remove if first word is a stop word
filter(!word2 %in% stop_words$word) %>% # remove if second word is a stop word
unite(words, word1, word2, sep = " ") # put them back together
remove_words = c("https", "t.co")
news_tweets %>%
select(text) %>%
unnest_tokens(words, text, token = "ngrams", n = 2) %>%
separate(words, c("word1", "word2"), sep = " ") %>% # separate them temporarily
filter(!word1 %in% stop_words$word) %>% # remove if first word is a stop word
filter(!word2 %in% stop_words$word) %>% # remove if second word is a stop word
filter(!word1 %in% remove_words) %>% # these two lines remove our remove_words
filter(!word2 %in% remove_words) %>%
unite(words, word1, word2, sep = " ") # put them back together
remove_words = c("https", "t.co")
news_tweets %>%
select(text) %>%
unnest_tokens(words, text, token = "ngrams", n = 2) %>%
separate(words, c("word1", "word2"), sep = " ") %>% # separate them temporarily
filter(!word1 %in% stop_words$word) %>% # remove if first word is a stop word
filter(!word2 %in% stop_words$word) %>% # remove if second word is a stop word
filter(!word1 %in% remove_words) %>% # these two lines remove our remove_words
filter(!word2 %in% remove_words) %>%
unite(words, word1, word2, sep = " ") -> news_bigrams # put them back together
news_bigrams %>%
count(words, sort = T)
news_bigrams %>%
count(words, sort = T) %>%
top_n(100) %>%
wordcloud2(size = .5)
Selecting by n
NA
first_word <- c("trump", "covid19") # these need to be lowercase
news_bigrams %>%
count(words, sort = TRUE) %>%
separate(words, c("word1", "word2"), sep = " ") %>% # separate the two words
filter(word1 %in% first_word) %>% # find first words from our list
count(word1, word2, wt = n, sort = TRUE) %>%
rename(total = nn)
first_word <- c("trump", "covid19") # these need to be lowercase
news_bigrams %>%
count(words, sort = TRUE) %>%
separate(words, c("word1", "word2"), sep = " ") %>% # separate the two words
filter(word1 %in% first_word) %>% # find first words from our list
count(word1, word2, wt = n, sort = TRUE) %>%
rename(total = nn) %>%
mutate(word2 = factor(word2, levels = rev(unique(word2)))) %>% # put the words in order
group_by(word1) %>%
top_n(5) %>%
ggplot(aes(word2, total, fill = word1)) + #
scale_fill_viridis_d() + # set the color palette
geom_col(show.legend = FALSE) +
labs(x = NULL, y = NULL, title = "Word following:") +
facet_wrap(~word1, scales = "free") +
coord_flip()
Selecting by total

LS0tCnRpdGxlOiAiUmllc2VuIFR3ZWV0cyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKQXNzaWdubWVudDoKU2VsZWN0IGFub3RoZXIgbmV3cyBvcmdhbml6YXRpb24gYW5kIGdyYWIgNTAwMCBvZiB0aGVpciB0d2VldHMuClNvbWUgcG9zc2liaWxpdGllczoKRm9yIEJpbGxpbmdzIEdhemV0dGUgaGVhZGxpbmVzOiBiaWxsaW5nc2dhemV0dGUKV2FsbCBTdHJlZXQgSm91cm5hbDogd3NqCldhc2hpbmd0b24gUG9zdDogd2FzaGluZ3RvbnBvc3QKQ05OOiBjbm4KQ05OIGJyZWFraW5nIG5ld3M6IGNubmJyawpVU0EgVG9kYXk6IHVzYXRvZGF5CgoxLiBVbm5lc3QgdGhlIHdvcmRzIG9mIHRoZSB0d2VldHMsIHJlbW92ZSBzdG9wIHdvcmRzIGFuZCB3ZWlyZCB3ZWIgIndvcmRzIiwgYW5kIGNyZWF0ZSBhIHRhYmxlIGFuZCBhIHdvcmQgY2xvdWQgb2YgdGhlIHRvcCB3b3Jkcy4gIAoyLiBDb25kdWN0IGEgc2VudGltZW50IGFuYWx5c2lzIHVzaW5nIGJpbmcsIHJlbW92ZSBhbnkgZXJyb3JzIGxpa2UgdHJ1bXAgPSBwb3NpdGl2ZSwgYW5kIGNyZWF0ZSBhIGdyYXBoIG9mIHRoZSB3b3JkcyB0aGF0IGNvbnRyaWJ1dGUgbW9zdCB0byBlYWNoIHNlbnRpbWVudC4gIAozLiBEbyB0aGUgc2FtZSBhcyBhYm92ZSBidXQgd2l0aCB0aGUgbnJjIHNlbnRpbWVudCBsZXhpY29uLiAgCjQuIFVubmVzdCB0aGUgdHdlZXRzIGFzIGJpZ3JhbXMsIHJlbW92ZSBzdG9wIHdvcmRzIGFuZCBlcnJvcnMsIGFuZCBjcmVhdGUgYSB0YWJsZSBhbmQgd29yZCBjbG91ZCBvZiB0aGUgbW9zdCBjb21tb24gYmlncmFtcy4gIAo1LiBVc2luZyB0aGUgYmlncmFtcywgbG9vayBmb3IgdGhlIG1vc3QgY29tbW9uIHdvcmRzIHRoYXQgZm9sbG93IHR3byBkaWZmZXJlbnQgd29yZHMuIFlvdSBtYXkgY2hvb3NlIHRydW1wIGFuZCBwZWxvc2ksIG9yIGNob29zZSB5b3VyIG93bi4gIAoKYGBge3J9Cm5ld3NfdHdlZXRzIDwtIGdldF90aW1lbGluZSgiYmlsbGluZ3NnYXpldHRlIiwgbiA9IDUwMDApCmBgYAoKYGBge3J9Cm5ld3Nfd29yZHMgPC0gbmV3c190d2VldHMgJT4lIAogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCkgJT4lIAogIHNlbGVjdChzY3JlZW5fbmFtZSwgd29yZCkKYGBgCgoKYGBge3J9Cm5ld3Nfd29yZHMgJT4lCiAgY291bnQod29yZCwgc29ydCA9IFQpCmBgYAoKYGBge3J9Cm5ld3Nfd29yZHMgJT4lIAogIGFudGlfam9pbihnZXRfc3RvcHdvcmRzKCkpICU+JSAKICBjb3VudCh3b3JkLCBzb3J0ID0gVCkKYGBgCgoKYGBge3J9Cm5ld3Nfd29yZHMgJT4lIAogIGFudGlfam9pbihnZXRfc3RvcHdvcmRzKCkpICU+JSAKICBmaWx0ZXIoIXdvcmQgPT0gImh0dHBzIiwKICAgICAgICAgIXdvcmQgPT0gInQuY28iKSAlPiUKICBjb3VudCh3b3JkLCBzb3J0ID0gVCkKYGBgCgoKYGBge3J9Cm5ld3Nfd29yZHMgJT4lIAogIGFudGlfam9pbihnZXRfc3RvcHdvcmRzKCkpICU+JSAKICBmaWx0ZXIoIXdvcmQgPT0gImh0dHBzIiwKICAgICAgICAgIXdvcmQgPT0gInQuY28iKSAlPiUKICBjb3VudCh3b3JkLCBzb3J0ID0gVCkgJT4lCiAgdG9wX24oMjAwKSAlPiUKICB3b3JkY2xvdWQyKHNpemUgPSAuNSkKYGBgCgoKYGBge3J9CmJpbmcgPC0gZ2V0X3NlbnRpbWVudHMoImJpbmciKQpiaW5nCmBgYAoKCmBgYHtyfQpuZXdzX3dvcmRzICU+JSAKICBpbm5lcl9qb2luKGJpbmcpICU+JSAKICBjb3VudCh3b3JkLCBzZW50aW1lbnQsIHNvcnQgPSBUUlVFKQoKYGBgCgoKCmBgYHtyfQpuZXdzX3dvcmRzICU+JSAKICBpbm5lcl9qb2luKGJpbmcpICU+JSAKICBmaWx0ZXIoIXdvcmQgPT0gInRydW1wIikgJT4lCiAgY291bnQod29yZCwgc2VudGltZW50LCBzb3J0ID0gVFJVRSkgCmBgYAoKCmBgYHtyfQpuZXdzX3dvcmRzICU+JSAKICBpbm5lcl9qb2luKGJpbmcpICU+JSAKICBmaWx0ZXIoIXdvcmQgPT0gInRydW1wIikgJT4lCiAgY291bnQod29yZCwgc2VudGltZW50LCBzb3J0ID0gVFJVRSklPiUKICBncm91cF9ieShzZW50aW1lbnQpICU+JQogIHRvcF9uKDEwKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKHdvcmQgPSByZW9yZGVyKHdvcmQsIG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHdvcmQsIG4sIGZpbGwgPSBzZW50aW1lbnQpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAodmFycyhzZW50aW1lbnQpLCBzY2FsZXMgPSAiZnJlZSIpICsKICBsYWJzKHkgPSAiTmV3cyBoZWFkbGluZXM6IFdvcmRzIHRoYXQgY29udHJpYnV0ZSB0aGUgbW9zdCB0byBlYWNoIHNlbnRpbWVudCIsCiAgICAgICB4ID0gTlVMTCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKCgpgYGB7cn0KbnJjIDwtIGdldF9zZW50aW1lbnRzKCJucmMiKQpucmMKYGBgCgoKYGBge3J9Cm5yYyAlPiUKICBkaXN0aW5jdChzZW50aW1lbnQpCmBgYAoKCgpgYGB7cn0KbmV3c193b3JkcyAlPiUgCiAgaW5uZXJfam9pbihucmMpICU+JSAKICBmaWx0ZXIoIXdvcmQgPT0gInRydW1wIikgJT4lCiAgY291bnQod29yZCwgc2VudGltZW50LCBzb3J0ID0gVFJVRSklPiUKICBncm91cF9ieShzZW50aW1lbnQpICU+JQogIHRvcF9uKDUpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUod29yZCA9IHJlb3JkZXIod29yZCwgbikpICU+JQogIGdncGxvdChhZXMod29yZCwgbiwgZmlsbCA9IHNlbnRpbWVudCkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh2YXJzKHNlbnRpbWVudCksIHNjYWxlcyA9ICJmcmVlIikgKwogIGxhYnMoeSA9ICJOZXdzIGhlYWRsaW5lczogV29yZHMgdGhhdCBjb250cmlidXRlIHRoZSBtb3N0IHRvIGVhY2ggc2VudGltZW50IiwKICAgICAgIHggPSBOVUxMKSArCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgoKCmBgYHtyfQpuZXdzX3R3ZWV0cyAlPiUKICBzZWxlY3QodGV4dCkgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhpcyBzZWxlY3RzIGp1c3QgdGhlIHRleHQgb2YgdGhlIHR3ZWV0cwogIHVubmVzdF90b2tlbnMod29yZHMsIHRleHQsIHRva2VuID0gIm5ncmFtcyIsIG4gPSAyKQoKYGBgCgpgYGB7cn0KbmV3c190d2VldHMgJT4lCiAgc2VsZWN0KHRleHQpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjCiAgdW5uZXN0X3Rva2Vucyh3b3JkcywgdGV4dCwgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDIpICU+JQogIGNvdW50KHdvcmRzLCBzb3J0ID0gVCkKYGBgCgpgYGB7cn0KbmV3c190d2VldHMgJT4lCiAgc2VsZWN0KHRleHQpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoaXMgc2VsZWN0cyBqdXN0IHRoZSB0ZXh0IG9mIHRoZSB0d2VldHMKICB1bm5lc3RfdG9rZW5zKHdvcmRzLCB0ZXh0LCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikgJT4lIAogIHNlcGFyYXRlKHdvcmRzLCBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpICU+JSAgICAgICAgICAjIHNlcGFyYXRlIHRoZW0gdGVtcG9yYXJpbHkKICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUgICAgICAgICAgICAgICAgICAgICAgIyByZW1vdmUgaWYgZmlyc3Qgd29yZCBpcyBhIHN0b3Agd29yZAogIGZpbHRlcighd29yZDIgJWluJSBzdG9wX3dvcmRzJHdvcmQpICU+JSAgICAgICAgICAgICAgICAgICAgICAjIHJlbW92ZSBpZiBzZWNvbmQgd29yZCBpcyBhIHN0b3Agd29yZCAgIAogIHVuaXRlKHdvcmRzLCB3b3JkMSwgd29yZDIsIHNlcCA9ICIgIikgICAgICAgICAgICAgICAgICAgICAgICAjIHB1dCB0aGVtIGJhY2sgdG9nZXRoZXIKYGBgCgoKYGBge3J9CnJlbW92ZV93b3JkcyA9IGMoImh0dHBzIiwgInQuY28iKQoKbmV3c190d2VldHMgJT4lCiAgc2VsZWN0KHRleHQpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICB1bm5lc3RfdG9rZW5zKHdvcmRzLCB0ZXh0LCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikgJT4lIAogIHNlcGFyYXRlKHdvcmRzLCBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpICU+JSAgICAgICAgICAjIHNlcGFyYXRlIHRoZW0gdGVtcG9yYXJpbHkKICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUgICAgICAgICAgICAgICAgICAgICAgIyByZW1vdmUgaWYgZmlyc3Qgd29yZCBpcyBhIHN0b3Agd29yZAogIGZpbHRlcighd29yZDIgJWluJSBzdG9wX3dvcmRzJHdvcmQpICU+JSAgICAgICAgICAgICAgICAgICAgICAjIHJlbW92ZSBpZiBzZWNvbmQgd29yZCBpcyBhIHN0b3Agd29yZCAgIAogIGZpbHRlcighd29yZDEgJWluJSByZW1vdmVfd29yZHMpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZXNlIHR3byBsaW5lcyByZW1vdmUgb3VyIHJlbW92ZV93b3JkcwogIGZpbHRlcighd29yZDIgJWluJSByZW1vdmVfd29yZHMpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAKICB1bml0ZSh3b3Jkcywgd29yZDEsIHdvcmQyLCBzZXAgPSAiICIpICAgICAgICAgICAgICAgICAgICAgICAgIyBwdXQgdGhlbSBiYWNrIHRvZ2V0aGVyCmBgYAoKCmBgYHtyfQpyZW1vdmVfd29yZHMgPSBjKCJodHRwcyIsICJ0LmNvIikKCm5ld3NfdHdlZXRzICU+JQogIHNlbGVjdCh0ZXh0KSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgdW5uZXN0X3Rva2Vucyh3b3JkcywgdGV4dCwgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDIpICU+JSAKICBzZXBhcmF0ZSh3b3JkcywgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKSAlPiUgICAgICAgICAgIyBzZXBhcmF0ZSB0aGVtIHRlbXBvcmFyaWx5CiAgZmlsdGVyKCF3b3JkMSAlaW4lIHN0b3Bfd29yZHMkd29yZCkgJT4lICAgICAgICAgICAgICAgICAgICAgICMgcmVtb3ZlIGlmIGZpcnN0IHdvcmQgaXMgYSBzdG9wIHdvcmQKICBmaWx0ZXIoIXdvcmQyICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUgICAgICAgICAgICAgICAgICAgICAgIyByZW1vdmUgaWYgc2Vjb25kIHdvcmQgaXMgYSBzdG9wIHdvcmQgICAKICBmaWx0ZXIoIXdvcmQxICVpbiUgcmVtb3ZlX3dvcmRzKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGVzZSB0d28gbGluZXMgcmVtb3ZlIG91ciByZW1vdmVfd29yZHMKICBmaWx0ZXIoIXdvcmQyICVpbiUgcmVtb3ZlX3dvcmRzKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgCiAgdW5pdGUod29yZHMsIHdvcmQxLCB3b3JkMiwgc2VwID0gIiAiKSAtPiBuZXdzX2JpZ3JhbXMgICAgICAgICAgICAgICAgICAgICAgICMgcHV0IHRoZW0gYmFjayB0b2dldGhlcgpgYGAKCgoKCmBgYHtyfQpuZXdzX2JpZ3JhbXMgJT4lIAogIGNvdW50KHdvcmRzLCBzb3J0ID0gVCkKYGBgCgoKYGBge3J9Cm5ld3NfYmlncmFtcyAlPiUgCiAgY291bnQod29yZHMsIHNvcnQgPSBUKSAlPiUKICB0b3BfbigxMDApICU+JQogIHdvcmRjbG91ZDIoc2l6ZSA9IC41KQogIApgYGAKCgoKYGBge3J9CmZpcnN0X3dvcmQgPC0gYygidHJ1bXAiLCAiY292aWQxOSIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhlc2UgbmVlZCB0byBiZSBsb3dlcmNhc2UKCm5ld3NfYmlncmFtcyAlPiUgICAgICAgICAgICAgCiAgY291bnQod29yZHMsIHNvcnQgPSBUUlVFKSAlPiUKICBzZXBhcmF0ZSh3b3JkcywgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKSAlPiUgICAgICAgIyBzZXBhcmF0ZSB0aGUgdHdvIHdvcmRzCiAgZmlsdGVyKHdvcmQxICVpbiUgZmlyc3Rfd29yZCkgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAjIGZpbmQgZmlyc3Qgd29yZHMgZnJvbSBvdXIgbGlzdAogIGNvdW50KHdvcmQxLCB3b3JkMiwgd3QgPSBuLCBzb3J0ID0gVFJVRSkgJT4lIAogIHJlbmFtZSh0b3RhbCA9IG5uKQpgYGAKCmBgYHtyfQpmaXJzdF93b3JkIDwtIGMoInRydW1wIiwgImNvdmlkMTkiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZXNlIG5lZWQgdG8gYmUgbG93ZXJjYXNlCgpuZXdzX2JpZ3JhbXMgJT4lICAgICAgICAgICAgIAogIGNvdW50KHdvcmRzLCBzb3J0ID0gVFJVRSkgJT4lCiAgc2VwYXJhdGUod29yZHMsIGMoIndvcmQxIiwgIndvcmQyIiksIHNlcCA9ICIgIikgJT4lICAgICAgICMgc2VwYXJhdGUgdGhlIHR3byB3b3JkcwogIGZpbHRlcih3b3JkMSAlaW4lIGZpcnN0X3dvcmQpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgIyBmaW5kIGZpcnN0IHdvcmRzIGZyb20gb3VyIGxpc3QKICBjb3VudCh3b3JkMSwgd29yZDIsIHd0ID0gbiwgc29ydCA9IFRSVUUpICU+JSAKICByZW5hbWUodG90YWwgPSBubikgJT4lCiAgbXV0YXRlKHdvcmQyID0gZmFjdG9yKHdvcmQyLCBsZXZlbHMgPSByZXYodW5pcXVlKHdvcmQyKSkpKSAlPiUgICAgICMgcHV0IHRoZSB3b3JkcyBpbiBvcmRlcgogIGdyb3VwX2J5KHdvcmQxKSAlPiUgCiAgdG9wX24oNSkgJT4lIAogIGdncGxvdChhZXMod29yZDIsIHRvdGFsLCBmaWxsID0gd29yZDEpKSArICAgICAgICAgICAgICAgICAgICAgICAgICAjCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc2V0IHRoZSBjb2xvciBwYWxldHRlCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCB0aXRsZSA9ICJXb3JkIGZvbGxvd2luZzoiKSArCiAgZmFjZXRfd3JhcCh+d29yZDEsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQpgYGAKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg==