作æ¥äº”
download.file('https://github.com/ywchiu/rtibame/raw/master/Data/oneday2.csv', 'oneday.csv')
oneday <- read.csv('oneday.csv', stringsAsFactors = FALSE)
head(oneday)
str(oneday)
library(jiebaR)
mixseg <- worker()
oneday.seg <- segment(oneday$content, mixseg)
tb <- table(oneday.seg)
tb <- tb[(nchar(names(tb)) >= 2) & (tb >= 10) & grepl('[\u4e00-\u9fa5]+', x = names(tb))]
tb
library(wordcloud2)
wordcloud2(tb, shape = "star")
iris classfication
data(iris)
#iris
library(rpart)
fit <- rpart( Species ~ Sepal.Length +Sepal.Width + Petal.Length +Petal.Width, data = iris )
fit
n= 150
node), split, n, loss, yval, (yprob)
* denotes terminal node
1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)
2) Petal.Length< 2.45 50 0 setosa (1.00000000 0.00000000 0.00000000) *
3) Petal.Length>=2.45 100 50 versicolor (0.00000000 0.50000000 0.50000000)
6) Petal.Width< 1.75 54 5 versicolor (0.00000000 0.90740741 0.09259259) *
7) Petal.Width>=1.75 46 1 virginica (0.00000000 0.02173913 0.97826087) *
plot(fit, margin=0.1)
text(fit)

plot(iris$Petal.Length, iris$Petal.Width, col = iris$Species)
abline(v = 2.45, col="orange")
abline(h = 1.75, col="blue")

predict(fit, data.frame(Petal.Length = 2, Petal.Width= 3, Sepal.Length = 2, Sepal.Width = 2))
setosa versicolor virginica
1 1 0 0
#predict(fit, iris)
predicted <- predict(fit, iris, type= 'class')
tb <- table(predicted,iris$Species)
# accuracy
(50 + 49 + 45) /150
[1] 0.96
#install.packages('caret')
#install.packages('e1071')
library(caret)
cm <- confusionMatrix(tb)
cm
Confusion Matrix and Statistics
predicted setosa versicolor virginica
setosa 50 0 0
versicolor 0 49 5
virginica 0 1 45
Overall Statistics
Accuracy : 0.96
95% CI : (0.915, 0.9852)
No Information Rate : 0.3333
P-Value [Acc > NIR] : < 2.2e-16
Kappa : 0.94
Mcnemar's Test P-Value : NA
Statistics by Class:
Class: setosa Class: versicolor
Sensitivity 1.0000 0.9800
Specificity 1.0000 0.9500
Pos Pred Value 1.0000 0.9074
Neg Pred Value 1.0000 0.9896
Prevalence 0.3333 0.3333
Detection Rate 0.3333 0.3267
Detection Prevalence 0.3333 0.3600
Balanced Accuracy 1.0000 0.9650
Class: virginica
Sensitivity 0.9000
Specificity 0.9900
Pos Pred Value 0.9783
Neg Pred Value 0.9519
Prevalence 0.3333
Detection Rate 0.3000
Detection Prevalence 0.3067
Balanced Accuracy 0.9450
# data sampling
set.seed(123)
sample.int(42, 6)
[1] 13 33 17 35 36 2
sample.int(42, 6)
[1] 23 37 42 18 41 17
sample.int(42, 6)
[1] 29 24 5 36 10 2
a <- c(1,2,3,4,5)
ix <- c(1,0,1,0,1)
a[ix == 1]
[1] 1 3 5
# split data into trainset and testset
nrow(iris)
[1] 150
set.seed(123)
idx <- sample.int(2, nrow(iris), replace = TRUE, prob=c(0.7,0.3))
trainset <- iris[idx == 1, ]
testset <- iris[idx == 2, ]
# build model
dim(trainset)
[1] 106 5
dim(testset)
[1] 44 5
fit <- rpart(Species ~ ., data = trainset)
fit
n= 106
node), split, n, loss, yval, (yprob)
* denotes terminal node
1) root 106 70 versicolor (0.33018868 0.33962264 0.33018868)
2) Petal.Length< 2.45 35 0 setosa (1.00000000 0.00000000 0.00000000) *
3) Petal.Length>=2.45 71 35 versicolor (0.00000000 0.50704225 0.49295775)
6) Petal.Length< 4.75 34 0 versicolor (0.00000000 1.00000000 0.00000000) *
7) Petal.Length>=4.75 37 2 virginica (0.00000000 0.05405405 0.94594595) *
plot(fit, margin = 0.1)
text(fit)

# apply model on testset
predicted <- predict(fit, testset, type="class")
tb <- table(testset$Species, predicted)
cm <- confusionMatrix(tb)
cm
Confusion Matrix and Statistics
predicted
setosa versicolor virginica
setosa 15 0 0
versicolor 0 10 4
virginica 0 1 14
Overall Statistics
Accuracy : 0.8864
95% CI : (0.7544, 0.9621)
No Information Rate : 0.4091
P-Value [Acc > NIR] : 6.207e-11
Kappa : 0.8291
Mcnemar's Test P-Value : NA
Statistics by Class:
Class: setosa Class: versicolor
Sensitivity 1.0000 0.9091
Specificity 1.0000 0.8788
Pos Pred Value 1.0000 0.7143
Neg Pred Value 1.0000 0.9667
Prevalence 0.3409 0.2500
Detection Rate 0.3409 0.2273
Detection Prevalence 0.3409 0.3182
Balanced Accuracy 1.0000 0.8939
Class: virginica
Sensitivity 0.7778
Specificity 0.9615
Pos Pred Value 0.9333
Neg Pred Value 0.8621
Prevalence 0.4091
Detection Rate 0.3182
Detection Prevalence 0.3409
Balanced Accuracy 0.8697
# apply model on trainset
predicted2 <- predict(fit, trainset, type="class")
tb2 <- table(trainset$Species, predicted2)
cm2 <- confusionMatrix(tb2)
cm2
Confusion Matrix and Statistics
predicted2
setosa versicolor virginica
setosa 35 0 0
versicolor 0 34 2
virginica 0 0 35
Overall Statistics
Accuracy : 0.9811
95% CI : (0.9335, 0.9977)
No Information Rate : 0.3491
P-Value [Acc > NIR] : < 2.2e-16
Kappa : 0.9717
Mcnemar's Test P-Value : NA
Statistics by Class:
Class: setosa Class: versicolor
Sensitivity 1.0000 1.0000
Specificity 1.0000 0.9722
Pos Pred Value 1.0000 0.9444
Neg Pred Value 1.0000 1.0000
Prevalence 0.3302 0.3208
Detection Rate 0.3302 0.3208
Detection Prevalence 0.3302 0.3396
Balanced Accuracy 1.0000 0.9861
Class: virginica
Sensitivity 0.9459
Specificity 1.0000
Pos Pred Value 1.0000
Neg Pred Value 0.9718
Prevalence 0.3491
Detection Rate 0.3302
Detection Prevalence 0.3302
Balanced Accuracy 0.9730
Churn rate analysis
#install.packages('C50')
library(C50)
data(churn)
#churnTrain
churnTrain <- churnTrain[,!names(churnTrain)%in%c("state", "area_code", "account_length")]
set.seed(2)
idx <- sample.int(2,nrow(churnTrain), replace = TRUE, prob = c(0.7, 0.3))
trainset <- churnTrain[idx == 1, ]
testset <- churnTrain[idx == 2, ]
churn.rp <- rpart(churn ~., data = trainset)
plot(churn.rp, margin=0.1)
text(churn.rp)

Verify Classfication Result
mgraph(L,graph="IMP",leg=names(trainset),col="gray",Grid=10)
Error: could not find function "mgraph"
Distance
x <- c(0, 0, 1, 1, 1, 1)
y <- c(1, 0, 1, 1, 0, 1)
# euclidean
sqrt(sum((x - y) ^ 2))
[1] 1.414214
dist(rbind(x,y), method = 'euclidean')
x
y 1.414214
# manhattan
sum(abs(x - y))
[1] 2
dist(rbind(x,y), method = 'manhattan')
x
y 2
Clustering
data(iris)
dist.iris <- dist(iris[,-5], method='euclidean')
hc <- hclust(dist.iris, method = "ward.D2")
plot(hc)

fit <- cutree(hc, k = 3)
fit
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[30] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
[59] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2
[88] 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 3 3 3 3 2 3 3 3 3 3 3 2 2 3
[117] 3 3 3 2 3 2 3 2 3 3 2 2 3 3 3 3 3 2 2 3 3 3 2 3 3 3 2 3 3
[146] 3 2 3 3 2
plot(hc, hang =-0.01, cex=0.7)
rect.hclust(hc, k =3, border="red")
fit <- cutree(hc, k = 3)
fit
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[30] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
[59] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2
[88] 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 3 3 3 3 2 3 3 3 3 3 3 2 2 3
[117] 3 3 3 2 3 2 3 2 3 3 2 2 3 3 3 3 3 2 2 3 3 3 2 3 3 3 2 3 3
[146] 3 2 3 3 2
par(mfrow=c(1,2))

plot(iris$Petal.Length, iris$Petal.Width, col =iris$Species, main = 'with species')
plot(iris$Petal.Length, iris$Petal.Width, col =fit, main= 'clustering result')

Article Clustering
a <- c(1, 2, 2, 1, 1, 1, 0)
b <- c(1, 2, 2, 1, 1, 2, 1)
sum(a * b ) /( sqrt(sum(a^ 2)) * sqrt(sum(b^ 2)))
#install.packages('proxy')
1 - proxy::dist(rbind(a,b), method="cosine")
# Download and load data
download.file('https://raw.githubusercontent.com/ywchiu/rtibame/master/History/Class1/news_big5.RData', 'new.RData')
load('new.RData')
# Data Preprocessing
names(news) <- c('title', 'content', 'articleid')
news$title <- as.character(news$title)
news$content <- as.character(news$content)
library(jiebaR)
mixseg <- worker()
news.seg <- lapply(news$content, function(e)segment(e, mixseg))
source('https://raw.githubusercontent.com/ywchiu/rtibame/master/Lib/CNCorpus.R')
corpus=CNCorpus(news.seg)
control.list=list(wordLengths=c(2,Inf),tokenize=space_tokenizer)
doc <- tm_map(corpus, removeNumbers)
dtm <- DocumentTermMatrix(doc, control<-control.list)
dtm.remove <- removeSparseTerms(dtm, 0.99)
dtm.remove
#dtm$dimnames$Terms
dtm.dist <- proxy::dist(as.matrix(dtm.remove), method ="cosine")
dtm.mat <- as.matrix(dtm.dist)
idx <- order(dtm.mat[127,])[1:10]
cbind(news$title[idx], dtm.mat[127,idx])
# article clustering
dtm.cluster <- hclust(dtm.dist, method = "ward.D2")
plot(dtm.cluster, hang=-1)
fit <- cutree(dtm.cluster, k = 6)
news$title[fit ==5]
LS0tDQp0aXRsZTogIkRlbW8yMDE2MTIxNyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQojI+S9nOalreS6lA0KDQpgYGB7cn0NCmRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vZ2l0aHViLmNvbS95d2NoaXUvcnRpYmFtZS9yYXcvbWFzdGVyL0RhdGEvb25lZGF5Mi5jc3YnLCAnb25lZGF5LmNzdicpIA0Kb25lZGF5IDwtIHJlYWQuY3N2KCdvbmVkYXkuY3N2Jywgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KaGVhZChvbmVkYXkpDQpzdHIob25lZGF5KQ0KDQpsaWJyYXJ5KGppZWJhUikNCm1peHNlZyA8LSB3b3JrZXIoKQ0Kb25lZGF5LnNlZyA8LSBzZWdtZW50KG9uZWRheSRjb250ZW50LCBtaXhzZWcpDQp0YiA8LSB0YWJsZShvbmVkYXkuc2VnKQ0KdGIgPC0gdGJbKG5jaGFyKG5hbWVzKHRiKSkgPj0gMikgJiAodGIgPj0gMTApICYgZ3JlcGwoJ1tcdTRlMDAtXHU5ZmE1XSsnLCB4ID0gbmFtZXModGIpKV0NCnRiDQoNCmxpYnJhcnkod29yZGNsb3VkMikNCndvcmRjbG91ZDIodGIsIHNoYXBlID0gInN0YXIiKQ0KDQpgYGANCg0KDQojIyBpcmlzIGNsYXNzZmljYXRpb24NCmBgYHtyfQ0KZGF0YShpcmlzKQ0KI2lyaXMNCg0KbGlicmFyeShycGFydCkNCmZpdCA8LSBycGFydCggU3BlY2llcyAgfiBTZXBhbC5MZW5ndGggK1NlcGFsLldpZHRoICsgUGV0YWwuTGVuZ3RoICtQZXRhbC5XaWR0aCwgICBkYXRhID0gaXJpcyApDQpmaXQNCnBsb3QoZml0LCBtYXJnaW49MC4xKQ0KdGV4dChmaXQpDQoNCnBsb3QoaXJpcyRQZXRhbC5MZW5ndGgsIGlyaXMkUGV0YWwuV2lkdGgsIGNvbCA9IGlyaXMkU3BlY2llcykNCmFibGluZSh2ID0gMi40NSwgY29sPSJvcmFuZ2UiKQ0KYWJsaW5lKGggPSAxLjc1LCBjb2w9ImJsdWUiKQ0KDQoNCnByZWRpY3QoZml0LCBkYXRhLmZyYW1lKFBldGFsLkxlbmd0aCA9IDIsIFBldGFsLldpZHRoPSAzLCBTZXBhbC5MZW5ndGggPSAyLCBTZXBhbC5XaWR0aCA9IDIpKQ0KDQojcHJlZGljdChmaXQsIGlyaXMpDQpwcmVkaWN0ZWQgPC0gcHJlZGljdChmaXQsIGlyaXMsIHR5cGU9ICdjbGFzcycpDQp0YiA8LSB0YWJsZShwcmVkaWN0ZWQsaXJpcyRTcGVjaWVzKQ0KDQojIGFjY3VyYWN5IA0KKDUwICsgNDkgKyA0NSkgLzE1MA0KDQojaW5zdGFsbC5wYWNrYWdlcygnY2FyZXQnKQ0KI2luc3RhbGwucGFja2FnZXMoJ2UxMDcxJykNCmxpYnJhcnkoY2FyZXQpDQpjbSA8LSBjb25mdXNpb25NYXRyaXgodGIpDQpjbQ0KDQojIGRhdGEgc2FtcGxpbmcNCnNldC5zZWVkKDEyMykNCnNhbXBsZS5pbnQoNDIsIDYpDQpzYW1wbGUuaW50KDQyLCA2KQ0Kc2FtcGxlLmludCg0MiwgNikNCg0KYSAgPC0gYygxLDIsMyw0LDUpDQppeCA8LSBjKDEsMCwxLDAsMSkNCmFbaXggPT0gMV0NCg0KIyBzcGxpdCBkYXRhIGludG8gdHJhaW5zZXQgYW5kIHRlc3RzZXQNCm5yb3coaXJpcykNCnNldC5zZWVkKDEyMykNCmlkeCA8LSBzYW1wbGUuaW50KDIsIG5yb3coaXJpcyksIHJlcGxhY2UgPSBUUlVFLCBwcm9iPWMoMC43LDAuMykpDQp0cmFpbnNldCA8LSBpcmlzW2lkeCA9PSAxLCBdDQp0ZXN0c2V0ICA8LSBpcmlzW2lkeCA9PSAyLCBdDQoNCiMgYnVpbGQgbW9kZWwNCmRpbSh0cmFpbnNldCkNCmRpbSh0ZXN0c2V0KQ0KDQpmaXQgPC0gcnBhcnQoU3BlY2llcyB+IC4sIGRhdGEgPSB0cmFpbnNldCkNCmZpdA0KcGxvdChmaXQsIG1hcmdpbiA9IDAuMSkNCnRleHQoZml0KQ0KDQojIGFwcGx5IG1vZGVsIG9uIHRlc3RzZXQNCnByZWRpY3RlZCA8LSBwcmVkaWN0KGZpdCwgdGVzdHNldCwgdHlwZT0iY2xhc3MiKQ0KdGIgPC0gdGFibGUodGVzdHNldCRTcGVjaWVzLCBwcmVkaWN0ZWQpDQpjbSA8LSBjb25mdXNpb25NYXRyaXgodGIpDQpjbQ0KDQojIGFwcGx5IG1vZGVsIG9uIHRyYWluc2V0DQpwcmVkaWN0ZWQyIDwtIHByZWRpY3QoZml0LCB0cmFpbnNldCwgdHlwZT0iY2xhc3MiKQ0KdGIyIDwtIHRhYmxlKHRyYWluc2V0JFNwZWNpZXMsIHByZWRpY3RlZDIpDQpjbTIgPC0gY29uZnVzaW9uTWF0cml4KHRiMikNCmNtMg0KYGBgDQoNCiMjIENodXJuIHJhdGUgYW5hbHlzaXMNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoJ0M1MCcpDQpsaWJyYXJ5KEM1MCkNCmRhdGEoY2h1cm4pDQoNCiNjaHVyblRyYWluDQoNCmNodXJuVHJhaW4gPC0gY2h1cm5UcmFpblssIW5hbWVzKGNodXJuVHJhaW4pJWluJWMoInN0YXRlIiwgImFyZWFfY29kZSIsICJhY2NvdW50X2xlbmd0aCIpXQ0KDQpzZXQuc2VlZCgyKQ0KaWR4IDwtIHNhbXBsZS5pbnQoMixucm93KGNodXJuVHJhaW4pLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdHJhaW5zZXQgPC0gY2h1cm5UcmFpbltpZHggPT0gMSwgXQ0KdGVzdHNldCAgPC0gY2h1cm5UcmFpbltpZHggPT0gMiwgXQ0KDQpjaHVybi5ycCA8LSBycGFydChjaHVybiB+LiwgZGF0YSA9IHRyYWluc2V0KQ0KcGxvdChjaHVybi5ycCwgbWFyZ2luPTAuMSkNCnRleHQoY2h1cm4ucnApDQoNCg0KYGBgDQojIyBWZXJpZnkgQ2xhc3NmaWNhdGlvbiBSZXN1bHQNCmBgYHtyfQ0KcHJlZGljdGVkIDwtIHByZWRpY3QoY2h1cm4ucnAsIHRlc3RzZXQsIHR5cGUgPSJjbGFzcyIpDQp0YiA8LSB0YWJsZShwcmVkaWN0ZWQsIHRlc3RzZXQkY2h1cm4pDQpkaW0odGVzdHNldCkNCg0KKDg1OSArIDEwMCApLzEwMTgNCmNvbmZ1c2lvbk1hdHJpeCh0YikNCg0KdGFibGUoIHRlc3RzZXQkY2h1cm4pDQo4NzcvMTAxOA0KDQoNCiMgc2VwYXJhdGUgZGF0YSBpbnRvIDEwIGZvbGRzDQppZHggPC0gc2FtcGxlLmludCgxMCwgbnJvdyh0cmFpbnNldCksIHJlcGxhY2UgPVRSVUUpDQpmb3IoaSBpbiBzZXEoMSwxMCkpew0KICB0cmFpbl9kYXRhIDwtIHRyYWluc2V0W2lkeCAhPSBpLCBdDQogIHRlc3RfZGF0YSAgPC0gdHJhaW5zZXRbaWR4ID09IGksIF0NCiAgZml0IDwtIHJwYXJ0KGNodXJuIH4uLCB0cmFpbl9kYXRhKQ0KICBwcmVkaWN0ZWQgPC0gcHJlZGljdChmaXQsIHRlc3RfZGF0YSx0eXBlID0gImNsYXNzIikNCiAgdGIgPC0gdGFibGUocHJlZGljdGVkLCB0ZXN0X2RhdGEkY2h1cm4pDQogIGNtIDwtIGNvbmZ1c2lvbk1hdHJpeCh0YikNCiAgYWNjdXJhY3kgPC0gY20kb3ZlcmFsbFsxXQ0KICBwcmludChhY2N1cmFjeSkNCn0NCg0KIyB1c2UgY2FyZXQgdG8gYnVpbGQgbWFjaGluZSBsZWFybmluZyBtb2RlbA0KbGlicmFyeShjYXJldCkNCmNvbnRyb2wgPC0gdHJhaW5Db250cm9sKG1ldGhvZD0icmVwZWF0ZWRjdiIsIG51bWJlcj0xMCwgcmVwZWF0cz0zKQ0KbW9kZWwgPC0gdHJhaW4oY2h1cm5+LiwgZGF0YT10cmFpbnNldCwgbWV0aG9kPSJycGFydCIsIHByZVByb2Nlc3M9InNjYWxlIiwgdHJDb250cm9sPWNvbnRyb2wpDQptb2RlbA0KDQoNCiMgY3JlYXRlIGEgUk9DIGN1cnZlDQpmaXQgICAgICAgPC0gcnBhcnQoY2h1cm4gfi4sIHRyYWluc2V0KQ0KcHJlZGljdGVkIDwtIHByZWRpY3QoZml0LCB0ZXN0c2V0KQ0KDQpST0MgPC0gZGF0YS5mcmFtZSgpDQpmb3IgKGMgaW4gc2VxKDAsMSwwLjEpKSB7DQogIHByZWRpY3Rpb25zIDwtIGlmZWxzZShwcmVkaWN0ZWRbLDJdID49IGMsIDEsIDApDQogIHByZWRpY3Rpb25zIDwtIGFzLmZhY3RvcihwcmVkaWN0aW9ucykNCiAgbGV2ZWxzKHByZWRpY3Rpb25zKSA8LSBjKCd5ZXMnLCAnbm8nKQ0KICBwcmVkaWN0aW9ucyA8LSBhcy5mYWN0b3IocHJlZGljdGlvbnMpDQogIHRiICAgICAgICA8LSB0YWJsZShwcmVkaWN0aW9ucywgdGVzdHNldCRjaHVybikNCiAgY20gICAgICAgIDwtIGNvbmZ1c2lvbk1hdHJpeCh0YikNCiAgVFBSIDwtIGNtJGJ5Q2xhc3NbMV0NCiAgRlBSIDwtIDEtIGNtJGJ5Q2xhc3NbMl0NCiAgUk9DIDwtIHJiaW5kKFJPQywgZGF0YS5mcmFtZShUUFIsIEZQUikpDQp9DQoNCnBsb3QoVFBSIH4gRlBSLCBkYXRhPVJPQ1syOm5yb3coUk9DKSxdLCB0eXBlPSAnbCcsIGNvbD0icmVkIikNCg0KDQoNCiMgdXNlIFJPQ1INCiNpbnN0YWxsLnBhY2thZ2VzKCJST0NSIikNCmxpYnJhcnkoUk9DUikNCnByZWRpY3Rpb25zIDwtcHJlZGljdChjaHVybi5ycCwgdGVzdHNldCwgdHlwZT0icHJvYiIpDQpwcmVkLnRvLnJvYzwtcHJlZGljdGlvbnNbLCAxXQ0KcHJlZC5yb2NyPC1wcmVkaWN0aW9uKHByZWQudG8ucm9jLCBhcy5mYWN0b3IodGVzdHNldFssKGRpbSh0ZXN0c2V0KVtbMl1dKV0pKQ0KDQpwZXJmLnJvY3I8LXBlcmZvcm1hbmNlKHByZWQucm9jciwgbWVhc3VyZSA9ImF1YyIsIHgubWVhc3VyZT0iY3V0b2ZmIikNCnBlcmYudHByLnJvY3I8LXBlcmZvcm1hbmNlKHByZWQucm9jciwgInRwciIsImZwciIpDQoNCnBsb3QocGVyZi50cHIucm9jcixjb2xvcml6ZT1ULG1haW49cGFzdGUoIkFVQzoiLChwZXJmLnJvY3JAeS52YWx1ZXMpKSkNCg0KDQoNCiNpbnN0YWxsLnBhY2thZ2VzKCJybWluZXIiKQ0KI2luc3RhbGwucGFja2FnZXMoInhnYm9vc3QiKQ0KI2xpYnJhcnkocm1pbmVyKQ0KI21vZGVsIDwtIGZpdChjaHVybn4uLHRyYWluc2V0LG1vZGVsPSJycGFydCIpDQojVmFyaWFibGVJbXBvcnRhbmNlIDwtIEltcG9ydGFuY2UobW9kZWwsdHJhaW5zZXQsbWV0aG9kPSJzZW5zdiIpDQojTD1saXN0KHJ1bnM9MSxzZW49dChWYXJpYWJsZUltcG9ydGFuY2UkaW1wKSxzcmVzcG9uc2VzPVZhcmlhYmxlSW1wb3J0YW5jZSRzcmVzcG9uc2VzKQ0KI21ncmFwaChMLGdyYXBoPSJJTVAiLGxlZz1uYW1lcyh0cmFpbnNldCksY29sPSJncmF5IixHcmlkPTEwKQ0KYGBgDQojIyBEaXN0YW5jZQ0KYGBge3J9DQp4IDwtIGMoMCwgMCwgMSwgMSwgMSwgMSkNCnkgPC0gYygxLCAwLCAxLCAxLCAwLCAxKQ0KIyBldWNsaWRlYW4NCnNxcnQoc3VtKCh4IC0geSkgXiAyKSkNCmRpc3QocmJpbmQoeCx5KSwgbWV0aG9kID0gJ2V1Y2xpZGVhbicpDQoNCiMgbWFuaGF0dGFuDQpzdW0oYWJzKHggLSB5KSkNCmRpc3QocmJpbmQoeCx5KSwgbWV0aG9kID0gJ21hbmhhdHRhbicpDQoNCg0KYGBgDQoNCiNDbHVzdGVyaW5nDQoNCmBgYHtyfQ0KZGF0YShpcmlzKQ0KZGlzdC5pcmlzIDwtIGRpc3QoaXJpc1ssLTVdLCBtZXRob2Q9J2V1Y2xpZGVhbicpDQpoYyA8LSBoY2x1c3QoZGlzdC5pcmlzLCBtZXRob2QgPSAid2FyZC5EMiIpDQpwbG90KGhjKQ0KDQpmaXQgPC0gY3V0cmVlKGhjLCBrID0gMykNCmZpdA0KDQpwbG90KGhjLCBoYW5nID0tMC4wMSwgY2V4PTAuNykNCnJlY3QuaGNsdXN0KGhjLCBrID0zLCBib3JkZXI9InJlZCIpDQoNCg0KZml0IDwtIGN1dHJlZShoYywgayA9IDMpDQpmaXQNCg0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QoaXJpcyRQZXRhbC5MZW5ndGgsIGlyaXMkUGV0YWwuV2lkdGgsIGNvbCA9aXJpcyRTcGVjaWVzLCBtYWluID0gJ3dpdGggc3BlY2llcycpDQpwbG90KGlyaXMkUGV0YWwuTGVuZ3RoLCBpcmlzJFBldGFsLldpZHRoLCBjb2wgPWZpdCwgbWFpbj0gJ2NsdXN0ZXJpbmcgcmVzdWx0JykNCg0KDQpgYGANCiMjIEFydGljbGUgQ2x1c3RlcmluZw0KYGBgDQphIDwtIGMoMSwgMiwgMiwgMSwgMSwgMSwgMCkNCmIgPC0gYygxLCAyLCAyLCAxLCAxLCAyLCAxKQ0KDQpzdW0oYSAqIGIgKSAvKCBzcXJ0KHN1bShhXiAyKSkgKiAgc3FydChzdW0oYl4gMikpKQ0KI2luc3RhbGwucGFja2FnZXMoJ3Byb3h5JykNCjEgLSBwcm94eTo6ZGlzdChyYmluZChhLGIpLCBtZXRob2Q9ImNvc2luZSIpDQoNCiMgRG93bmxvYWQgYW5kIGxvYWQgZGF0YQ0KZG93bmxvYWQuZmlsZSgnaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3l3Y2hpdS9ydGliYW1lL21hc3Rlci9IaXN0b3J5L0NsYXNzMS9uZXdzX2JpZzUuUkRhdGEnLCAnbmV3LlJEYXRhJykNCmxvYWQoJ25ldy5SRGF0YScpDQoNCiMgRGF0YSBQcmVwcm9jZXNzaW5nDQpuYW1lcyhuZXdzKSAgPC0gYygndGl0bGUnLCAnY29udGVudCcsICdhcnRpY2xlaWQnKQ0KbmV3cyR0aXRsZSAgIDwtIGFzLmNoYXJhY3RlcihuZXdzJHRpdGxlKQ0KbmV3cyRjb250ZW50IDwtIGFzLmNoYXJhY3RlcihuZXdzJGNvbnRlbnQpDQoNCmxpYnJhcnkoamllYmFSKQ0KbWl4c2VnIDwtIHdvcmtlcigpDQpuZXdzLnNlZyA8LSBsYXBwbHkobmV3cyRjb250ZW50LCBmdW5jdGlvbihlKXNlZ21lbnQoZSwgbWl4c2VnKSkNCnNvdXJjZSgnaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3l3Y2hpdS9ydGliYW1lL21hc3Rlci9MaWIvQ05Db3JwdXMuUicpDQoNCmNvcnB1cz1DTkNvcnB1cyhuZXdzLnNlZykNCmNvbnRyb2wubGlzdD1saXN0KHdvcmRMZW5ndGhzPWMoMixJbmYpLHRva2VuaXplPXNwYWNlX3Rva2VuaXplcikNCmRvYyAgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlTnVtYmVycykNCmR0bSAgPC0gRG9jdW1lbnRUZXJtTWF0cml4KGRvYywgY29udHJvbDwtY29udHJvbC5saXN0KQ0KZHRtLnJlbW92ZSA8LSByZW1vdmVTcGFyc2VUZXJtcyhkdG0sIDAuOTkpDQpkdG0ucmVtb3ZlDQojZHRtJGRpbW5hbWVzJFRlcm1zDQoNCg0KZHRtLmRpc3QgPC0gcHJveHk6OmRpc3QoYXMubWF0cml4KGR0bS5yZW1vdmUpLCBtZXRob2QgPSJjb3NpbmUiKQ0KZHRtLm1hdCAgPC0gYXMubWF0cml4KGR0bS5kaXN0KQ0KaWR4IDwtIG9yZGVyKGR0bS5tYXRbMTI3LF0pWzE6MTBdDQpjYmluZChuZXdzJHRpdGxlW2lkeF0sIGR0bS5tYXRbMTI3LGlkeF0pDQoNCg0KDQojIGFydGljbGUgY2x1c3RlcmluZw0KZHRtLmNsdXN0ZXIgPC0gaGNsdXN0KGR0bS5kaXN0LCBtZXRob2QgPSAid2FyZC5EMiIpDQpwbG90KGR0bS5jbHVzdGVyLCBoYW5nPS0xKQ0KZml0IDwtIGN1dHJlZShkdG0uY2x1c3RlciwgayA9IDYpDQoNCm5ld3MkdGl0bGVbZml0ID09NV0NCg0KYGBgDQoNCg0KDQo=