About this Notebook
On this notebook we are going to analysis tweets from march madness 2018
Use regular expression to clean the tweets text
Familiarize with some natural language processing tools
Sentiment Analysis: Natural Language Processing
First lets read the dataset and inspect the first 10 rows
tweets <- read_csv("data/march_madness_sent.csv")
tweets$tweet_id <- as.character(tweets$tweet_id)
head(tweets[12:21])
For sentiment analysis we are going to use the cleanNLP package that uses Stanford CoreNLP – Natural language software int he backend. First we need to initialize the CoreNLP engine and create an annotation object using the text column, tweet_id and the other columns are given as metadata
cnlp_init_udpipe()
doc <- cnlp_annotate(input = tweets$text, as_strings = TRUE, doc_ids = tweets$tweet_id, meta = tweets[-c(1,2)])
Lets explore the emotions in the tweets more in-depth. Here we are going to extract the variables regarding emotions and create a subset.
value <- as.double(colSums(prop.table(tweets[, 11:18])))
emotion <- names(tweets)[11:18]
emotion <- factor(emotion, levels = names(tweets)[11:18][order(value, decreasing = FALSE)])
emotions <- data_frame(emotion, percent = value * 100)
head(emotions)
LS0tCnRpdGxlOiAiTWFyY2ggTWFkbmVzcyBBbmFseXNpcyIKYXV0aG9yOiAKLSAiUXVpbmxhbiBTY2hvb2wgb2YgQnVzaW5lc3MgLSBMb3lvbGEgVW5pdmVyc2l0eSBDaGljYWdvIgotICJKb3NlIEx1aXMgUm9kcmlndWV6IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKZGF0ZTogIkFwcmlsIDksIDIwMTgiCnN1YnRpdGxlOiAiQ01FIEdyb3VwIEZvdW5kYXRpb24gQnVzaW5lc3MgQW5hbHl0aWNzIExhYiIKLS0tCgo8YnI+CgotLS0tLS0tLS0tLS0tLQoKIyMgQWJvdXQgdGhpcyBOb3RlYm9vawoKLS0tLS0tLS0tLS0tLS0KCiogT24gdGhpcyBub3RlYm9vayB3ZSBhcmUgZ29pbmcgdG8gYW5hbHlzaXMgdHdlZXRzIGZyb20gbWFyY2ggbWFkbmVzcyAyMDE4CgoqIFVzZSByZWd1bGFyIGV4cHJlc3Npb24gdG8gY2xlYW4gdGhlIHR3ZWV0cyB0ZXh0CgoqIEZhbWlsaWFyaXplIHdpdGggc29tZSBuYXR1cmFsIGxhbmd1YWdlIHByb2Nlc3NpbmcgdG9vbHMKCjxicj4KCi0tLS0tLS0tLS0tLS0tCgojIyBBbmFseXRpY3MgVG9vbGtpdDogUmVxdWlyZSBQYWNrYWdlcwoKLS0tLS0tLS0tLS0tLS0KCjxicj4KCiogdGlkeXZlcnNlOiBodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLwoqIHN5dXpoZXQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9tam9ja2Vycy9zeXV6aGV0CiogY2xlYW5OTFA6IGh0dHBzOi8vZ2l0aHViLmNvbS9zdGF0c21hdGhzL2NsZWFuTkxQCiogd29yZGNsb3VkOiBodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvd29yZGNsb3VkL3dvcmRjbG91ZC5wZGYKCmBgYHtyICwgbWVzc2FnZT1GQUxTRX0KCiMgSGVyZSB3ZSBhcmUgY2hlY2tpbmcgaWYgdGhlIHBhY2thZ2UgaXMgaW5zdGFsbGVkCmlmKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSl7CiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkKICBsaWJyYXJ5KCJ0aWR5dmVyc2UiKQp9CgppZighcmVxdWlyZSgic3l1emhldCIpKXsKICBpbnN0YWxsLnBhY2thZ2VzKCJzeXV6aGV0IiwgZGVwZW5kZW5jaWVzID0gVFJVRSkKICBsaWJyYXJ5KCJzeXV6aGV0IikKfQoKaWYoIXJlcXVpcmUoImNsZWFuTkxQIikpewogIGluc3RhbGwucGFja2FnZXMoImNsZWFuTkxQIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkKICBsaWJyYXJ5KCJjbGVhbk5MUCIpCn0KCmlmKCFyZXF1aXJlKCJtYWdyaXR0ciIpKXsKICBpbnN0YWxsLnBhY2thZ2VzKCJtYWdyaXR0ciIsIGRlcGVuZGVuY2llcyA9IFRSVUUpCiAgbGlicmFyeSgibWFncml0dHIiKQp9CgppZighcmVxdWlyZSgid29yZGNsb3VkIikpewogIGluc3RhbGwucGFja2FnZXMoIndvcmRjbG91ZCIsIGRlcGVuZGVuY2llcyA9IFRSVUUpCiAgbGlicmFyeSgid29yZGNsb3VkIikKfQoKYGBgCgo8YnI+CgotLS0tLS0tLS0tLS0tLQoKIyMgRGF0YSBQcmVwYXJhdGlvbjogQ2xlYW5pbmcgdHdlZXRzIHVzaW5nIHJlZ3VsYXIgZXhwcmVzc2lvbnMKCi0tLS0tLS0tLS0tLS0tCgo8YnI+CgojIyMjIFJlYWRpbmcgYW5kIGluc3BlY3RpbmcgdGhlIGRhdGFzZXQKYGBge3IsIG1lc3NhZ2U9RkFMU0V9CnR3ZWV0cyA8LSByZWFkX2NzdigiZGF0YS9tYXJjaF9tYWRuZXNzLmNzdiIpCgojIENoYW5nZSB0aGUgdHdlZXRzIElEcyBmcm9tIGxvbmdlIGludGVnZXIgdG8gY2hhcmFjdGVycwp0d2VldHMkdHdlZXRfaWQgPC0gYXMuY2hhcmFjdGVyKHR3ZWV0cyR0d2VldF9pZCkKCiMgRXh0cmFjdCBhbmQgZGVsZXRlIHRoZSBsaW5rcyB2YXJpYWJsZSB0byBhZGQgaXQgYXQgdGhlIGVuZApsaW5rcyA8LSB0d2VldHMkbGlua3MKdHdlZXRzJGxpbmtzIDwtIE5VTEwKCiMgSW5zcGVjdHMgdGhlIGZpcnN0IDEwIHJvd3MKaGVhZCh0d2VldHMpCmBgYAoKPGJyPgoKIyMjIyBOb3cgZmlyc3Qgd2UgbmVlZCB0byBleHRyYWN0IHRoZSB0ZXh0IGZyb20gdGhlIHJhdyB0d2VldHMgYW5kIGNsZWFuIGl0IHVzaW5nIHJlZ3VsYXIgZXhwcmVzc2lvbnMKYGBge3J9CnJlcGxhY2VfcmVnIDwtICdodHRwczovL3QuY28vW0EtWmEtelxcZF0rfGh0dHA6Ly9bQS1aYS16XFxkXSt8KHBpYy50d2l0dGVyLmNvbS9bQS1aYS16XFxkXSspfCZhbXA7fCZsdDt8Jmd0O3xSVHwoLiouKVxcLmNvbSguKi4pXFxTK1xcc3xbXls6YWxudW06XV18KGh0dHB8aHR0cHMpXFxTK1xccyp8KCN8QClcXFMrXFxzKnxcXG58XFwiJwoKdHdlZXRzIDwtIHR3ZWV0cyAlPiUgCiAgbXV0YXRlKHRleHQgPSBzdHJfcmVwbGFjZV9hbGwodGV4dCwgcmVwbGFjZV9yZWcsICIgIikpICU+JSAKICBtdXRhdGUodGV4dCA9IGljb252KHRleHQsIGZyb20gPSAiQVNDSUkiLCB0byA9ICJVVEYtOCIsIHN1YiA9ICIgIikpCgpoZWFkKHR3ZWV0c1sndGV4dCddKQpgYGAKCjxicj4KCiMjIyMgSGVyZSB3ZSBhcmUgZ29pbmcgdG8gdXNlIHRoZSBTYWlmIE1vaGFtbWFk4oCZcyBOUkMgRW1vdGlvbiBsZXhpY29uIHRvZXh0cmFjdCB0aGUgc2VudGltZW50IG9mIHRoZSB0d2VldC4gVGhlIE5SQyBlbW90aW9uIGxleGljb24gaXMgYSBsaXN0IG9mIHdvcmRzIGFuZCB0aGVpciBhc3NvY2lhdGlvbnMgd2l0aCBlaWdodCBlbW90aW9ucyAoYW5nZXIsIGZlYXIsIGFudGljaXBhdGlvbiwgdHJ1c3QsIHN1cnByaXNlLCBzYWRuZXNzLCBqb3ksIGFuZCBkaXNndXN0KSBhbmQgdHdvIHNlbnRpbWVudHMgKG5lZ2F0aXZlIGFuZCBwb3NpdGl2ZSkuCgoqIFNvdXJjZTogaHR0cDovL3NhaWZtb2hhbW1hZC5jb20vV2ViUGFnZXMvTlJDLUVtb3Rpb24tTGV4aWNvbi5odG0KCmBgYHtyfQpucmNfZGF0YSA8LSBnZXRfbnJjX3NlbnRpbWVudCh0d2VldHMkdGV4dCkKbnJjX2RhdGEgPC0gYXNfdGliYmxlKG5yY19kYXRhKQoKaGVhZChucmNfZGF0YSkKYGBgCgo8YnI+CgojIyMjIEhlcmUgd2UgYXJlIGdvaW5nIHRvIG1lcmdlIHRoZSBOUkMgRW1vdGlvbiByZXN1bHRzIHdpdGggdGhlIG9yaWdpbmFsIGRhdGEgdG8gY3JlYXRlIGEgY29tcGxldGUgZGF0YXNldC4KYGBge3J9CnR3ZWV0cyA8LSBiaW5kX2NvbHModHdlZXRzLCBucmNfZGF0YSkKCmBgYAoKPGJyPgoKIyMjIyBUbyBoYXZlIGFub3RoZXIgbWV0cmljcyBmb3Igc2VtdGltZW50IHdlIGFyZSBnb2luZyB0byB1c2UgYW5vdGhlciBsZXhpY29uIGRldmVsb3BlZCBieSBQcm9mZXNzb3IgTWlucWluZyBIdSBhbmQgUHJvZmVzc29yIEJpbmcgTGl1LCBmcm9tIFVuaXZlcnNpdHkgb2YgSWxsaW5vaXMgYXQgQ2hpY2Fnby4KKiBTb3VyY2U6IGh0dHA6Ly93d3cuY3MudWljLmVkdS9+bGl1Yi9GQlMvc2VudGltZW50LWFuYWx5c2lzLmh0bWwKCmBgYHtyfQp0d2VldHMkc2VudGltZW50X2JpbmcgPC0gZ2V0X3NlbnRpbWVudChjaGFyX3YgPSB0d2VldHMkdGV4dCwgbWV0aG9kPSJiaW5nIiwgbGFuZ3VhZ2UgPSAiZW5nbGlzaCIpCgpgYGAKCjxicj4KCiMjIyMgRmluYWxseSBhZGQgdGhlIGxpbmtzIHZhcmlhYmxlIGFuZCBzYXZlIHRoZSBuZXcgY29tcGxldGUgZGF0YXNldCAKYGBge3J9CnR3ZWV0cyRsaW5rcyA8LSBsaW5rcwoKd3JpdGVfY3N2KHR3ZWV0cywgImRhdGEvbWFyY2hfbWFkbmVzc19zZW50LmNzdiIpCgpoZWFkKHR3ZWV0c1szOjEwXSkKYGBgCgo8YnI+CgotLS0tLS0tLS0tLS0tLQoKIyMgU2VudGltZW50IEFuYWx5c2lzOiBOYXR1cmFsIExhbmd1YWdlIFByb2Nlc3NpbmcKCi0tLS0tLS0tLS0tLS0tCgo8YnI+CgojIyMjIEZpcnN0IGxldHMgcmVhZCB0aGUgZGF0YXNldCBhbmQgaW5zcGVjdCB0aGUgZmlyc3QgMTAgcm93cwpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KdHdlZXRzIDwtIHJlYWRfY3N2KCJkYXRhL21hcmNoX21hZG5lc3Nfc2VudC5jc3YiKQp0d2VldHMkdHdlZXRfaWQgPC0gYXMuY2hhcmFjdGVyKHR3ZWV0cyR0d2VldF9pZCkKaGVhZCh0d2VldHNbMTI6MjFdKQpgYGAKCjxicj4KCiMjIyMgRm9yIHNlbnRpbWVudCBhbmFseXNpcyB3ZSBhcmUgZ29pbmcgdG8gdXNlIHRoZSBjbGVhbk5MUCBwYWNrYWdlIHRoYXQgdXNlcyBTdGFuZm9yZCBDb3JlTkxQIOKAkyBOYXR1cmFsIGxhbmd1YWdlIHNvZnR3YXJlIGludCBoZSBiYWNrZW5kLiBGaXJzdCB3ZSBuZWVkIHRvIGluaXRpYWxpemUgdGhlIENvcmVOTFAgZW5naW5lIGFuZCBjcmVhdGUgYW4gYW5ub3RhdGlvbiBvYmplY3QgdXNpbmcgdGhlIHRleHQgY29sdW1uLCB0d2VldF9pZCBhbmQgdGhlIG90aGVyIGNvbHVtbnMgYXJlIGdpdmVuIGFzIG1ldGFkYXRhCmBgYHtyfQpjbmxwX2luaXRfdWRwaXBlKCkKCmRvYyA8LSBjbmxwX2Fubm90YXRlKGlucHV0ID0gdHdlZXRzJHRleHQsIGFzX3N0cmluZ3MgPSBUUlVFLCBkb2NfaWRzID0gdHdlZXRzJHR3ZWV0X2lkLCBtZXRhID0gdHdlZXRzWy1jKDEsMildKQoKYGBgCgo8YnI+CgojIyMjIERpc3RyaWJ1dGlvbiBvZiB0d2VldC9zZW50ZW5jZSBsZW5ndGgsIG1heCBudW1iZXIgb2Ygd29ya3MgaW4gYSB0d2VldCAyODAKYGBge3J9CnRva2VucyA8LSBjbmxwX2dldF90b2tlbihkb2MpICU+JQogIGdyb3VwX2J5KGlkLCBzaWQpICU+JQogIHN1bW1hcml6ZShzZW50X2xlbiA9IG4oKSkKCnF1YW50aWxlKHRva2VucyRzZW50X2xlbiwgc2VxKDAsMSwwLjEpKQoKYGBgCgo8YnI+CgojIyMjIEhlcmUgd2UgY2FuIHNlZSB0aGUgY2hhbmdlIG9mIHNlbnRpbWVudCBpbiB0aGUgdHdlZXRzIApgYGB7cn0KcXBsb3QoeCA9IDE6bGVuZ3RoKHR3ZWV0cyRzZW50aW1lbnRfYmluZyksIAogICAgICB5ID0gdHdlZXRzJHNlbnRpbWVudF9iaW5nLCAKICAgICAgZ2VvbSA9ICJsaW5lIiwgCiAgICAgIHhsYWIgPSAiTmFycmF0aXZlIFRpbWUiLCAKICAgICAgeWxhYiA9ICJFbW90aW9uYWwgVmFsZW5jZSIsIAogICAgICBtYWluID0gIlR3ZWV0cyBTZW50aW1lbnQgVHJhamVjdG9yeSIpCgpgYGAKCjxicj4KCiMjIyMgSGVyZSB3ZSBjYW4gZmluZCB0aGUgbW9zdCB1c2VkIGVudGl0aWVzIGZyb20gdGhlIHR3ZWV0cyBlbnRpdHkgdGFibGUuIFRoZSBkb2N1bWVudCBjb3JwdXMgeWllbGRzIGFuIGFsdGVybmF0aXZlIHdheSB0byBzZWUgdGhlIHVuZGVybHlpbmcgdG9waWNzLgpgYGB7cn0KdHdlZXRzX2VudGl0aWVzIDwtIGNubHBfZ2V0X3Rva2VuKGRvYykgJT4lCiAgZmlsdGVyKHVwb3MgPT0gIk5PVU4iKSAlPiUKICBncm91cF9ieShsZW1tYSkgJT4lCiAgc3VtbWFyaXplKGNvdW50ID0gbigpKSAlPiUKICB0b3BfbihuID0gODAsIGNvdW50KSAlPiUKICBhcnJhbmdlKGRlc2MoY291bnQpKSAlPiUKICB1c2Vfc2VyaWVzKGxlbW1hKQoKZGF0YV9mcmFtZSh0d2VldHNfZW50aXRpZXMpCgpgYGAKCjxicj4KCiMjIyMgSGVyZSB3ZSBjcmVhdGluZyBhIGhpZ2gtbGV2ZWwgc3VtbWFyeSBvZiB0aGUgdHdlZXRzIHRleHQgYnkgZXh0cmFjdGluZyBhbGwgZGlyZWN0IG9iamVjdCBvYmplY3QtZGVwZW5kZW5jaWVzLgpgYGB7cn0KdHdlZXRzX3N1bW1hcnkgPC0gY25scF9nZXRfZGVwZW5kZW5jeShkb2MsIGdldF90b2tlbiA9IFRSVUUpICU+JQogIGxlZnRfam9pbihjbmxwX2dldF9kb2N1bWVudChkb2MpKSAlPiUKICBzZWxlY3QoaWQgPSBpZCwgc3RhcnQgPSB3b3JkLCB3b3JkID0gbGVtbWFfdGFyZ2V0KSAlPiUKICBsZWZ0X2pvaW4od29yZF9mcmVxdWVuY3kpICU+JQogIGZpbHRlcihmcmVxdWVuY3kgPCAwLjAwMDEpICU+JQogIHNlbGVjdChpZCwgc3RhcnQsIHdvcmQpICUkJQogIHNwcmludGYoIiVzID0+ICVzIiwgc3RhcnQsIHdvcmQpCgpkYXRhX2ZyYW1lKHR3ZWV0c19zdW1tYXJ5KQoKYGBgCgo8YnI+CgojIyMjIExvb2sgYXQgdGhlIHR3ZWV0cyB3aXRoIG5lZ2F0aXZlIHNlbnRpbWVudCAKYGBge3J9CgphbmdyeV90d2VldHMgPC0gd2hpY2godHdlZXRzJGFuZ2VyID4gMCkKZGF0YV9mcmFtZSh0d2VldCA9IHR3ZWV0cyR0ZXh0W2FuZ3J5X3R3ZWV0c11bMToyXSkKCmBgYAoKPGJyPgoKIyMjIyBMb29rIGEgdHdlZXRzIHdpdGggcG9zaXRpdmUgc2VudGltZW50CmBgYHtyfQpqb3lfdHdlZXRzIDwtIHdoaWNoKHR3ZWV0cyRqb3kgPiAwKQpkYXRhX2ZyYW1lKHR3ZWV0ID0gdHdlZXRzJHRleHRbam95X3R3ZWV0c11bNTo3XSkKCmBgYAoKPGJyPgoKIyMjIyBMZXRzIGV4cGxvcmUgdGhlIGVtb3Rpb25zIGluIHRoZSB0d2VldHMgbW9yZSBpbi1kZXB0aC4gSGVyZSB3ZSBhcmUgZ29pbmcgdG8gZXh0cmFjdCB0aGUgdmFyaWFibGVzIHJlZ2FyZGluZyBlbW90aW9ucyBhbmQgY3JlYXRlIGEgc3Vic2V0LgpgYGB7cn0KdmFsdWUgPC0gYXMuZG91YmxlKGNvbFN1bXMocHJvcC50YWJsZSh0d2VldHNbLCAxMToxOF0pKSkKZW1vdGlvbiA8LSBuYW1lcyh0d2VldHMpWzExOjE4XQplbW90aW9uIDwtIGZhY3RvcihlbW90aW9uLCBsZXZlbHMgPSBuYW1lcyh0d2VldHMpWzExOjE4XVtvcmRlcih2YWx1ZSwgZGVjcmVhc2luZyA9IEZBTFNFKV0pCmVtb3Rpb25zIDwtIGRhdGFfZnJhbWUoZW1vdGlvbiwgcGVyY2VudCA9IHZhbHVlICogMTAwKQoKaGVhZChlbW90aW9ucykKYGBgCgo8YnI+CgojIyMjIE5vdyB3ZSBjYW4gY3JlYXRlIGEgcGxvdCBvZiB0aGUgZW1vdGlvbnMgaW4gdGhlIG1hcmNoIG1hZG5lc3MgdHdlZXRzCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGVtb3Rpb25zLCBhZXMoeCA9IGVtb3Rpb24sIHkgPSBwZXJjZW50KSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgYWVzKGZpbGwgPSBlbW90aW9uKSkgKyAKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJSZFlsR24iKSArIAogIGNvb3JkX2ZsaXAoKSArCiAgeGxhYigiRW1vdGlvbiIpICsKICB5bGFiKCJQZXJjZW50YWdlIikKCmBgYAoKPGJyPgoKLS0tLS0tLS0tLS0tLS0KCiMjIFJlcG9ydGluZzogQSBXb3JkY2xvdWQgZnJvbSBNYXJjaCBNYWRuZXNzIFR3ZWV0cwoKLS0tLS0tLS0tLS0tLS0KCjxicj4KCiMjIyMgV29yZGNsb3VkcyBhcmUgYWx3YXlzIGEgZnVuIGFuZCBlbmdhZ2luZyB3YXkgdG8gZGlzcGxheSBkYXRhLiBIZXJlIHdlIGFyZSBnb2luZyB0byBzZXQgc29tZSBzdG9wIHdvcmRzIHRoYXQgd2UgZG9udCB3YW50IGluIHRoZSBwbG90LgpgYGB7cn0KcmVtb3ZlX3dvcmRzIDwtIGMoICJ0d2l0dGVyIiwgImNoaWNhZ28iLCAibG95b2xhIiwgInJhbWJsZXJzIiwgImxveW9sYXJhbWJsZXJzIiwic2Nob29sIiwgImdvbm5hIiwKICAgICAgICAgICAgICAgICAgICJ1bml2ZXJzaXR5IiwgImx1YyIsICJsb3lvbGFjaGljYWdvIiAsICJyYW1ibGVyc21iYiIsICJuY2FhIiwidmUiLCJiYXNrZXRiYWxsIiAsCiAgICAgICAgICAgICAgICAgICAidW1pY2hiYmFsbCIsICJtYXJjaG1hZG5lc3MyMDE4IiwgIm1hcmNobWFkbmVzcyIsICJmaW5hbCIsICJtYXJjaG1hZGRuZXNzIiwKICAgICAgICAgICAgICAgICAgICJnb2JsdWUiLCAiZmluYWxmb3VyIiwgInNpc3RlcmplYW4iLCAibmNhYXRvdXJuYW1lbnQiLCAibmNhYXRvdXJuYW1lbnQyMDE4IiwKICAgICAgICAgICAgICAgICAgICJkaWRuIiwiY2l0eSIsICJoZXkiLCAiZGF5IiwgImNvbGxlZ2UiLCAiZ2FtZXMiLCAidG91cm5leSIsICJtYXJjaCIsICJnYW1lIikKCm15X3N0b3Bfd29yZHMgPC0gYmluZF9yb3dzKGRhdGFfZnJhbWUod29yZCA9IHJlbW92ZV93b3JkcywgbGV4aWNvbiA9IGMoIlNNQVJUIikpLCBzdG9wX3dvcmRzKQoKYGBgCgo8YnI+CgojIyMjIE5vdyBsZXRzIGNyZWF0ZSBhIGRhdGFmcmFtZSBvZiB3b3JkcyBhbmQgZmlsdGVyIHVzaW5nIHByZWRlZmluZWQgc3RvcCB3b3JkcyAKYGBge3J9CnR3dF90ZXh0IDwtIHRpYmJsZSh0ZXh0ID0gdHdlZXRzJHRleHQpICU+JSAKICB1bm5lc3RfdG9rZW5zKHdvcmQsIHRleHQpICU+JQogIGZpbHRlcighd29yZCAlaW4lIG15X3N0b3Bfd29yZHMkd29yZCwgc3RyX2RldGVjdCh3b3JkLCAiW2Etel0iKSkKCmBgYAoKPGJyPgoKIyMjIyBTZXQgYSB0aHJlc2hvbGQgZm9yIHRoZSBtaW4vbWF4IGZyZXF1ZW5jeSBvZiB3b3JkcyBhbmQgc2NhbGUgb2YgdGhlIHdvcmRjbG91ZApgYGB7cn0KbWluX2ZyZXEgPSA4MAptYXhfd29yZHMgPSAxMDAKZmlnX3NjYWxlID0gYygzICwgMC41KQpgYGAKCjxicj4KCiMjIyMgVGhlIGxhc3Qgc3RlcCBpcyB0byBjcmVhdGUgdGhlIHdvcmRjbG91ZCBieSBjb3VudGluZyB0aGUgZnJlcXVlbmN5IG9mIHRoZSB3b3JkcwpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KdHd0X3RleHQgJT4lCiAgYW50aV9qb2luKG15X3N0b3Bfd29yZHMpICU+JQogIGNvdW50KHdvcmQpICU+JQogIHdpdGgod29yZGNsb3VkKHdvcmQsIG4sIAogICAgICAgICAgICAgICAgIHNjYWxlID0gZmlnX3NjYWxlLAogICAgICAgICAgICAgICAgIG1pbi5mcmVxID0gbWluX2ZyZXEsCiAgICAgICAgICAgICAgICAgbWF4LndvcmRzID0gbWF4X3dvcmRzKSkKCmBgYAo=