TFIDF
a <- c('a')
abb <- c('a', 'b', 'b')
abc <- c('a', 'b', 'c')
D <- list(a, abb, abc)
#tfidf('a', a, D)
tf <- 1/1
idf <- log(3/3)
tf
[1] 1
idf
[1] 0
tf * idf
[1] 0
#tfidf('a', abb, D)
tf <- 1/3
idf <- log(3/3)
tf * idf
[1] 0
#tfidf('b', abb, D)
tf <- 2/3
idf <- log(3/2)
tf * idf
[1] 0.2703101
#tfidf('b', abc, D)
tf <- 1/3
idf <- log(3/2)
tf * idf
[1] 0.135155
#tfidf('c', abc, D)
tf <- 1/3
idf <- log(3/1)
tf * idf
[1] 0.3662041
a <- c('a')
abb <- c('a', 'b', 'b')
abc <- c('a', 'b', 'c')
D <- list(a, abb, abc)
#tfidf('c', abc, D)
tf <- sum(abc == 'c') /length(abc)
length(D)
[1] 3
#'c' %in% abc
idf <- log(length(D) / sum(sapply(D, function(e) 'c' %in% e )))
tfidf <- function(t, d, D){
tf <- sum(d == t) /length(d)
idf <- log(length(D) / sum(sapply(D, function(e) t %in% e )))
tf * idf
}
tfidf('c', abc, D)
[1] 0.3662041
jiebaR
#install.packages('jiebaR')
library(jiebaR)
s <- '大巨蛋案對市府同仁下封口令?柯P否認'
mixseg <- worker()
segment(code = s, jiebar = mixseg)
edit_dict()
library(tm)
e3 <- 'Hello, I am David, I have taken over 100 courses~~~'
e3.list <- strsplit(e3, ' ')
e3.corpus <- Corpus(VectorSource(e3.list))
e3.dtm <- DocumentTermMatrix(e3.corpus)
inspect(e3.dtm)
e3.dtm <- DocumentTermMatrix(e3.corpus, control = list(wordLengths = c(1,20)))
inspect(e3.dtm)
getTransformations()
doc <- tm_map(e3.corpus, removeNumbers)
doc <- tm_map(doc, removePunctuation)
doc <- tm_map(doc, stemDocument)
dtm <- DocumentTermMatrix(doc)
inspect(dtm)
removetilde <- content_transformer(
function(e) gsub('~', '', e))
doc <- tm_map(e3.corpus, removetilde)
dtm <- DocumentTermMatrix(doc)
inspect(dtm)
e1 <- 'this is a book'
e2 <- 'this is my car'
e.list <- strsplit(c(e1, e2), ' ')
e.corpus <- Corpus(VectorSource(e.list))
e.dtm <- DocumentTermMatrix(e.corpus, control = list(weighting = function(x)
weightTfIdf(x, normalize = FALSE)))
?DocumentTermMatrix
inspect(e.dtm)
Chinese DocumentTermMatrix
sapply(s.vec, function(t) {
if (t %in% names(synonym_dict)){
synonym_dict[t]
} else{
t
}
})
$`憭批楊<e8><9b>
[1] "憭批楊<e8><9b><8b>"
$獢<b0><8d>
[1] "獢<b0><8d>"
$撣<ba><9c>
[1] "撣<ba><9c>"
$<e5><90><bb><81>
[1] "<e5><90><bb><81>"
$銝<8b>
[1] "銝<8b>"
$撠隞<a4>
[1] "撠隞<a4>"
$<e6>P.<e6>P
[1] "<e6><e6><96>"
$<e5>隤<8d>
[1] "<e5>隤<8d>"
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
input string 1 is invalid in this locale
The application of documentTermMatrix
download.file('https://github.com/ywchiu/rtibame/raw/master/data/applenews20160925.RData', 'applenews.RData')
load('applenews.RData')
library(jiebaR)
source('https://raw.githubusercontent.com/ywchiu/rtibame/master/Lib/CNCorpus.R')
mixseg <- worker()
apple.seg <- lapply(applenews$article, function(e) segment(e, jiebar = mixseg))
s.corpus <- CNCorpus(apple.seg)
doc <- tm_map(s.corpus, removeNumbers)
'jayson'[grepl('[\u4e00-\u9fa5]+', 'jayson')]
removeen <- content_transformer(
function(x, pattern){
print(x[grepl('[\u4e00-\u9fa5]+',x)])
return(x[grepl('[\u4e00-\u9fa5]+',x)])
}
)
removeen2 <- function(x, pattern){
return(x[grepl('[\u4e00-\u9fa5]+',x)])
}
doc <- tm_map(s.corpus, removeen2)
#doc <- tm_map(doc, removeNumbers)
doc
s.dtm <- DocumentTermMatrix(doc, control = list(wordLengths = c(2,Inf), tokenizer = space_tokenizer))
s.dtm
dim(s.dtm)
#s.dtm$dimnames$Terms[nchar(s.dtm$dimnames$Terms) == 21]
s.dtm$dimnames$Terms
findAssocs(s.dtm, '颱風', 0.5)
Clustering
dist(rbind(x,y), method = 'euclidean')
x
y 1.414214
iris clustering

Cosine distance
1- proxy::dist(rbind(a,b), method= "cosine")
a
b 0.9381942
News Clustering
# Load Data
download.file('https://raw.githubusercontent.com/ywchiu/rtibame/master/data/applenews.RData', destfile = 'appledaily.RData')
load('appledaily.RData')
head(applenews)
# Segmentation
library(jiebaR)
mixseg <- worker()
apple.seg <- lapply(applenews$content, function(article) segment(code= article, jiebar = mixseg))
class(apple.seg)
# Convert segments into corpus
source('https://raw.githubusercontent.com/ywchiu/rtibame/master/Lib/CNCorpus.R')
s.corpus <- CNCorpus(apple.seg)
s.corpus <- tm_map(s.corpus, removeNumbers)
s.corpus <- tm_map(s.corpus, removePunctuation)
# Build Document Term Matrix
control.list <- list(wordLengths = c(2, Inf), tokenize = space_tokenizer)
s.dtm <- DocumentTermMatrix(s.corpus, control = control.list)
dim(s.dtm)
dtm <- removeSparseTerms(s.dtm, 0.99)
dim(dtm)
#s.dtm
dtm.dist <- proxy::dist(as.matrix(dtm), method = 'cosine')
dtm.mat <- as.matrix(dtm.dist)
queryArticle <- function(query_idx){
#query_idx <- 9
print(paste('查詢文章:', applenews$title[query_idx]))
query_idx_score <- dtm.mat[query_idx,]
print(paste('相關文章:', applenews$title[order(query_idx_score)[2:11]]))
}
queryArticle(70)
applenews$content[70]
hc <- hclust(dtm.dist, 'ward.D2')
plot(hc, hang = -0.01)
rect.hclust(hc,13)
fit <- cutree(hc, 13 )
applenews$title[fit == 5]
LS0tDQp0aXRsZTogIkRlbW8yMDE3MDEyNCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIFRGSURGDQpgYGB7cn0NCmEgPC0gYygnYScpDQphYmIgPC0gYygnYScsICdiJywgJ2InKQ0KYWJjIDwtIGMoJ2EnLCAnYicsICdjJykNCkQgPC0gbGlzdChhLCBhYmIsIGFiYykNCg0KDQojdGZpZGYoJ2EnLCBhLCBEKSANCnRmICA8LSAxLzENCmlkZiA8LSBsb2coMy8zKQ0KdGYNCmlkZg0KdGYgKiBpZGYNCg0KI3RmaWRmKCdhJywgYWJiLCBEKQ0KdGYgIDwtIDEvMw0KaWRmIDwtIGxvZygzLzMpDQp0ZiAqIGlkZg0KDQojdGZpZGYoJ2InLCBhYmIsIEQpDQp0ZiAgPC0gMi8zDQppZGYgPC0gbG9nKDMvMikNCnRmICogaWRmIA0KDQojdGZpZGYoJ2InLCBhYmMsIEQpDQp0ZiAgPC0gMS8zDQppZGYgPC0gbG9nKDMvMikNCnRmICogaWRmIA0KDQojdGZpZGYoJ2MnLCBhYmMsIEQpDQp0ZiAgPC0gMS8zDQppZGYgPC0gbG9nKDMvMSkNCnRmICogaWRmDQogIA0KYSA8LSBjKCdhJykNCmFiYiA8LSBjKCdhJywgJ2InLCAnYicpDQphYmMgPC0gYygnYScsICdiJywgJ2MnKQ0KRCA8LSBsaXN0KGEsIGFiYiwgYWJjKQ0KDQojdGZpZGYoJ2MnLCBhYmMsIEQpDQp0ZiA8LSBzdW0oYWJjID09ICdjJykgL2xlbmd0aChhYmMpDQpsZW5ndGgoRCkgDQojJ2MnICVpbiUgYWJjIA0KaWRmIDwtIGxvZyhsZW5ndGgoRCkgLyBzdW0oc2FwcGx5KEQsIGZ1bmN0aW9uKGUpICdjJyAlaW4lIGUgICkpKQ0KDQoNCnRmaWRmIDwtIGZ1bmN0aW9uKHQsIGQsIEQpew0KICB0ZiA8LSBzdW0oZCA9PSB0KSAvbGVuZ3RoKGQpDQogIGlkZiA8LSBsb2cobGVuZ3RoKEQpIC8gc3VtKHNhcHBseShELCBmdW5jdGlvbihlKSB0ICVpbiUgZSAgKSkpDQogIHRmICogaWRmDQp9DQoNCnRmaWRmKCdjJywgYWJjLCBEKQ0KDQpgYGANCiMjIGppZWJhUg0KYGBgDQojaW5zdGFsbC5wYWNrYWdlcygnamllYmFSJykNCmxpYnJhcnkoamllYmFSKQ0KcyA8LSAn5aSn5beo6JuL5qGI5bCN5biC5bqc5ZCM5LuB5LiL5bCB5Y+j5LukP+afr1DlkKboqo0nDQptaXhzZWcgPC0gd29ya2VyKCkNCg0Kc2VnbWVudChjb2RlID0gcywgamllYmFyID0gbWl4c2VnKQ0KZWRpdF9kaWN0KCkNCg0KDQpsaWJyYXJ5KHRtKQ0KDQoNCmUzIDwtICdIZWxsbywgSSBhbSBEYXZpZCwgSSBoYXZlIHRha2VuIG92ZXIgMTAwIGNvdXJzZXN+fn4nDQplMy5saXN0IDwtIHN0cnNwbGl0KGUzLCAnICcpDQplMy5jb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZShlMy5saXN0KSkNCmUzLmR0bSA8LSBEb2N1bWVudFRlcm1NYXRyaXgoZTMuY29ycHVzKQ0KaW5zcGVjdChlMy5kdG0pDQoNCg0KZTMuZHRtIDwtIERvY3VtZW50VGVybU1hdHJpeChlMy5jb3JwdXMsIGNvbnRyb2wgPSBsaXN0KHdvcmRMZW5ndGhzID0gYygxLDIwKSkpDQppbnNwZWN0KGUzLmR0bSkNCg0KDQpnZXRUcmFuc2Zvcm1hdGlvbnMoKQ0KZG9jIDwtIHRtX21hcChlMy5jb3JwdXMsIHJlbW92ZU51bWJlcnMpDQpkb2MgPC0gdG1fbWFwKGRvYywgcmVtb3ZlUHVuY3R1YXRpb24pDQpkb2MgPC0gdG1fbWFwKGRvYywgc3RlbURvY3VtZW50KQ0KZHRtIDwtIERvY3VtZW50VGVybU1hdHJpeChkb2MpDQppbnNwZWN0KGR0bSkNCg0KcmVtb3ZldGlsZGUgPC0gY29udGVudF90cmFuc2Zvcm1lcigNCiAgICAgZnVuY3Rpb24oZSkgZ3N1YignficsICcnLCBlKSkNCg0KZG9jIDwtIHRtX21hcChlMy5jb3JwdXMsIHJlbW92ZXRpbGRlKQ0KZHRtIDwtIERvY3VtZW50VGVybU1hdHJpeChkb2MpDQppbnNwZWN0KGR0bSkNCg0KDQplMSA8LSAndGhpcyBpcyBhIGJvb2snDQplMiA8LSAndGhpcyBpcyBteSBjYXInDQplLmxpc3QgPC0gc3Ryc3BsaXQoYyhlMSwgZTIpLCAnICcpDQplLmNvcnB1cyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKGUubGlzdCkpDQplLmR0bSA8LSBEb2N1bWVudFRlcm1NYXRyaXgoZS5jb3JwdXMsIGNvbnRyb2wgPSBsaXN0KHdlaWdodGluZyA9IGZ1bmN0aW9uKHgpDQogICAgICAgICAgd2VpZ2h0VGZJZGYoeCwgbm9ybWFsaXplID0gRkFMU0UpKSkNCj9Eb2N1bWVudFRlcm1NYXRyaXgNCmluc3BlY3QoZS5kdG0pDQpgYGANCg0KIyMgQ2hpbmVzZSBEb2N1bWVudFRlcm1NYXRyaXgNCmBgYHtyfQ0KbGlicmFyeShqaWViYVIpDQpsaWJyYXJ5KHRtKQ0KDQpzIDwtICflpKflt6jom4vmoYjlsI3luILlupzlkIzku4HkuIvlsIHlj6Pku6Q/5p+vUOWQpuiqjScNCnMxIDwtICfmn69Q5biC5bqc6L+R5L6G6aO95Y+X5aSn5beo6JuL54it6K2wJw0KbWl4c2VnIDwtIHdvcmtlcigpDQpzLnZlYyA8LSBzZWdtZW50KGNvZGU9IHMsIGppZWJhciA9IG1peHNlZykNCg0KczEudmVjIDwtIHNlZ21lbnQoY29kZT0gczEsIGppZWJhciA9IG1peHNlZykNCg0Kcy5jb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZShsaXN0KHMudmVjLHMxLnZlYykpKQ0Kcy5kdG0gPC0gRG9jdW1lbnRUZXJtTWF0cml4KHMuY29ycHVzKQ0KaW5zcGVjdChzLmR0bSkNCg0KDQoNCnNvdXJjZSgnaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3l3Y2hpdS9ydGliYW1lL21hc3Rlci9MaWIvQ05Db3JwdXMuUicpDQoNCnMuY29ycHVzIDwtIENOQ29ycHVzKGxpc3Qocy52ZWMsczEudmVjKSkNCg0Kcy5kdG0gPC0gRG9jdW1lbnRUZXJtTWF0cml4KHMuY29ycHVzLCBjb250cm9sID0gbGlzdCh3b3JkTGVuZ3RocyA9IGMoMSxJbmYpLCB0b2tlbml6ZXIgPSBzcGFjZV90b2tlbml6ZXIpKQ0KaW5zcGVjdChzLmR0bSkNCg0KDQpzLnZlYw0KP3N5bm9ueW1fZGljdA0KJ+afr1AnICVpbiUgbmFtZXMoc3lub255bV9kaWN0KQ0KDQoNCnN5bm9ueW1fZGljdCA8LSBsaXN0KCfmn69QJyA9ICfmn6/mloflk7InKQ0Kc2FwcGx5KHMudmVjLCBmdW5jdGlvbih0KSB7IA0KICAgIGlmICh0ICVpbiUgbmFtZXMoc3lub255bV9kaWN0KSl7DQogICAgICAgc3lub255bV9kaWN0W3RdDQogICAgfSBlbHNlew0KICAgICAgdA0KICAgIH0NCiAgfSkNCmBgYA0KDQojIyBUaGUgYXBwbGljYXRpb24gb2YgZG9jdW1lbnRUZXJtTWF0cml4DQpgYGANCmRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vZ2l0aHViLmNvbS95d2NoaXUvcnRpYmFtZS9yYXcvbWFzdGVyL2RhdGEvYXBwbGVuZXdzMjAxNjA5MjUuUkRhdGEnLCAnYXBwbGVuZXdzLlJEYXRhJykNCmxvYWQoJ2FwcGxlbmV3cy5SRGF0YScpDQoNCmxpYnJhcnkoamllYmFSKQ0Kc291cmNlKCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20veXdjaGl1L3J0aWJhbWUvbWFzdGVyL0xpYi9DTkNvcnB1cy5SJykNCg0KbWl4c2VnIDwtIHdvcmtlcigpDQphcHBsZS5zZWcgPC0gbGFwcGx5KGFwcGxlbmV3cyRhcnRpY2xlLCBmdW5jdGlvbihlKSBzZWdtZW50KGUsIGppZWJhciA9IG1peHNlZykpDQoNCnMuY29ycHVzIDwtIENOQ29ycHVzKGFwcGxlLnNlZykNCg0KZG9jIDwtIHRtX21hcChzLmNvcnB1cywgcmVtb3ZlTnVtYmVycykNCg0KJ2pheXNvbidbZ3JlcGwoJ1tcdTRlMDAtXHU5ZmE1XSsnLCAnamF5c29uJyldDQpyZW1vdmVlbiA8LSBjb250ZW50X3RyYW5zZm9ybWVyKA0KICBmdW5jdGlvbih4LCBwYXR0ZXJuKXsNCiAgICBwcmludCh4W2dyZXBsKCdbXHU0ZTAwLVx1OWZhNV0rJyx4KV0pDQogICAgcmV0dXJuKHhbZ3JlcGwoJ1tcdTRlMDAtXHU5ZmE1XSsnLHgpXSkNCiAgfQ0KKQ0KDQpyZW1vdmVlbjIgPC0gZnVuY3Rpb24oeCwgcGF0dGVybil7DQogICAgcmV0dXJuKHhbZ3JlcGwoJ1tcdTRlMDAtXHU5ZmE1XSsnLHgpXSkNCiAgfQ0KDQoNCmRvYyA8LSB0bV9tYXAocy5jb3JwdXMsIHJlbW92ZWVuMikNCiNkb2MgPC0gdG1fbWFwKGRvYywgcmVtb3ZlTnVtYmVycykNCg0KZG9jDQpzLmR0bSA8LSBEb2N1bWVudFRlcm1NYXRyaXgoZG9jLCBjb250cm9sID0gbGlzdCh3b3JkTGVuZ3RocyA9IGMoMixJbmYpLCB0b2tlbml6ZXIgPSBzcGFjZV90b2tlbml6ZXIpKQ0Kcy5kdG0NCmRpbShzLmR0bSkNCiNzLmR0bSRkaW1uYW1lcyRUZXJtc1tuY2hhcihzLmR0bSRkaW1uYW1lcyRUZXJtcykgPT0gMjFdDQoNCnMuZHRtJGRpbW5hbWVzJFRlcm1zDQpmaW5kQXNzb2NzKHMuZHRtLCAn6aKx6aKoJywgMC41KQ0KYGBgDQojIyBDbHVzdGVyaW5nDQpgYGB7cn0NCnggPC0gYygwLDAsMSwxLDEsMSkNCnkgPC0gYygxLDAsMSwxLDAsMSkNCnNxcnQoIHN1bSgoeCAtIHkgKSBeMikpDQpkaXN0KHJiaW5kKHgseSksIG1ldGhvZCA9ICdldWNsaWRlYW4nKQ0KDQpgYGANCg0KDQojIyBpcmlzIGNsdXN0ZXJpbmcNCmBgYHtyfQ0KZGF0YShpcmlzKQ0KI2lyaXMNCg0KaXJpc19kYXRhIDwtIGlyaXNbLCAtNV0NCmhjIDwtIGhjbHVzdChkaXN0KGlyaXNfZGF0YSwgJ2V1Y2xpZGVhbicpLCAnd2FyZC5EMicgKQ0KcGxvdChoYykNCg0KDQpmaXQgPC0gY3V0cmVlKGhjLCAzKQ0KZml0DQoNCnBsb3QoaGMpDQpyZWN0LmhjbHVzdChoYywgMykNCg0KDQpwYXIobWZyb3cgPSBjKDEsMikpDQpwbG90KFBldGFsLkxlbmd0aCB+IFBldGFsLldpZHRoLCBkYXRhID0gaXJpcywgY29sPWlyaXMkU3BlY2llcywgbWFpbiA9ICJ3aXRoIHNwZWNpZXMgaW5mb3JtYXRpb24iKQ0KDQpwbG90KFBldGFsLkxlbmd0aCB+IFBldGFsLldpZHRoLCBkYXRhID0gaXJpcywgY29sPWZpdCwgbWFpbiA9ICJjbHVzdGVyaW5nIikNCg0KDQpgYGANCg0KDQoNCiMjIENvc2luZSBkaXN0YW5jZQ0KYGBge3J9DQphIDwtIGMoMSwyLDIsMSwxLDEsMCkNCmIgPC0gYygxLDIsMiwxLDEsMiwxKQ0KDQpzdW0oYSAqIGIpIC8gKHNxcnQoc3VtKGEgXiAyKSkgKnNxcnQoc3VtKGIgXiAyKSkpDQoNCjEgLSBwcm94eTo6ZGlzdChyYmluZChhLGIpLCBtZXRob2Q9ICJjb3NpbmUiKQ0KDQoNCmBgYA0KIyMgTmV3cyBDbHVzdGVyaW5nDQoNCmBgYA0KIyBMb2FkIERhdGENCmRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS95d2NoaXUvcnRpYmFtZS9tYXN0ZXIvZGF0YS9hcHBsZW5ld3MuUkRhdGEnLCBkZXN0ZmlsZSA9ICdhcHBsZWRhaWx5LlJEYXRhJykNCmxvYWQoJ2FwcGxlZGFpbHkuUkRhdGEnKQ0KaGVhZChhcHBsZW5ld3MpDQoNCiMgU2VnbWVudGF0aW9uDQpsaWJyYXJ5KGppZWJhUikNCm1peHNlZyA8LSB3b3JrZXIoKQ0KYXBwbGUuc2VnIDwtIGxhcHBseShhcHBsZW5ld3MkY29udGVudCwgZnVuY3Rpb24oYXJ0aWNsZSkgc2VnbWVudChjb2RlPSBhcnRpY2xlLCBqaWViYXIgPSBtaXhzZWcpKQ0KY2xhc3MoYXBwbGUuc2VnKQ0KDQojIENvbnZlcnQgc2VnbWVudHMgaW50byBjb3JwdXMNCnNvdXJjZSgnaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3l3Y2hpdS9ydGliYW1lL21hc3Rlci9MaWIvQ05Db3JwdXMuUicpDQpzLmNvcnB1cyA8LSBDTkNvcnB1cyhhcHBsZS5zZWcpDQpzLmNvcnB1cyA8LSB0bV9tYXAocy5jb3JwdXMsIHJlbW92ZU51bWJlcnMpDQpzLmNvcnB1cyA8LSB0bV9tYXAocy5jb3JwdXMsIHJlbW92ZVB1bmN0dWF0aW9uKQ0KDQojIEJ1aWxkIERvY3VtZW50IFRlcm0gTWF0cml4DQpjb250cm9sLmxpc3QgPC0gbGlzdCh3b3JkTGVuZ3RocyA9IGMoMiwgSW5mKSwgdG9rZW5pemUgPSBzcGFjZV90b2tlbml6ZXIpDQpzLmR0bSA8LSBEb2N1bWVudFRlcm1NYXRyaXgocy5jb3JwdXMsIGNvbnRyb2wgPSBjb250cm9sLmxpc3QpDQpkaW0ocy5kdG0pDQoNCmR0bSA8LSByZW1vdmVTcGFyc2VUZXJtcyhzLmR0bSwgMC45OSkNCmRpbShkdG0pDQojcy5kdG0NCmR0bS5kaXN0IDwtIHByb3h5OjpkaXN0KGFzLm1hdHJpeChkdG0pLCBtZXRob2QgPSAnY29zaW5lJykNCg0KZHRtLm1hdCA8LSBhcy5tYXRyaXgoZHRtLmRpc3QpDQoNCnF1ZXJ5QXJ0aWNsZSA8LSBmdW5jdGlvbihxdWVyeV9pZHgpew0KI3F1ZXJ5X2lkeCA8LSA5DQpwcmludChwYXN0ZSgn5p+l6Kmi5paH56ugOicsIGFwcGxlbmV3cyR0aXRsZVtxdWVyeV9pZHhdKSkNCnF1ZXJ5X2lkeF9zY29yZSA8LSBkdG0ubWF0W3F1ZXJ5X2lkeCxdDQpwcmludChwYXN0ZSgn55u46Zec5paH56ugOicsIGFwcGxlbmV3cyR0aXRsZVtvcmRlcihxdWVyeV9pZHhfc2NvcmUpWzI6MTFdXSkpDQp9DQoNCnF1ZXJ5QXJ0aWNsZSg3MCkNCmFwcGxlbmV3cyRjb250ZW50WzcwXQ0KDQoNCg0KaGMgPC0gaGNsdXN0KGR0bS5kaXN0LCAnd2FyZC5EMicpDQpwbG90KGhjLCBoYW5nID0gLTAuMDEpDQpyZWN0LmhjbHVzdChoYywxMykNCmZpdCA8LSBjdXRyZWUoaGMsIDEzICkNCmFwcGxlbmV3cyR0aXRsZVtmaXQgPT0gNV0NCmBgYA0KDQoNCg0KDQoNCg==