R Basic

R 數值運算

3 + 8
[1] 11
3 -8
[1] -5
3 * 8
[1] 24
3 / 8
[1] 0.375
2 ^ 10
[1] 1024
11 %% 2
[1] 1
a <- 3
a
[1] 3
a = 3
b <- 5
a + b
[1] 8
a <- 8
b <- 5
a + b
[1] 13
numer <- 17.8
char <- "hello world"
logic <- TRUE
class(numer)
[1] "numeric"
class(char)
[1] "character"
card_length <- 3
card_width <- "5 inches"
card_width <- 5
card_length * card_width
[1] 15
RRP <- 35.99
Exchange <- 31.74
NTD <- RRP * Exchange
NTD
[1] 1142.323

向量 Vector

height_vec <- c(180,169,173)
names_vec <- c("Brian", "Toby", "Sherry")
height_vec[1]
[1] 180
height_vec[3]
[1] 173
height_vec[2:3]
[1] 169 173
x <- c(1,2,3,7)
y <- c(2,3,5,1)
x+y
[1] 3 5 8 8
x*y
[1]  2  6 15  7
x - y
[1] -1 -1 -2  6
x/y
[1] 0.5000000 0.6666667 0.6000000 7.0000000
x + 10
[1] 11 12 13 17
x + c(10)
[1] 11 12 13 17
x + c(10,10,10,10)
[1] 11 12 13 17
x <- 1:20
x
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14
[15] 15 16 17 18 19 20
y <- seq(1,20)
y <- seq(from = 1, to = 20)
y
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14
[15] 15 16 17 18 19 20
?seq
help(seq)
seq(1,20,2)
 [1]  1  3  5  7  9 11 13 15 17 19
seq(1,3.5, by =0.5)
[1] 1.0 1.5 2.0 2.5 3.0 3.5
seq(1,10,length=2)
[1]  1 10
x <- c(1,2,3,5,7)
sum(x)
[1] 18
min(x)
[1] 1
max(x)
[1] 7
summary(x)
   Min. 1st Qu.  Median    Mean 3rd Qu. 
    1.0     2.0     3.0     3.6     5.0 
   Max. 
    7.0 
?sum
height_vec <- c(180,169,173)
height_vec
[1] 180 169 173
names(height_vec) <- c("Brian", "Toby", "Sherry")
height_vec
 Brian   Toby Sherry 
   180    169    173 
name_vec <- c("Brian", "Toby", "Sherry")
names(height_vec) <- name_vec
height_vec
 Brian   Toby Sherry 
   180    169    173 
height_vec[1]
Brian 
  180 
height_vec > 175
 Brian   Toby Sherry 
  TRUE  FALSE  FALSE 
height_vec[height_vec > 175]
Brian 
  180 
height_vec >= 175
 Brian   Toby Sherry 
  TRUE  FALSE  FALSE 
height_vec <  175
 Brian   Toby Sherry 
 FALSE   TRUE   TRUE 
height_vec <= 175
 Brian   Toby Sherry 
 FALSE   TRUE   TRUE 
height_vec == 175
 Brian   Toby Sherry 
 FALSE  FALSE  FALSE 
height_vec != 175
 Brian   Toby Sherry 
  TRUE   TRUE   TRUE 
(height_vec >= 170) & (height_vec < 180)
 Brian   Toby Sherry 
 FALSE  FALSE   TRUE 
(height_vec >= 180) | (height_vec <= 170)
 Brian   Toby Sherry 
  TRUE   TRUE  FALSE 

BMI 計算

height_vec <- c(180,169,173)
weight_vec <- c(73 ,87 ,43 )
bmi_vec    <- weight_vec / ((height_vec / 100) ^ 2)
names_vec  <- c('Brian', 'Toby', 'Sherry')
names(bmi_vec) <- names_vec
bmi_vec < 18.5 | bmi_vec >=24
 Brian   Toby Sherry 
 FALSE   TRUE   TRUE 
bmi_vec[bmi_vec < 18.5 | bmi_vec >=24]
    Toby   Sherry 
30.46112 14.36734 
names(bmi_vec[bmi_vec < 18.5 | bmi_vec >=24])
[1] "Toby"   "Sherry"

陣列 (Matrix)

test1 <- c(60,53,80)
test2 <- c(80,63,90)
test3 <- c(70,58,85)
c(test1,test2,test3)
[1] 60 53 80 80 63 90 70 58 85
matrix(c(test1,test2,test3), nrow=3, byrow = TRUE)
     [,1] [,2] [,3]
[1,]   60   53   80
[2,]   80   63   90
[3,]   70   58   85
matrix(1:9, byrow=TRUE, nrow=3)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
matrix(1:9, nrow=3)
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
kevin <- c(85,73)
marry <- c(72,64)
jerry <- c(59,66)
c(kevin, marry, jerry)
[1] 85 73 72 64 59 66
mat <- matrix(c(kevin, marry, jerry), nrow = 3, byrow = TRUE)
colnames(mat) <- c('first', 'second')
rownames(mat) <- c('kevin', 'marry', 'jerry')
mat
      first second
kevin    85     73
marry    72     64
jerry    59     66
mat2 <- matrix(
          c(kevin, marry, jerry), 
               nrow=3, 
               byrow=TRUE,  
          dimnames=list(
            c('kevin', 'marry', 'jerry'),
            c('first', 'second'))
          )
mat2
      first second
kevin    85     73
marry    72     64
jerry    59     66
dim(mat2)
[1] 3 2
nrow(mat2)
[1] 3
ncol(mat2)
[1] 2
mat2
      first second
kevin    85     73
marry    72     64
jerry    59     66
mat2[,1]
kevin marry jerry 
   85    72    59 
mat2[1,]
 first second 
    85     73 
mat2[2:3,]
      first second
marry    72     64
jerry    59     66
mat2[2,1]
[1] 72
mat3 <- rbind(mat2, c(78,63))
rownames(mat3)[4] <- 'sam'
rownames(mat3)[nrow(mat3)] <- 'sam'
mat4 <- cbind(mat2, c(82,77,70))
colnames(mat4)[ncol(mat4)] <- 'third'
mat4
      first second third
kevin    85     73    82
marry    72     64    77
jerry    59     66    70
mat2
      first second
kevin    85     73
marry    72     64
jerry    59     66
rowSums(mat2)
kevin marry jerry 
  158   136   125 
rowMeans(mat2)
kevin marry jerry 
 79.0  68.0  62.5 
colSums(mat2)
 first second 
   216    203 
colMeans(mat2)
   first   second 
72.00000 67.66667 
m1 <- matrix(1:4, byrow=TRUE, nrow=2)
m2 <- matrix(5:8, byrow=TRUE, nrow=2)
m1 + m2
     [,1] [,2]
[1,]    6    8
[2,]   10   12
m1 - m2
     [,1] [,2]
[1,]   -4   -4
[2,]   -4   -4
m1 * m2
     [,1] [,2]
[1,]    5   12
[2,]   21   32
m1 / m2
          [,1]      [,2]
[1,] 0.2000000 0.3333333
[2,] 0.4285714 0.5000000
m1 %*% m2
     [,1] [,2]
[1,]   19   22
[2,]   43   50

計算考試成績加權結果

kevin <- c(85,73)
marry <- c(72,64)
jerry <- c(59,66)
mat <- matrix(c(kevin, marry, jerry), nrow=3,
byrow= TRUE)
colnames(mat) <- c('first', 'second')
rownames(mat) <- c('kevin', 'marry', 'jerry')
# method 1
test_avg <- mat[,1] * 0.4 + mat[,2] * 0.6 
cbind(mat, test_avg)
      first second test_avg
kevin    85     73     77.8
marry    72     64     67.2
jerry    59     66     63.2
# method 2
mat %*% c(0.4,0.6)
      [,1]
kevin 77.8
marry 67.2
jerry 63.2
# 9 * 9
matrix(1:9, nrow = 9) %*% matrix(1:9, nrow = 1)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
 [1,]    1    2    3    4    5    6    7    8
 [2,]    2    4    6    8   10   12   14   16
 [3,]    3    6    9   12   15   18   21   24
 [4,]    4    8   12   16   20   24   28   32
 [5,]    5   10   15   20   25   30   35   40
 [6,]    6   12   18   24   30   36   42   48
 [7,]    7   14   21   28   35   42   49   56
 [8,]    8   16   24   32   40   48   56   64
 [9,]    9   18   27   36   45   54   63   72
      [,9]
 [1,]    9
 [2,]   18
 [3,]   27
 [4,]   36
 [5,]   45
 [6,]   54
 [7,]   63
 [8,]   72
 [9,]   81

階層 (Factor)

weather <- c("sunny","rainy", "cloudy", "rainy", "cloudy")
class(weather)
[1] "character"
weather_category <- factor(weather)
weather_category
[1] sunny  rainy  cloudy rainy  cloudy
Levels: cloudy rainy sunny
class(weather_category)
[1] "factor"
levels(weather_category)
[1] "cloudy" "rainy"  "sunny" 
temperature <- c("Low", "High", "High", "Medium", "Low","Medium")
temperature
[1] "Low"    "High"   "High"   "Medium"
[5] "Low"    "Medium"
temperature_category <- factor(temperature, order =TRUE, levels = c("Low","Medium", "High"))
temperature_category
[1] Low    High   High   Medium Low    Medium
Levels: Low < Medium < High
temperature_category[3] > temperature_category[1]
[1] TRUE
temperature_category[4] > temperature_category[3]
[1] FALSE
levels(temperature_category)
[1] "Low"    "Medium" "High"  

Data Frame

days <- c('mon','tue','wed','thu','fri')
temp <- c( 22.2,   21,   23, 24.3, 25)
rain <- c( TRUE, TRUE,FALSE,FALSE, TRUE)
df   <- data.frame(days, temp, rain)
df
class(df)
[1] "data.frame"
str(df)
'data.frame':   5 obs. of  3 variables:
 $ days: Factor w/ 5 levels "fri","mon","thu",..: 2 4 5 3 1
 $ temp: num  22.2 21 23 24.3 25
 $ rain: logi  TRUE TRUE FALSE FALSE TRUE
summary(df)
  days        temp         rain        
 fri:1   Min.   :21.0   Mode :logical  
 mon:1   1st Qu.:22.2   FALSE:2        
 thu:1   Median :23.0   TRUE :3        
 tue:1   Mean   :23.1   NA's :0        
 wed:1   3rd Qu.:24.3                  
         Max.   :25.0                  
data()
data(iris)
class(iris)
[1] "data.frame"
View(iris)
head(iris)
#?head
head(iris, 10)
tail(iris)
tail(iris, 10)
iris[1:3 ,  ]
iris[1:3 , 1]
[1] 5.1 4.9 4.7
iris[1:3 , "Sepal.Length"]
[1] 5.1 4.9 4.7
iris[    , 1:2]
str(iris)
'data.frame':   150 obs. of  5 variables:
 $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
head(iris$Sepal.Length)
[1] 5.1 4.9 4.7 4.6 5.0 5.4
five.sepal.iris <- iris[1:5, c('Sepal.Length', 'Sepal.Width')]
# filter by true and false
iris[iris$Species == 'setosa', 1:3]
# filter by position
which(iris$Species == 'setosa')
 [1]  1  2  3  4  5  6  7  8  9 10 11 12
[13] 13 14 15 16 17 18 19 20 21 22 23 24
[25] 25 26 27 28 29 30 31 32 33 34 35 36
[37] 37 38 39 40 41 42 43 44 45 46 47 48
[49] 49 50
iris[which(iris$Species == 'setosa'), 1:3]
iris[iris$Species == 'setosa' & iris$Sepal.Length >= 5, 1:4]
# from small to large
sort(iris$Sepal.Length)
  [1] 4.3 4.4 4.4 4.4 4.5 4.6 4.6 4.6 4.6
 [10] 4.7 4.7 4.8 4.8 4.8 4.8 4.8 4.9 4.9
 [19] 4.9 4.9 4.9 4.9 5.0 5.0 5.0 5.0 5.0
 [28] 5.0 5.0 5.0 5.0 5.0 5.1 5.1 5.1 5.1
 [37] 5.1 5.1 5.1 5.1 5.1 5.2 5.2 5.2 5.2
 [46] 5.3 5.4 5.4 5.4 5.4 5.4 5.4 5.5 5.5
 [55] 5.5 5.5 5.5 5.5 5.5 5.6 5.6 5.6 5.6
 [64] 5.6 5.6 5.7 5.7 5.7 5.7 5.7 5.7 5.7
 [73] 5.7 5.8 5.8 5.8 5.8 5.8 5.8 5.8 5.9
 [82] 5.9 5.9 6.0 6.0 6.0 6.0 6.0 6.0 6.1
 [91] 6.1 6.1 6.1 6.1 6.1 6.2 6.2 6.2 6.2
[100] 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3
[109] 6.4 6.4 6.4 6.4 6.4 6.4 6.4 6.5 6.5
[118] 6.5 6.5 6.5 6.6 6.6 6.7 6.7 6.7 6.7
[127] 6.7 6.7 6.7 6.7 6.8 6.8 6.8 6.9 6.9
[136] 6.9 6.9 7.0 7.1 7.2 7.2 7.2 7.3 7.4
[145] 7.6 7.7 7.7 7.7 7.7 7.9
# from large to small
sort(iris$Sepal.Length, decreasing = TRUE)
  [1] 7.9 7.7 7.7 7.7 7.7 7.6 7.4 7.3 7.2
 [10] 7.2 7.2 7.1 7.0 6.9 6.9 6.9 6.9 6.8
 [19] 6.8 6.8 6.7 6.7 6.7 6.7 6.7 6.7 6.7
 [28] 6.7 6.6 6.6 6.5 6.5 6.5 6.5 6.5 6.4
 [37] 6.4 6.4 6.4 6.4 6.4 6.4 6.3 6.3 6.3
 [46] 6.3 6.3 6.3 6.3 6.3 6.3 6.2 6.2 6.2
 [55] 6.2 6.1 6.1 6.1 6.1 6.1 6.1 6.0 6.0
 [64] 6.0 6.0 6.0 6.0 5.9 5.9 5.9 5.8 5.8
 [73] 5.8 5.8 5.8 5.8 5.8 5.7 5.7 5.7 5.7
 [82] 5.7 5.7 5.7 5.7 5.6 5.6 5.6 5.6 5.6
 [91] 5.6 5.5 5.5 5.5 5.5 5.5 5.5 5.5 5.4
[100] 5.4 5.4 5.4 5.4 5.4 5.3 5.2 5.2 5.2
[109] 5.2 5.1 5.1 5.1 5.1 5.1 5.1 5.1 5.1
[118] 5.1 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0
[127] 5.0 5.0 4.9 4.9 4.9 4.9 4.9 4.9 4.8
[136] 4.8 4.8 4.8 4.8 4.7 4.7 4.6 4.6 4.6
[145] 4.6 4.5 4.4 4.4 4.4 4.3
a <- c(2,4,5,1,3)
sort(a)
[1] 1 2 3 4 5
order(a)
[1] 4 1 5 2 3
iris[order(iris$Sepal.Length, decreasing = TRUE), ]

股票分析

#install.packages("quantmod")
library(quantmod)
getSymbols('2330.TW')
[1] "2330.TW"
View(`2330.TW`)
class(`2330.TW`)
[1] "xts" "zoo"
tw2330 <- as.data.frame(`2330.TW`)
str(tw2330)
'data.frame':   2509 obs. of  6 variables:
 $ 2330.TW.Open    : num  67.5 67.5 67.4 67.2 65.8 ...
 $ 2330.TW.High    : num  67.7 68.4 67.8 67.4 66.2 ...
 $ 2330.TW.Low     : num  67 67.2 67.3 66.2 65.4 ...
 $ 2330.TW.Close   : num  67.4 67.7 67.4 66.6 65.5 ...
 $ 2330.TW.Volume  : num  26160600 42250300 22331600 30750100 24228400 ...
 $ 2330.TW.Adjusted: num  47.3 47.5 47.3 46.8 46 ...
max(tw2330$`2330.TW.Close`)
[1] 193
min(tw2330$`2330.TW.Close`)
[1] 36.8
summary(tw2330$`2330.TW.Close`)
   Min. 1st Qu.  Median    Mean 3rd Qu. 
  36.80   62.30   76.60   92.15  122.00 
   Max. 
 193.00 

查詢最大最小

tw2330[order(tw2330$`2330.TW.Close`),]
tw2330[order(tw2330$`2330.TW.Close`, decreasing = TRUE),]

繪製股價圖表

hist(tw2330$`2330.TW.Close`)

boxplot(tw2330$`2330.TW.Close`)

plot(tw2330$`2330.TW.Close`)

股票漲跌分析

tw2330$tf <- ifelse((tw2330$`2330.TW.Close` - tw2330$`2330.TW.Open`) > 0, 'bull', 'bear')
head(tw2330)
table(tw2330$tf)

bear bull 
1435 1074 

分析2015年股價走勢

tw2330_close_2015 <- tw2330[rownames(tw2330) >= '2015-01-01' & rownames(tw2330) < '2016-01-01', 4]
max(tw2330_close_2015)
[1] 154.5
min(tw2330_close_2015)
[1] 115
summary(tw2330_close_2015)
   Min. 1st Qu.  Median    Mean 3rd Qu. 
  115.0   136.5   141.0   140.1   146.0 
   Max. 
  154.5 

清單(Lists)

item <- list(thing="hat", size=8.25)
item
$thing
[1] "hat"

$size
[1] 8.25
item$size
[1] 8.25
test <- list(name="Toby", score = c(87,57,72))
test$score
[1] 87 57 72
test$score[1]
[1] 87
li <- list(c(3,5,12), c(2,4,5,8,10))
li
[[1]]
[1]  3  5 12

[[2]]
[1]  2  4  5  8 10
li[[1]]
[1]  3  5 12
li[[2]]
[1]  2  4  5  8 10
lapply(li, sum)
[[1]]
[1] 20

[[2]]
[1] 29
LS0tDQp0aXRsZTogIkRlbW8yMDE2MTExMiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQojIFIgQmFzaWMNCg0KIyMgUiC8xq3IuUK64g0KDQpgYGB7cn0NCjMgKyA4DQozIC04DQozICogOA0KMyAvIDgNCjIgXiAxMA0KMTEgJSUgMg0KDQphIDwtIDMNCmENCmEgPSAzDQpiIDwtIDUNCmEgKyBiDQoNCmEgPC0gOA0KYiA8LSA1DQphICsgYg0KDQpudW1lciA8LSAxNy44DQpjaGFyIDwtICJoZWxsbyB3b3JsZCINCmxvZ2ljIDwtIFRSVUUNCmNsYXNzKG51bWVyKQ0KY2xhc3MoY2hhcikNCg0KY2FyZF9sZW5ndGggPC0gMw0KY2FyZF93aWR0aCA8LSAiNSBpbmNoZXMiDQoNCmNhcmRfd2lkdGggPC0gNQ0KY2FyZF9sZW5ndGggKiBjYXJkX3dpZHRoDQoNClJSUCA8LSAzNS45OQ0KDQpFeGNoYW5nZSA8LSAzMS43NA0KTlREIDwtIFJSUCAqIEV4Y2hhbmdlDQpOVEQNCmBgYA0KIyMgpla2cSBWZWN0b3INCg0KYGBge3J9DQpoZWlnaHRfdmVjIDwtIGMoMTgwLDE2OSwxNzMpDQpuYW1lc192ZWMgPC0gYygiQnJpYW4iLCAiVG9ieSIsICJTaGVycnkiKQ0KaGVpZ2h0X3ZlY1sxXQ0KaGVpZ2h0X3ZlY1szXQ0KaGVpZ2h0X3ZlY1syOjNdDQoNCg0KeCA8LSBjKDEsMiwzLDcpDQp5IDwtIGMoMiwzLDUsMSkNCngreQ0KeCp5DQp4IC0geQ0KeC95DQoNCnggKyAxMA0KeCArIGMoMTApDQp4ICsgYygxMCwxMCwxMCwxMCkNCg0KeCA8LSAxOjIwDQp4DQp5IDwtIHNlcSgxLDIwKQ0KeSA8LSBzZXEoZnJvbSA9IDEsIHRvID0gMjApDQp5DQo/c2VxDQpoZWxwKHNlcSkNCg0Kc2VxKDEsMjAsMikNCnNlcSgxLDMuNSwgYnkgPTAuNSkNCnNlcSgxLDEwLGxlbmd0aD0yKQ0KDQoNCnggPC0gYygxLDIsMyw1LDcpDQpzdW0oeCkNCm1pbih4KQ0KbWF4KHgpDQpzdW1tYXJ5KHgpDQo/c3VtDQoNCg0KaGVpZ2h0X3ZlYyA8LSBjKDE4MCwxNjksMTczKQ0KaGVpZ2h0X3ZlYw0KbmFtZXMoaGVpZ2h0X3ZlYykgPC0gYygiQnJpYW4iLCAiVG9ieSIsICJTaGVycnkiKQ0KaGVpZ2h0X3ZlYw0KDQpuYW1lX3ZlYyA8LSBjKCJCcmlhbiIsICJUb2J5IiwgIlNoZXJyeSIpDQpuYW1lcyhoZWlnaHRfdmVjKSA8LSBuYW1lX3ZlYw0KaGVpZ2h0X3ZlYw0KaGVpZ2h0X3ZlY1sxXQ0KDQpoZWlnaHRfdmVjID4gMTc1DQpoZWlnaHRfdmVjW2hlaWdodF92ZWMgPiAxNzVdDQpoZWlnaHRfdmVjID49IDE3NQ0KaGVpZ2h0X3ZlYyA8ICAxNzUNCmhlaWdodF92ZWMgPD0gMTc1DQpoZWlnaHRfdmVjID09IDE3NQ0KaGVpZ2h0X3ZlYyAhPSAxNzUNCg0KKGhlaWdodF92ZWMgPj0gMTcwKSAmIChoZWlnaHRfdmVjIDwgMTgwKQ0KDQooaGVpZ2h0X3ZlYyA+PSAxODApIHwgKGhlaWdodF92ZWMgPD0gMTcwKQ0KYGBgDQojIyBCTUkgrXC64g0KYGBge3J9DQpoZWlnaHRfdmVjIDwtIGMoMTgwLDE2OSwxNzMpDQp3ZWlnaHRfdmVjIDwtIGMoNzMgLDg3ICw0MyApDQpibWlfdmVjICAgIDwtIHdlaWdodF92ZWMgLyAoKGhlaWdodF92ZWMgLyAxMDApIF4gMikNCg0KbmFtZXNfdmVjICA8LSBjKCdCcmlhbicsICdUb2J5JywgJ1NoZXJyeScpDQpuYW1lcyhibWlfdmVjKSA8LSBuYW1lc192ZWMNCg0KYm1pX3ZlYyA8IDE4LjUgfCBibWlfdmVjID49MjQNCmJtaV92ZWNbYm1pX3ZlYyA8IDE4LjUgfCBibWlfdmVjID49MjRdDQpuYW1lcyhibWlfdmVjW2JtaV92ZWMgPCAxOC41IHwgYm1pX3ZlYyA+PTI0XSkNCg0KYGBgDQojIyCwfaZDIChNYXRyaXgpDQpgYGB7cn0NCnRlc3QxIDwtIGMoNjAsNTMsODApDQp0ZXN0MiA8LSBjKDgwLDYzLDkwKQ0KdGVzdDMgPC0gYyg3MCw1OCw4NSkNCmModGVzdDEsdGVzdDIsdGVzdDMpDQoNCm1hdHJpeChjKHRlc3QxLHRlc3QyLHRlc3QzKSwgbnJvdz0zLCBieXJvdyA9IFRSVUUpDQoNCm1hdHJpeCgxOjksIGJ5cm93PVRSVUUsIG5yb3c9MykNCm1hdHJpeCgxOjksIG5yb3c9MykNCg0Ka2V2aW4gPC0gYyg4NSw3MykNCm1hcnJ5IDwtIGMoNzIsNjQpDQpqZXJyeSA8LSBjKDU5LDY2KQ0KYyhrZXZpbiwgbWFycnksIGplcnJ5KQ0KDQptYXQgPC0gbWF0cml4KGMoa2V2aW4sIG1hcnJ5LCBqZXJyeSksIG5yb3cgPSAzLCBieXJvdyA9IFRSVUUpDQoNCmNvbG5hbWVzKG1hdCkgPC0gYygnZmlyc3QnLCAnc2Vjb25kJykNCnJvd25hbWVzKG1hdCkgPC0gYygna2V2aW4nLCAnbWFycnknLCAnamVycnknKQ0KbWF0DQoNCm1hdDIgPC0gbWF0cml4KA0KICAgICAgICAgIGMoa2V2aW4sIG1hcnJ5LCBqZXJyeSksIA0KICAgICAgICAgICAgICAgbnJvdz0zLCANCiAgICAgICAgICAgICAgIGJ5cm93PVRSVUUsICANCiAgICAgICAgICBkaW1uYW1lcz1saXN0KA0KICAgICAgICAgICAgYygna2V2aW4nLCAnbWFycnknLCAnamVycnknKSwNCiAgICAgICAgICAgIGMoJ2ZpcnN0JywgJ3NlY29uZCcpKQ0KICAgICAgICAgICkNCm1hdDINCg0KZGltKG1hdDIpDQpucm93KG1hdDIpDQpuY29sKG1hdDIpDQptYXQyDQptYXQyWywxXQ0KbWF0MlsxLF0NCm1hdDJbMjozLF0NCm1hdDJbMiwxXQ0KDQptYXQzIDwtIHJiaW5kKG1hdDIsIGMoNzgsNjMpKQ0Kcm93bmFtZXMobWF0MylbNF0gPC0gJ3NhbScNCnJvd25hbWVzKG1hdDMpW25yb3cobWF0MyldIDwtICdzYW0nDQoNCm1hdDQgPC0gY2JpbmQobWF0MiwgYyg4Miw3Nyw3MCkpDQpjb2xuYW1lcyhtYXQ0KVtuY29sKG1hdDQpXSA8LSAndGhpcmQnDQptYXQ0DQoNCm1hdDINCnJvd1N1bXMobWF0MikNCnJvd01lYW5zKG1hdDIpDQpjb2xTdW1zKG1hdDIpDQpjb2xNZWFucyhtYXQyKQ0KDQptMSA8LSBtYXRyaXgoMTo0LCBieXJvdz1UUlVFLCBucm93PTIpDQptMiA8LSBtYXRyaXgoNTo4LCBieXJvdz1UUlVFLCBucm93PTIpDQptMSArIG0yDQptMSAtIG0yDQptMSAqIG0yDQptMSAvIG0yDQoNCm0xICUqJSBtMg0KDQpgYGANCiMgrXC64qbSuNWmqMFapVvFdrWyqkcNCmBgYHtyfQ0Ka2V2aW4gPC0gYyg4NSw3MykNCm1hcnJ5IDwtIGMoNzIsNjQpDQpqZXJyeSA8LSBjKDU5LDY2KQ0KbWF0IDwtIG1hdHJpeChjKGtldmluLCBtYXJyeSwgamVycnkpLCBucm93PTMsDQpieXJvdz0gVFJVRSkNCmNvbG5hbWVzKG1hdCkgPC0gYygnZmlyc3QnLCAnc2Vjb25kJykNCnJvd25hbWVzKG1hdCkgPC0gYygna2V2aW4nLCAnbWFycnknLCAnamVycnknKQ0KDQojIG1ldGhvZCAxDQp0ZXN0X2F2ZyA8LSBtYXRbLDFdICogMC40ICsgbWF0WywyXSAqIDAuNiANCmNiaW5kKG1hdCwgdGVzdF9hdmcpDQoNCiMgbWV0aG9kIDINCm1hdCAlKiUgYygwLjQsMC42KQ0KDQojIDkgKiA5DQptYXRyaXgoMTo5LCBucm93ID0gOSkgJSolIG1hdHJpeCgxOjksIG5yb3cgPSAxKQ0KDQpgYGANCiMjILalvGggKEZhY3RvcikNCmBgYHtyfQ0Kd2VhdGhlciA8LSBjKCJzdW5ueSIsInJhaW55IiwgImNsb3VkeSIsICJyYWlueSIsICJjbG91ZHkiKQ0KY2xhc3Mod2VhdGhlcikNCndlYXRoZXJfY2F0ZWdvcnkgPC0gZmFjdG9yKHdlYXRoZXIpDQp3ZWF0aGVyX2NhdGVnb3J5DQoNCmNsYXNzKHdlYXRoZXJfY2F0ZWdvcnkpDQpsZXZlbHMod2VhdGhlcl9jYXRlZ29yeSkNCg0KDQp0ZW1wZXJhdHVyZSA8LSBjKCJMb3ciLCAiSGlnaCIsICJIaWdoIiwgIk1lZGl1bSIsICJMb3ciLCJNZWRpdW0iKQ0KdGVtcGVyYXR1cmUNCg0KdGVtcGVyYXR1cmVfY2F0ZWdvcnkgPC0gZmFjdG9yKHRlbXBlcmF0dXJlLCBvcmRlciA9VFJVRSwgbGV2ZWxzID0gYygiTG93IiwiTWVkaXVtIiwgIkhpZ2giKSkNCnRlbXBlcmF0dXJlX2NhdGVnb3J5DQoNCnRlbXBlcmF0dXJlX2NhdGVnb3J5WzNdID4gdGVtcGVyYXR1cmVfY2F0ZWdvcnlbMV0NCnRlbXBlcmF0dXJlX2NhdGVnb3J5WzRdID4gdGVtcGVyYXR1cmVfY2F0ZWdvcnlbM10NCg0KbGV2ZWxzKHRlbXBlcmF0dXJlX2NhdGVnb3J5KQ0KYGBgDQojIyBEYXRhIEZyYW1lDQpgYGB7cn0NCmRheXMgPC0gYygnbW9uJywndHVlJywnd2VkJywndGh1JywnZnJpJykNCnRlbXAgPC0gYyggMjIuMiwgICAyMSwgICAyMywgMjQuMywgMjUpDQpyYWluIDwtIGMoIFRSVUUsIFRSVUUsRkFMU0UsRkFMU0UsIFRSVUUpDQpkZiAgIDwtIGRhdGEuZnJhbWUoZGF5cywgdGVtcCwgcmFpbikNCmRmDQoNCmNsYXNzKGRmKQ0Kc3RyKGRmKQ0Kc3VtbWFyeShkZikNCg0KZGF0YSgpDQpkYXRhKGlyaXMpDQpjbGFzcyhpcmlzKQ0KVmlldyhpcmlzKQ0KDQpoZWFkKGlyaXMpDQojP2hlYWQNCmhlYWQoaXJpcywgMTApDQoNCnRhaWwoaXJpcykNCnRhaWwoaXJpcywgMTApDQoNCmlyaXNbMTozICwgIF0NCmlyaXNbMTozICwgMV0NCmlyaXNbMTozICwgIlNlcGFsLkxlbmd0aCJdDQppcmlzWyAgICAsIDE6Ml0NCg0Kc3RyKGlyaXMpDQpoZWFkKGlyaXMkU2VwYWwuTGVuZ3RoKQ0KDQpmaXZlLnNlcGFsLmlyaXMgPC0gaXJpc1sxOjUsIGMoJ1NlcGFsLkxlbmd0aCcsICdTZXBhbC5XaWR0aCcpXQ0KDQojIGZpbHRlciBieSB0cnVlIGFuZCBmYWxzZQ0KaXJpc1tpcmlzJFNwZWNpZXMgPT0gJ3NldG9zYScsIDE6M10NCg0KIyBmaWx0ZXIgYnkgcG9zaXRpb24NCndoaWNoKGlyaXMkU3BlY2llcyA9PSAnc2V0b3NhJykNCmlyaXNbd2hpY2goaXJpcyRTcGVjaWVzID09ICdzZXRvc2EnKSwgMTozXQ0KDQoNCmlyaXNbaXJpcyRTcGVjaWVzID09ICdzZXRvc2EnICYgaXJpcyRTZXBhbC5MZW5ndGggPj0gNSwgMTo0XQ0KDQojIGZyb20gc21hbGwgdG8gbGFyZ2UNCnNvcnQoaXJpcyRTZXBhbC5MZW5ndGgpDQoNCiMgZnJvbSBsYXJnZSB0byBzbWFsbA0Kc29ydChpcmlzJFNlcGFsLkxlbmd0aCwgZGVjcmVhc2luZyA9IFRSVUUpDQoNCmEgPC0gYygyLDQsNSwxLDMpDQpzb3J0KGEpDQpvcmRlcihhKQ0KDQppcmlzW29yZGVyKGlyaXMkU2VwYWwuTGVuZ3RoLCBkZWNyZWFzaW5nID0gVFJVRSksIF0NCg0KDQoNCmBgYA0KIyMgqtGyvKTAqlINCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoInF1YW50bW9kIikNCmxpYnJhcnkocXVhbnRtb2QpDQpnZXRTeW1ib2xzKCcyMzMwLlRXJykNClZpZXcoYDIzMzAuVFdgKQ0KY2xhc3MoYDIzMzAuVFdgKQ0KdHcyMzMwIDwtIGFzLmRhdGEuZnJhbWUoYDIzMzAuVFdgKQ0KDQpzdHIodHcyMzMwKQ0KbWF4KHR3MjMzMCRgMjMzMC5UVy5DbG9zZWApDQptaW4odHcyMzMwJGAyMzMwLlRXLkNsb3NlYCkNCnN1bW1hcnkodHcyMzMwJGAyMzMwLlRXLkNsb3NlYCkNCmBgYA0KIyMgrGS437PMpGqzzKRwDQpgYGB7cn0NCnR3MjMzMFtvcmRlcih0dzIzMzAkYDIzMzAuVFcuQ2xvc2VgKSxdDQp0dzIzMzBbb3JkZXIodHcyMzMwJGAyMzMwLlRXLkNsb3NlYCwgZGVjcmVhc2luZyA9IFRSVUUpLF0NCmBgYA0KIyDDuLtzqtG7+bnPqu0NCmBgYHtyfQ0KDQpoaXN0KHR3MjMzMCRgMjMzMC5UVy5DbG9zZWApDQpib3hwbG90KHR3MjMzMCRgMjMzMC5UVy5DbG9zZWApDQpwbG90KHR3MjMzMCRgMjMzMC5UVy5DbG9zZWApDQpgYGANCg0KIyMgqtGyvLqmtl6kwKpSDQpgYGB7cn0NCnR3MjMzMCR0ZiA8LSBpZmVsc2UoKHR3MjMzMCRgMjMzMC5UVy5DbG9zZWAgLSB0dzIzMzAkYDIzMzAuVFcuT3BlbmApID4gMCwgJ2J1bGwnLCAnYmVhcicpDQoNCmhlYWQodHcyMzMwKQ0KdGFibGUodHcyMzMwJHRmKQ0KYGBgDQojIKTAqlIyMDE1pn6q0bv5qKu21Q0KYGBge3J9DQp0dzIzMzBfY2xvc2VfMjAxNSA8LSB0dzIzMzBbcm93bmFtZXModHcyMzMwKSA+PSAnMjAxNS0wMS0wMScgJiByb3duYW1lcyh0dzIzMzApIDwgJzIwMTYtMDEtMDEnLCA0XQ0KbWF4KHR3MjMzMF9jbG9zZV8yMDE1KQ0KbWluKHR3MjMzMF9jbG9zZV8yMDE1KQ0Kc3VtbWFyeSh0dzIzMzBfY2xvc2VfMjAxNSkNCmBgYA0KIyMgsk2z5ihMaXN0cykNCmBgYHtyfQ0KaXRlbSA8LSBsaXN0KHRoaW5nPSJoYXQiLCBzaXplPTguMjUpDQppdGVtDQppdGVtJHNpemUNCg0KdGVzdCA8LSBsaXN0KG5hbWU9IlRvYnkiLCBzY29yZSA9IGMoODcsNTcsNzIpKQ0KdGVzdCRzY29yZQ0KdGVzdCRzY29yZVsxXQ0KDQoNCmxpIDwtIGxpc3QoYygzLDUsMTIpLCBjKDIsNCw1LDgsMTApKQ0KbGkNCmxpW1sxXV0NCmxpW1syXV0NCg0KbGFwcGx5KGxpLCBzdW0pDQpgYGANCg0K