Cài đặt 2 thư viện này giúp mình :

install.packages(“rmarkdown”).
Install.packages(‘tinydex’)
tinytex::install_tinytex()

Tài liệu Rmarkdown : 1 2

Công thức toán : 3 4

Vẽ sơ đồ : 5

Xin chào mọi người đến với bài hướng dẫn về ngôn ngữ lập trình R của mình. Nếu có thắc mắc gì các bạn có thể comment xuống bài viết hoặc nhắn tin qua facebook của mình : Huyy Huyy.

OK bắt đầu nào, bây giờ mọi người hãy xem video giới thiệu về Linear Regression sau đây : video

Chúng ta sẽ minh hoạ nó bằng hình ảnh :

2 Đọc dữ liệu từ file .csv (Heart.csv)

Bộ dữ liệu gồm có 15 biến, trong đó biến kết quả là AHD gồm 2 giá trị là Yes hoặc No, ở đây ta dùng lệnh head() để xem một vài dòng đầu của bộ dữ liệu.

X Age Sex ChestPain RestBP Chol Fbs RestECG MaxHR ExAng Oldpeak Slope Ca Thal AHD
1 63 1 typical 145 233 1 2 150 0 2.3 3 0 fixed No
2 67 1 asymptomatic 160 286 0 2 108 1 1.5 2 3 normal Yes
3 67 1 asymptomatic 120 229 0 2 129 1 2.6 2 2 reversable Yes
4 37 1 nonanginal 130 250 0 0 187 0 3.5 3 0 normal No
5 41 0 nontypical 130 204 0 2 172 0 1.4 1 0 normal No
6 56 1 nontypical 120 236 0 0 178 0 0.8 1 0 normal No

2.1 Tạo một biến Gender tương ứng với biến Sex (0 : Female , 1 : Male )

3 Phân tích tương quan

Phân tích tương quan cho ta biết mối liên quan giữa 2 hay nhiều biến là mạnh hay yếu. Hệ số tương quan được ký hiệu là r và nằm trong khoảng -1 < r < 1. Công thức tính hệ số tương quan giữa hai biến xy : \[r_{xy} = \frac{S_{xy}}{S_{x}S_{y}} \]

3.1 Tương quan một biến

Trong phần này, mình sẽ tính hệ số tương quan giữa 2 biến MaxHRAge. Ta sẽ dùng hàm cor.test()

## 
##  Pearson's product-moment correlation
## 
## data:  MaxHR and Age
## t = -7.4329, df = 301, p-value = 1.109e-12
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.4849644 -0.2941816
## sample estimates:
##        cor 
## -0.3938058

Dựa vào kết quả ta có hệ số tương quan là : -0.39

3.2 Tương quan đa biến

Tương tự tương quan một biến, ở tương quan đa biến ta dùng hàm corr.test() để tính. Ở đây mình sẽ tính tương quan đa biến giữa các biến được lưu trong biến vars

## Call:corr.test(x = vars)
## Correlation matrix 
##         MaxHR   Age Chol RestBP Oldpeak  Thal
## MaxHR    1.00 -0.39 0.00  -0.05   -0.34 -0.12
## Age     -0.39  1.00 0.21   0.28    0.20  0.06
## Chol     0.00  0.21 1.00   0.13    0.05  0.08
## RestBP  -0.05  0.28 0.13   1.00    0.19  0.06
## Oldpeak -0.34  0.20 0.05   0.19    1.00  0.21
## Thal    -0.12  0.06 0.08   0.06    0.21  1.00
## Sample Size 
##         MaxHR Age Chol RestBP Oldpeak Thal
## MaxHR     303 303  303    303     303  301
## Age       303 303  303    303     303  301
## Chol      303 303  303    303     303  301
## RestBP    303 303  303    303     303  301
## Oldpeak   303 303  303    303     303  301
## Thal      301 301  301    301     301  301
## Probability values (Entries above the diagonal are adjusted for multiple tests.) 
##         MaxHR  Age Chol RestBP Oldpeak Thal
## MaxHR    0.00 0.00 1.00   1.00    0.00 0.29
## Age      0.00 0.00 0.00   0.00    0.00 1.00
## Chol     0.95 0.00 0.00   0.19    1.00 0.97
## RestBP   0.43 0.00 0.02   0.00    0.01 1.00
## Oldpeak  0.00 0.00 0.42   0.00    0.00 0.00
## Thal     0.04 0.29 0.16   0.32    0.00 0.00
## 
##  To see confidence intervals of the correlations, print with the short=FALSE option

Biểu đồ minh hoạ

4 Hồi quy tuyến tính một biến

Phương trình hồi quy tuyến tính có dạng :

\(Y = \alpha + \beta X_{0}\)

Trong đó :

  • Y là biến mục tiêu
  • \(\alpha\) là intercept
  • \(\beta\) là hệ số hồi quy
  • \(X_{0}\) là biến đầu vào

Đối với hồi quy tuyến tính trong R, mình sẽ dử dụng hàm lm() để đưa các biến cần xây dựng mô hình và dùng hàm summary() để xem tóm tắt các thông số trong mô hình.

4.1 Hồi quy tuyến tính với biến liên tục

## 
## Call:
## lm(formula = MaxHR ~ Age)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -66.088 -12.040   3.965  15.937  44.955 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 203.8634     7.3991  27.553  < 2e-16 ***
## Age          -0.9966     0.1341  -7.433 1.11e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 21.06 on 301 degrees of freedom
## Multiple R-squared:  0.1551, Adjusted R-squared:  0.1523 
## F-statistic: 55.25 on 1 and 301 DF,  p-value: 1.109e-12

4.1.2 Tính y^

Ta dùng hàm predict() để tính giá trị y dự đoán

##        1        2        3        4        5        6 
## 141.0750 137.0884 137.0884 166.9876 163.0011 148.0514

Ở đây ta có thể tóm tắt như sau:

\(X_0\) \(\hat{Y}\)
63 141.01
67 137.08
67 137.08
37 166.98
41 163.00

4.1.3 Phân tích phương sai

Df Sum Sq Mean Sq F value Pr(>F)
Age 1 24507.19 24507.189 55.24802 0
Residuals 301 133519.07 443.585 NA NA

4.1.4 Phân tích residual

4.1.5 Phân phối chuẩn

  • Tính y - y^
##          1          2          3          4          5          6 
##   8.925046 -29.088387  -8.088387  20.012358   8.998926  29.948553
  • Kiểm định phân phối chuẩn

## 
##  Shapiro-Wilk normality test
## 
## data:  m
## W = 0.96133, p-value = 3.296e-07
  • Trung bình bằng 0
## [1] -6.282132e-16
  • Kiểm tra phương sai
## Non-constant Variance Score Test 
## Variance formula: ~ fitted.values 
## Chisquare = 0.7229959, Df = 1, p = 0.39516

## 
## Suggested power transformation:  1.217132

4.2 Hồi quy tuyến tính với biến phân nhóm

## 
## Call:
## lm(formula = MaxHR ~ Gender)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -77.845 -16.036   2.773  16.155  53.155 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  151.227      2.324  65.080   <2e-16 ***
## GenderMale    -2.382      2.818  -0.845    0.399    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 22.89 on 301 degrees of freedom
## Multiple R-squared:  0.002368,   Adjusted R-squared:  -0.0009463 
## F-statistic: 0.7145 on 1 and 301 DF,  p-value: 0.3986

5 Hồi quy tuyến tính đa biến

## 
## Call:
## lm(formula = MaxHR ~ RestBP + Age + Thal)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -70.046 -12.269   3.579  14.086  52.824 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    172.57393   11.48221  15.030  < 2e-16 ***
## RestBP           0.13314    0.06932   1.921 0.055720 .  
## Age             -0.98287    0.13478  -7.292  2.8e-12 ***
## Thalnormal      18.34722    5.04476   3.637 0.000325 ***
## Thalreversable   7.69466    5.11709   1.504 0.133721    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 20.19 on 296 degrees of freedom
##   (2 observations deleted due to missingness)
## Multiple R-squared:  0.2301, Adjusted R-squared:  0.2197 
## F-statistic: 22.12 on 4 and 296 DF,  p-value: 5.425e-16

6 Xây dựng mô hình thống kê tối ưu

  • Xử lý dữ liệu1
Age Sex ChestPain RestBP Chol Fbs RestECG MaxHR ExAng Oldpeak Slope Ca Thal
63 1 typical 145 233 1 2 150 0 2.3 3 0 fixed
67 1 asymptomatic 160 286 0 2 108 1 1.5 2 3 normal
67 1 asymptomatic 120 229 0 2 129 1 2.6 2 2 reversable
37 1 nonanginal 130 250 0 0 187 0 3.5 3 0 normal
41 0 nontypical 130 204 0 2 172 0 1.4 1 0 normal
56 1 nontypical 120 236 0 0 178 0 0.8 1 0 normal
  • Xây dựng mô hình
  • Chọn mô hình tối ưu
## Start:  AIC=1740.99
## MaxHR ~ Age + Sex + ChestPain + RestBP + Chol + Fbs + RestECG + 
##     ExAng + Oldpeak + Slope + Ca + Thal
## 
##             Df Sum of Sq    RSS    AIC
## - Sex        1       0.5  93705 1739.0
## - Thal       2     714.5  94419 1739.2
## - RestECG    1     103.5  93808 1739.3
## - Fbs        1     130.9  93836 1739.4
## - Oldpeak    1     204.4  93909 1739.6
## - Ca         1     260.5  93965 1739.8
## <none>                    93705 1741.0
## - Chol       1     753.7  94458 1741.4
## - RestBP     1    1062.2  94767 1742.3
## - ChestPain  3    3261.9  96967 1745.2
## - Slope      1    4418.0  98123 1752.7
## - ExAng      1    4689.1  98394 1753.5
## - Age        1   13092.8 106798 1777.8
## 
## Step:  AIC=1738.99
## MaxHR ~ Age + ChestPain + RestBP + Chol + Fbs + RestECG + ExAng + 
##     Oldpeak + Slope + Ca + Thal
## 
##             Df Sum of Sq    RSS    AIC
## - RestECG    1     105.5  93811 1737.3
## - Thal       2     747.6  94453 1737.3
## - Fbs        1     131.6  93837 1737.4
## - Oldpeak    1     203.9  93909 1737.6
## - Ca         1     260.0  93965 1737.8
## <none>                    93705 1739.0
## - Chol       1     774.6  94480 1739.4
## - RestBP     1    1070.6  94776 1740.4
## - ChestPain  3    3303.9  97009 1743.3
## - Slope      1    4477.9  98183 1750.8
## - ExAng      1    4704.6  98410 1751.5
## - Age        1   13253.5 106959 1776.3
## 
## Step:  AIC=1737.32
## MaxHR ~ Age + ChestPain + RestBP + Chol + Fbs + ExAng + Oldpeak + 
##     Slope + Ca + Thal
## 
##             Df Sum of Sq    RSS    AIC
## - Thal       2     758.0  94569 1735.7
## - Fbs        1     140.8  93951 1735.8
## - Oldpeak    1     206.8  94017 1736.0
## - Ca         1     240.7  94051 1736.1
## <none>                    93811 1737.3
## - Chol       1     871.6  94682 1738.1
## - RestBP     1    1137.1  94948 1738.9
## - ChestPain  3    3251.5  97062 1741.4
## - Slope      1    4392.3  98203 1748.9
## - ExAng      1    4686.0  98497 1749.8
## - Age        1   13184.0 106995 1774.4
## 
## Step:  AIC=1735.71
## MaxHR ~ Age + ChestPain + RestBP + Chol + Fbs + ExAng + Oldpeak + 
##     Slope + Ca
## 
##             Df Sum of Sq    RSS    AIC
## - Fbs        1      90.2  94659 1734.0
## - Oldpeak    1     223.5  94792 1734.4
## - Ca         1     331.9  94901 1734.8
## <none>                    94569 1735.7
## - RestBP     1    1020.2  95589 1736.9
## - Chol       1    1085.9  95655 1737.1
## - ChestPain  3    3653.3  98222 1741.0
## - ExAng      1    5008.0  99577 1749.0
## - Slope      1    5152.4  99721 1749.5
## - Age        1   13186.6 107755 1772.5
## 
## Step:  AIC=1734
## MaxHR ~ Age + ChestPain + RestBP + Chol + ExAng + Oldpeak + Slope + 
##     Ca
## 
##             Df Sum of Sq    RSS    AIC
## - Oldpeak    1     251.0  94910 1732.8
## - Ca         1     285.6  94944 1732.9
## <none>                    94659 1734.0
## - Chol       1    1070.5  95729 1735.3
## - RestBP     1    1147.3  95806 1735.6
## - ChestPain  3    3830.4  98489 1739.8
## - ExAng      1    4969.9  99629 1747.2
## - Slope      1    5086.7  99746 1747.5
## - Age        1   13121.8 107781 1770.5
## 
## Step:  AIC=1732.78
## MaxHR ~ Age + ChestPain + RestBP + Chol + ExAng + Slope + Ca
## 
##             Df Sum of Sq    RSS    AIC
## - Ca         1     445.4  95355 1732.2
## <none>                    94910 1732.8
## - RestBP     1    1042.6  95952 1734.0
## - Chol       1    1065.2  95975 1734.1
## - ChestPain  3    3999.2  98909 1739.0
## - ExAng      1    5269.1 100179 1746.8
## - Slope      1    8707.8 103618 1756.9
## - Age        1   13067.3 107977 1769.1
## 
## Step:  AIC=1732.17
## MaxHR ~ Age + ChestPain + RestBP + Chol + ExAng + Slope
## 
##             Df Sum of Sq    RSS    AIC
## <none>                    95355 1732.2
## - Chol       1    1014.0  96369 1733.3
## - RestBP     1    1054.1  96409 1733.4
## - ChestPain  3    4757.4 100113 1740.6
## - ExAng      1    5310.0 100665 1746.3
## - Slope      1    8761.6 104117 1756.3
## - Age        1   16241.2 111597 1776.9
## 
## Call:
## lm(formula = MaxHR ~ Age + ChestPain + RestBP + Chol + ExAng + 
##     Slope, data = na.omit(dt))
## 
## Coefficients:
##         (Intercept)                  Age  ChestPainnonanginal  
##           187.70592             -0.88515              7.39669  
## ChestPainnontypical     ChestPaintypical               RestBP  
##             9.97711             11.14766              0.11303  
##                Chol                ExAng                Slope  
##             0.03665            -10.31114             -9.35208
## 
## Call:
## lm(formula = MaxHR ~ Age + ChestPain + RestBP + Chol + ExAng + 
##     Slope, data = na.omit(dt))
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -60.947 -12.047   2.099  11.722  44.007 
## 
## Coefficients:
##                      Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         187.70592   10.13348  18.523  < 2e-16 ***
## Age                  -0.88515    0.12638  -7.004 1.76e-11 ***
## ChestPainnonanginal   7.39669    2.73949   2.700  0.00734 ** 
## ChestPainnontypical   9.97711    3.31704   3.008  0.00286 ** 
## ChestPaintypical     11.14766    4.25312   2.621  0.00923 ** 
## RestBP                0.11303    0.06335   1.784  0.07543 .  
## Chol                  0.03665    0.02094   1.750  0.08118 .  
## ExAng               -10.31114    2.57474  -4.005 7.91e-05 ***
## Slope                -9.35208    1.81799  -5.144 4.98e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 18.2 on 288 degrees of freedom
## Multiple R-squared:  0.3879, Adjusted R-squared:  0.3709 
## F-statistic: 22.82 on 8 and 288 DF,  p-value: < 2.2e-16

  1. dữ liệu ở đây là Heart.csv

LS0tCnRpdGxlOiAiSOG7k2kgUXV5IFR1eeG6v24gVMOtbmgiCmF1dGhvcjogIkh1eSBQaHVuZyIKZGF0ZTogIjMvMjAvMjAyMCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgZGZfcHJpbnQ6IGthYmxlCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBudW1iZXJfc2VjdGlvbjogeWVzCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRoZW1lOiBjZXJ1bGVhbgogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXggIAogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwotLS0KCkPDoGkgxJHhurd0IDIgdGjGsCB2aeG7h24gbsOgeSBnacO6cCBtw6xuaCA6CgpgYGAKaW5zdGFsbC5wYWNrYWdlcyjigJxybWFya2Rvd27igJ0pLgpJbnN0YWxsLnBhY2thZ2VzKOKAmHRpbnlkZXjigJkpCnRpbnl0ZXg6Omluc3RhbGxfdGlueXRleCgpCmBgYAoKVMOgaSBsaeG7h3UgUm1hcmtkb3duIDoKWzFdKGh0dHBzOi8vcnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTYvMDMvcm1hcmtkb3duLWNoZWF0c2hlZXQtVmlldG5hbWVzZS5wZGYpClsyXShodHRwczovL3JwdWJzLmNvbS9waGFtZGluaGtoYW5oLzM4MTgyNSkKCkPDtG5nIHRo4bupYyB0b8OhbiA6ClszXShodHRwOi8vcmFuYWx5dGljcy52bi9ibG9nLzIwMTgvMDcvMTgvMjAxOC0wNy0yMS12aWV0LWNvbmctdGh1Yy10b2FuLXRyb25nLXJtYXJrZG93bi8pCls0XShodHRwczovL3d3dy5sYXRleDR0ZWNobmljcy5jb20vKQoKClbhur0gc8ahIMSR4buTIDoKWzVdKGh0dHA6Ly9hc2NpaWZsb3cuY29tLykKCgoKWGluIGNow6BvIG3hu41pIG5nxrDhu51pIMSR4bq/biB24bubaSBiw6BpIGjGsOG7m25nIGThuqtuIHbhu4EgbmfDtG4gbmfhu68gbOG6rXAgdHLDrG5oIFIgY+G7p2EgbcOsbmguIE7hur91IGPDsyB0aOG6r2MgbeG6r2MgZ8OsIGPDoWMgYuG6oW4gY8OzIHRo4buDIGNvbW1lbnQgeHXhu5FuZyBiw6BpIHZp4bq/dCBob+G6t2Mgbmjhuq9uIHRpbiBxdWEgZmFjZWJvb2sgY+G7p2EgbcOsbmggOiBbSHV5eSBIdXl5XShodHRwczovL3d3dy5mYWNlYm9vay5jb20vaGVyby5waHVuZy4xLykuCgpPSyBi4bqvdCDEkeG6p3UgbsOgbywgYsOieSBnaeG7nSBt4buNaSBuZ8aw4budaSBow6N5IHhlbSB2aWRlbyBnaeG7m2kgdGhp4buHdSB24buBICpMaW5lYXIgUmVncmVzc2lvbiogc2F1IMSRw6J5IDogW3ZpZGVvXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PW5rMkNRSVRtX2VvKQoKQ2jDum5nIHRhIHPhur0gbWluaCBob+G6oSBuw7MgYuG6sW5nIGjDrG5oIOG6o25oIDoKCiFbXSgvVXNlcnMvcGh1bmdkdWNodXkvRG93bmxvYWRzL2xpbmVhci1yZWdyZXNzaW9uLnBuZykKCgojIExvYWQgdGjGsCB2aeG7h24gCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGNhcikKbGlicmFyeShIbWlzYykKbGlicmFyeShwc3ljaCkKbGlicmFyeShkcGx5cikKYGBgCgojICDEkOG7jWMgZOG7ryBsaeG7h3UgdOG7qyBmaWxlIC5jc3YgKEhlYXJ0LmNzdikKCkLhu5kgZOG7ryBsaeG7h3UgZ+G7k20gY8OzIDE1IGJp4bq/biwgdHJvbmcgxJHDsyBiaeG6v24ga+G6v3QgcXXhuqMgbMOgICoqQUhEKiogZ+G7k20gMiBnacOhIHRy4buLIGzDoCBgWWVzYCBob+G6t2MgYE5vYCwg4bufIMSRw6J5IHRhIGTDuW5nIGzhu4duaCBgaGVhZCgpYCDEkeG7gyB4ZW0gbeG7mXQgdsOgaSBkw7JuZyDEkeG6p3UgY+G7p2EgYuG7mSBk4buvIGxp4buHdS4KCmBgYHtyfQpkYXRhID0gcmVhZC5jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9wbmh1eS9kYXRhc2V0cy9tYXN0ZXIvaGVhcnRfdWNpL2hlYXJ0LmNzdicpCmF0dGFjaChkYXRhKQpoZWFkKGRhdGEpCmBgYAoKIyMgVOG6oW8gbeG7mXQgYmnhur9uIEdlbmRlciB0xrDGoW5nIOG7qW5nIHbhu5tpIGJp4bq/biBTZXggKDAgOiBGZW1hbGUgLCAxIDogTWFsZSApCmBgYHtyfQpHZW5kZXIgPSBmYWN0b3IoU2V4LCBsZXZlbHMgPSBjKDAsMSksIGxhYmVscyA9IGMoJ0ZlbWFsZScsJ01hbGUnKSkKYGBgCgojIFBow6JuIHTDrWNoIHTGsMahbmcgcXVhbiAKClBow6JuIHTDrWNoIHTGsMahbmcgcXVhbiBjaG8gdGEgYmnhur90IG3hu5FpIGxpw6puIHF1YW4gZ2nhu69hIDIgaGF5IG5oaeG7gXUgYmnhur9uIGzDoCBt4bqhbmggaGF5IHnhur91LiBI4buHIHPhu5EgdMawxqFuZyBxdWFuIMSRxrDhu6NjIGvDvSBoaeG7h3UgbMOgICoqcioqIHbDoCBu4bqxbSB0cm9uZyBraG/huqNuZyAqKi0xIDwgciA8IDEqKi4KQ8O0bmcgdGjhu6ljIHTDrW5oIGjhu4cgc+G7kSB0xrDGoW5nIHF1YW4gZ2nhu69hIGhhaSBiaeG6v24gKngqIHbDoCAqeSogOgokJHJfe3h5fSA9IFxmcmFje1Nfe3h5fX17U197eH1TX3t5fX0gJCQKCiMjIFTGsMahbmcgcXVhbiBt4buZdCBiaeG6v24gCgpUcm9uZyBwaOG6p24gbsOgeSwgbcOsbmggc+G6vSB0w61uaCBo4buHIHPhu5EgdMawxqFuZyBxdWFuIGdp4buvYSAyIGJp4bq/biBgTWF4SFJgIHbDoCBgQWdlYC4gVGEgc+G6vSBkw7luZyBow6BtIGBjb3IudGVzdCgpYAoKYGBge3IgZmlnLmhlaWdodD0gNiwgZmlnLndpZHRoPTd9CnBsb3QoTWF4SFIgfiBBZ2UsIHBjaCA9IDE2ICwgY29sID0gJ3JlZCcpCmBgYApgYGB7cn0KY29yLnRlc3QoTWF4SFIsIEFnZSkKYGBgCgpE4buxYSB2w6BvIGvhur90IHF14bqjIHRhIGPDsyBo4buHIHPhu5EgdMawxqFuZyBxdWFuIGzDoCA6ICotMC4zOSoKCiMjIFTGsMahbmcgcXVhbiDEkWEgYmnhur9uIAoKVMawxqFuZyB04buxIHTGsMahbmcgcXVhbiBt4buZdCBiaeG6v24sIOG7nyB0xrDGoW5nIHF1YW4gxJFhIGJp4bq/biB0YSBkw7luZyBow6BtIGBjb3JyLnRlc3QoKWAgxJHhu4MgdMOtbmguIOG7niDEkcOieSBtw6xuaCBz4bq9IHTDrW5oIHTGsMahbmcgcXVhbiDEkWEgYmnhur9uIGdp4buvYSBjw6FjIGJp4bq/biDEkcaw4bujYyBsxrB1IHRyb25nIGJp4bq/biBgdmFyc2AKCmBgYHtyfQp2YXJzID0gY2JpbmQoTWF4SFIsQWdlLENob2wsUmVzdEJQLE9sZHBlYWssVGhhbCkKY29yci50ZXN0KHZhcnMpCmBgYAoKPiBCaeG7g3UgxJHhu5MgbWluaCBob+G6oSAKCmBgYHtyfQpwYWlycy5wYW5lbHModmFycykKYGBgCgojIEjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIG3hu5l0IGJp4bq/biAKClBoxrDGoW5nIHRyw6xuaCBo4buTaSBxdXkgdHV54bq/biB0w61uaCBjw7MgZOG6oW5nIDogCgo+ICRZID0gXGFscGhhICsgXGJldGEgWF97MH0kCgpUcm9uZyDEkcOzIDoKCiogWSBsw6AgYmnhur9uIG3hu6VjIHRpw6p1ICAKKiAkXGFscGhhJCBsw6AgaW50ZXJjZXB0IAoqICRcYmV0YSQgbMOgIGjhu4cgc+G7kSBo4buTaSBxdXkgCiogJFhfezB9JCBsw6AgYmnhur9uIMSR4bqndSB2w6BvIAoKxJDhu5FpIHbhu5tpIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIHRyb25nIFIsIG3DrG5oIHPhur0gZOG7rSBk4bulbmcgaMOgbSBgbG0oKWAgxJHhu4MgxJHGsGEgY8OhYyBiaeG6v24gY+G6p24geMOieSBk4buxbmcgbcO0IGjDrG5oIHbDoCBkw7luZyBow6BtIGBzdW1tYXJ5KClgIMSR4buDIHhlbSB0w7NtIHThuq90IGPDoWMgdGjDtG5nIHPhu5EgdHJvbmcgbcO0IGjDrG5oLgoKIyMgSOG7k2kgcXV5IHR1eeG6v24gdMOtbmggduG7m2kgYmnhur9uIGxpw6puIHThu6VjIAoKCmBgYHtyIGV2YWwgPSBUUlVFfQpyZXMgPSBsbShNYXhIUiB+IEFnZSkKc3VtbWFyeShyZXMpCmBgYAoKCiMjIyBW4bq9IGJp4buDdSDEkeG7kyAKYGBge3J9CnBsb3QoTWF4SFIgfiBBZ2UsIGNvbCA9ICdibHVlJywgcGNoID0gMTYpCmFibGluZShyZXMsIGNvbCA9IDIpCmBgYAoKIyMjIFTDrW5oIHleCgpUYSBkw7luZyBow6BtIGBwcmVkaWN0KClgIMSR4buDIHTDrW5oIGdpw6EgdHLhu4sgeSBk4buxIMSRb8OhbgoKYGBge3J9CmhlYWQocHJlZGljdChyZXMpKQpgYGAKCuG7niDEkcOieSB0YSBjw7MgdGjhu4MgdMOzbSB04bqvdCBuaMawIHNhdToKCnwgJFhfMCQgfCAkXGhhdHtZfSQgfAp8Oi0tLS0tOnw6LS0tLS0tLS0tOnwKfDYzICAgICB8MTQxLjAxICAgICB8Cnw2NyAgICAgfDEzNy4wOCAgICAgfAp8NjcgICAgIHwxMzcuMDggICAgIHwKfDM3ICAgICB8MTY2Ljk4ICAgICB8Cnw0MSAgICAgfDE2My4wMCAgICAgfAoKIyMjIFBow6JuIHTDrWNoIHBoxrDGoW5nIHNhaSAKYGBge3J9CmFvdiA9IGFub3ZhKHJlcykKYW92IApgYGAKCiMjIyBQaMOibiB0w61jaCByZXNpZHVhbCAKCiMjIyBQaMOibiBwaOG7kWkgY2h14bqpbgoKLSBUw61uaCB5IC0geV4KYGBge3J9Cm0gPSByZXNpZChyZXMpCmhlYWQobSkKYGBgCgotIEtp4buDbSDEkeG7i25oIHBow6JuIHBo4buRaSBjaHXhuqluCmBgYHtyfQpoaXN0KG0pCnFxbm9ybShtLCBwY2ggPSAxNikKcXFsaW5lKG0sIGNvbCA9IDIsIGx3ZCA9IDMpCmBgYAoKYGBge3J9CnNoYXBpcm8udGVzdChtKQpgYGAKCi0gVHJ1bmcgYsOsbmggYuG6sW5nIDAKYGBge3J9Cm1lYW4obSkKYGBgCgotIEtp4buDbSB0cmEgcGjGsMahbmcgc2FpCgpgYGB7cn0KbmN2VGVzdChyZXMpCnNwcmVhZExldmVsUGxvdChyZXMsIHBjaCA9IDE2KQpgYGAKCiMjIEjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIHbhu5tpIGJp4bq/biBwaMOibiBuaMOzbSAKYGBge3J9CnJlczEgPSBsbShNYXhIUiB+IEdlbmRlcikKc3VtbWFyeShyZXMxKQpgYGAKCgpgYGB7cn0KYm94cGxvdChNYXhIUiB+IEdlbmRlciwgY29sID0gYygncmVkJywnYmx1ZScpKQpgYGAKCgoKIyBI4buTaSBxdXkgdHV54bq/biB0w61uaCDEkWEgYmnhur9uIApgYGB7cn0KcmVzMiA9IGxtKE1heEhSIH4gUmVzdEJQICsgQWdlICsgVGhhbCkKc3VtbWFyeShyZXMyKQpgYGAKCgojIFjDonkgZOG7sW5nIG3DtCBow6xuaCB0aOG7kW5nIGvDqiB04buRaSDGsHUgCgoqIFjhu60gbMO9IGThu68gbGnhu4d1W14xXSAKCmBgYHtyfQpkdCA9IHNlbGVjdChkYXRhLCBjKDI6MTQpKQpoZWFkKGR0KQpgYGAKCiogWMOieSBk4buxbmcgbcO0IGjDrG5oCgpgYGB7cn0KbW9kZWwgPSBsbShNYXhIUiB+IC4sIGRhdGEgPSBuYS5vbWl0KGR0KSkKYGBgCgoqIENo4buNbiBtw7QgaMOsbmggdOG7kWkgxrB1IAoKYGBge3J9Cm9wID0gc3RlcChtb2RlbCkgCm9wCmBgYAoKYGBge3J9CnN1bW1hcnkob3ApCmBgYAoKClteMV06IGThu68gbGnhu4d1IOG7nyDEkcOieSBsw6AgSGVhcnQuY3N2CgoKCg==