Notebook Instructions


Load Packages in R/RStudio

We are going to use tidyverse a collection of R packages designed for data science.

Loading required package: tidyverse
── Attaching packages ────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 2.2.1     ✔ purrr   0.2.4
✔ tibble  1.4.2     ✔ dplyr   0.7.4
✔ tidyr   0.7.2     ✔ stringr 1.2.0
✔ readr   1.1.1     ✔ forcats 0.2.0
── Conflicts ───────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
Loading required package: gridExtra
there is no package called ‘gridExtra’also installing the dependencies ‘praise’, ‘withr’, ‘egg’, ‘testthat’

trying URL 'https://cran.rstudio.com/bin/macosx/el-capitan/contrib/3.4/praise_1.0.0.tgz'
Content type 'application/x-gzip' length 14617 bytes (14 KB)
==================================================
downloaded 14 KB

trying URL 'https://cran.rstudio.com/bin/macosx/el-capitan/contrib/3.4/withr_2.1.1.tgz'
Content type 'application/x-gzip' length 118461 bytes (115 KB)
==================================================
downloaded 115 KB

trying URL 'https://cran.rstudio.com/bin/macosx/el-capitan/contrib/3.4/egg_0.2.0.tgz'
Content type 'application/x-gzip' length 1266217 bytes (1.2 MB)
==================================================
downloaded 1.2 MB

trying URL 'https://cran.rstudio.com/bin/macosx/el-capitan/contrib/3.4/testthat_2.0.0.tgz'
Content type 'application/x-gzip' length 1640399 bytes (1.6 MB)
==================================================
downloaded 1.6 MB

trying URL 'https://cran.rstudio.com/bin/macosx/el-capitan/contrib/3.4/gridExtra_2.3.tgz'
Content type 'application/x-gzip' length 1077959 bytes (1.0 MB)
==================================================
downloaded 1.0 MB

The downloaded binary packages are in
    /var/folders/5x/kl6y2ft90fgg2x8wnq5khk8m0000gn/T//RtmpujWa0M/downloaded_packages

Attaching package: ‘gridExtra’

The following object is masked from ‘package:dplyr’:

    combine

Task 1: Quantitative Analysis


1A) Read the csv file into R Studio and display the dataset.

  • Name your dataset ‘mydata’ so it easy to work with.

  • Commands: read_csv() head() max() min() var() sd()

Extract the assigned features (columns) to perform some analytics.

mydata = read_csv(file="data/Advertising.csv")
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  X1 = col_integer(),
  TV = col_double(),
  radio = col_double(),
  newspaper = col_double(),
  sales = col_double()
)
head(mydata)

Change the variable name “X1” to case_number using the function rename()

  • mydata <- rename(mydata, “NEW_VAR_NAME” = “OLD_VAR_NAME”)
mydata = rename(mydata, "case_number" = "X1")
mydata

1B) Find the range ( difference between min and max ), min, max, standard deviation and variance for each assigned feature ( Use separate chunks for each feature ). Compare each feature and note any significant differences

TV

#variable_max
maxTV = max(mydata$TV)
maxTV
[1] 296.4
#variable_min
minTV = min(mydata$TV)
minTV
[1] 0.7
#variable_Range max-min
rangeTV = sum(maxTV - minTV)
rangeTV
[1] 295.7
#variable_mean 
meanTV = mean(mydata$TV)
meanTV
[1] 147.0425
#variable_sd Standard Deviation
sdTV = sd(mydata$TV)
sdTV
[1] 85.85424
#variable_variance
varianceTV = var(mydata$TV)
varianceTV
[1] 7370.95

RADIO

#variable_max
maxradio = max(mydata$radio)
maxradio
[1] 49.6
#variable_min
minradio = min(mydata$radio)
minradio
[1] 0
#variable_Range max-min
rangeradio = sum(maxradio - minradio)
rangeradio
[1] 49.6
#variable_mean 
meanradio = mean(mydata$radio)
meanradio
[1] 23.264
#variable_sd Standard Deviation
sdradio = sd(mydata$radio)
sdradio
[1] 14.84681
#variable_variance
varianceradio = var(mydata$radio)
varianceradio
[1] 220.4277

NEWSPAPER

#variable_max
maxnewspaper = max(mydata$newspaper)
maxnewspaper
[1] 114
#variable_min
minnewspaper = min(mydata$newspaper)
minnewspaper
[1] 0.3
#variable_Range max-min
rangenewspaper = sum(maxradio - minnewspaper)
rangenewspaper
[1] 49.3
#variable_mean 
meannewspaper = mean(mydata$newspaper)
meannewspaper
[1] 30.554
#variable_sd Standard Deviation
sdnewspaper = sd(mydata$newspaper)
sdnewspaper
[1] 21.77862
#variable_variance
variancenewspaper = var(mydata$newspaper)
variancenewspaper
[1] 474.3083

SALES

#variable_max
maxsales = max(mydata$sales)
maxsales
[1] 27
#variable_min
minsales = min(mydata$sales)
minsales
[1] 1.6
#variable_Range max-min
rangesales = sum(maxradio - minsales)
rangesales
[1] 48
#variable_mean 
meansales = mean(mydata$sales)
meansales
[1] 14.0225
#variable_sd Standard Deviation
sdsales = sd(mydata$sales)
sdsales
[1] 5.217457
#variable_variance
variancesales = var(mydata$sales)
variancesales
[1] 27.22185

1C) Use the summary() function on all the dataset to give you a general description of the data. Note any differences between features.

summary(mydata)
  case_number           TV             radio          newspaper     
 Min.   :  1.00   Min.   :  0.70   Min.   : 0.000   Min.   :  0.30  
 1st Qu.: 50.75   1st Qu.: 74.38   1st Qu.: 9.975   1st Qu.: 12.75  
 Median :100.50   Median :149.75   Median :22.900   Median : 25.75  
 Mean   :100.50   Mean   :147.04   Mean   :23.264   Mean   : 30.55  
 3rd Qu.:150.25   3rd Qu.:218.82   3rd Qu.:36.525   3rd Qu.: 45.10  
 Max.   :200.00   Max.   :296.40   Max.   :49.600   Max.   :114.00  
     sales      
 Min.   : 1.60  
 1st Qu.:10.38  
 Median :12.90  
 Mean   :14.02  
 3rd Qu.:17.40  
 Max.   :27.00  

Are there any outliers, if not explain the lack of outliers? if any explain what the outliers represent and how many records are outliers? ( Use code from notebook-03 to find outliers)

lowerquantileTV = quantile(mydata$TV)[2]
upperquantileTV = quantile(mydata$TV)[4]
lowerquantileradio = quantile(mydata$radio)[2]
upperquantileradio = quantile(mydata$radio)[4]
lowerquantilenewspaper = quantile(mydata$newspaper)[2]
upperquantilenewspaper = quantile(mydata$newspaper)[4]
lowerquantilesales = quantile(mydata$sales)[2]
upperquantilesales = quantile(mydata$sales)[4]

IQR calculations

iqrTV = upperquantileTV - lowerquantileTV
iqrradio = upperquantileradio - lowerquantileradio
iqrnewspaper = upperquantilenewspaper - lowerquantilenewspaper
iqrsales = upperquantilesales - lowerquantilesales

Upper Threshold

UTTV = (iqrTV * 1.5) + upperquantileTV
UTradio = (iqrradio * 1.5) + upperquantileradio
UTnewspaper = (iqrnewspaper * 1.5) + upperquantilenewspaper
UTsales = (iqrsales * 1.5) + upperquantilesales

LOWER THRESHOLD

LTTV = lowerquantileTV - (iqrTV * 1.5)
LTradio = lowerquantileradio - (iqrradio * 1.5)
LTnewspaper = lowerquantilenewspaper - (iqrnewspaper * 1.5)
LTsales = lowerquantilesales - (iqrsales * 1.5)
count(mydata[mydata$TV > UTTV, ])
count(mydata[mydata$TV < LTTV, ])
count(mydata[mydata$radio > UTradio, ])
count(mydata[mydata$radio < LTradio, ])
count(mydata[mydata$newspaper > UTnewspaper, ])
count(mydata[mydata$newspaper < LTnewspaper, ])
count(mydata[mydata$sales > UTsales, ])
count(mydata[mydata$sales < LTsales, ])

There are no outliers for TV, radio or sales. However, there are two outliers in newspaper that exceed the upper threshold. This means that the values of these two data points are significantly different from all the other points in this data.

1D) Write a general description of the dataset using the statistics found in the steps above. Use the min,max range to compare the features, note any significant differences.

The mean for TV is 147.04 and the standard deviation is 85.85. The max value for TV is 296.4 and the minimum value is 0.7. The mean for radio is 23.26, the standard deviation is 14.84, the max is 49.6 and the min value is 0. For newspaper, the mean is 30.55, the standard deviation is 21.77, the max is 114 and the min is 0.3. Lastly, the mean for sales is 14.02, the standard deviation is 5.21, the max is 27 and the min is 1.6. This data shows that on average the most money spent on advertising went to TV and the least money spent on advertising went to sales. This makes sense in most applications of advertising, because TV ads tend to be one of the most expensive forms of advertising.


Task 2: Qualitative Analysis


2A) Plot all the assigned features as y-axis for x-axis use case_number. Use the given commands to create each plot and create a grid to plot all features Note any trends/patters in the data

  • Commands: VARIABLE_plot <- ggplot(data = mydata, aes(x = VARIABLE, y = VARIABLE)) + geom_point()
  • Commands: grid.arrange(VARIABLE_plot1, VARIABLE_plot2, VARIABLE_plot3, VARIABLE_plot4, ncol=2)
#grid.arrange(VARIABLE_plot1, VARIABLE_plot2, VARIABLE_plot3, VARIABLE_plot4, ncol=2)
TV_plot <- ggplot(data = mydata, aes(x = case_number, y = TV)) + geom_point()
radio_plot <- ggplot(data = mydata, aes(x = case_number, y = radio)) + geom_point()
newspaper_plot <- ggplot(data = mydata, aes(x = case_number, y = newspaper)) + geom_point()
sales_plot <- ggplot(data = mydata, aes(x = case_number, y = sales)) + geom_point()
grid.arrange(sales_plot, TV_plot, radio_plot, newspaper_plot, ncol=2)

There does not seem to be an identifiable trend in any of these scatterplots.

  • When looking at these plots it is hard to see a particular trend.
  • One way to observe any possible trend in the sales data would be to re-order the data from low to high.
  • The 200 months observations are in no particular chronological time sequence.
  • The case numbers are independent sequentially generated numbers. Since each case is independent, we can reorder them.

2B) Re-order sales from low to high, and save re-ordered data in a new set. As sales data is re-reorded associated other column fields follow.

  • Commands: newdata <- mydata[ order(mydata$VARIABLE), ]
# Extract case_number from the newdata
newdata = mydata[ order(mydata$sales), ]
case_number <- newdata$case_number
head(newdata)

Extract the variables from the new data

# new_VARIABLE = newdata$VARIABLE
new_TV = newdata$TV
new_radio = newdata$radio
new_newspaper = newdata$newspaper
new_sales = newdata$sales

Task 3: Standardized Z-Value


3A) Create a histogram of the assigned feature z-scores. Describe the output note any relevant values.

  • Command: z_score = ( VARIABLE - mean(VARIABLE) ) / sd(VARIABLE)
  • Commands: qplot( x = VARIABLE ,geom=“histogram”, binwidth = 0.3)
z_scoreTV = (mydata$TV - meanTV) / sdTV
z_scoreradio = (mydata$radio - meanradio) / sdradio
z_scorenewspaper = (mydata$newspaper - meannewspaper) / sdnewspaper
z_scoresales = (mydata$sales - meansales) / sdsales
qplot( x = z_scoreTV ,geom="histogram", binwidth = 0.3)

qplot( x = z_scoreradio ,geom="histogram", binwidth = 0.3)

qplot( x = z_scorenewspaper ,geom="histogram", binwidth = 0.3)

qplot( x = z_scoresales ,geom="histogram", binwidth = 0.3)

The sales histogram appears the closest to resembling a normal distribution while newspaper is positively skewed. This is likely because of the outliers in the newspaper data.

3B) Given a sales value of $26700, calculate the corresponding z-value or z-score.

  • Command: z_score = ( VARIABLE - mean(VARIABLE) ) / sd(VARIABLE)
z_scoresalescalculation = ( 26.7 - mean(mydata$sales) ) / sd(mydata$sales)
z_scoresalescalculation
[1] 2.429824

3C) Based on the z-value, how would you rate a $26700 sales value: poor, average, good, or very good performance? Explain your logic.

I would say that a z-score of 2.43 resembles a good performace. It is a positive number and it is about two standard deviations above the mean which shows that sales are above average and there is a good performance.

LS0tCnRpdGxlOiAiRGVzY3JpcHRpdmUgQW5hbHl0aWNzIgphdXRob3I6ICJDYW1lcm9uIEdlcmhhcnQiCmRhdGU6ICJGcmVicnVhcnkgMjcsIDIwMTgiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CnN1YnRpdGxlOiBDTUUgR3JvdXAgRm91bmRhdGlvbiBCdXNpbmVzcyBBbmFseXRpY3MgTGFiCi0tLQoKLS0tLS0tLS0tLS0tLQoKIyMgTm90ZWJvb2sgSW5zdHJ1Y3Rpb25zCgotLS0tLS0tLS0tLS0tCgoqIEZvciB5b3VyIGFzc2lnbm1lbnQgeW91IG1heSBiZSB1c2luZyBkaWZmZXJlbnQgZGF0YXNldCB0aGFuIHdoYXQgaXMgaW5jbHVkZWQgaGVyZS4gCgoqIEFsd2F5cyByZWFkIGNhcmVmdWxseSB0aGUgaW5zdHJ1Y3Rpb25zIG9uIFNha2FpLiAgCgoqIFRhc2tzL3F1ZXN0aW9ucyB0byBiZSBjb21wbGV0ZWQvYW5zd2VyZWQgYXJlIGhpZ2hsaWdodGVkIGluIGxhcmdlciBib2xkZWQgZm9udHMgYW5kIG51bWJlcmVkIGFjY29yZGluZyB0byB0aGVpciBzZWN0aW9uLgoKIyMjIExvYWQgUGFja2FnZXMgaW4gUi9SU3R1ZGlvIAoKV2UgYXJlIGdvaW5nIHRvIHVzZSB0aWR5dmVyc2UgYSBjb2xsZWN0aW9uIG9mIFIgcGFja2FnZXMgZGVzaWduZWQgZm9yIGRhdGEgc2NpZW5jZS4gCgoqIEluZm86IGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvCgpgYGB7ciwgZWNobz1GQUxTRX0KCiMgSGVyZSB3ZSBhcmUgY2hlY2tpbmcgaWYgdGhlIHBhY2thZ2UgaXMgaW5zdGFsbGVkCmlmKCFyZXF1aXJlKHRpZHl2ZXJzZSkpewogIAogICMgSWYgdGhlIHBhY2thZ2UgaXMgbm90IGluIHRoZSBzeXN0ZW0gdGhlbiBpdCB3aWxsIGJlIGluc3RhbGwKICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQogIAogICMgSGVyZSB3ZSBhcmUgbG9hZGluZyB0aGUgcGFja2FnZQogIGxpYnJhcnkodGlkeXZlcnNlKQp9CgppZighcmVxdWlyZShncmlkRXh0cmEpKXsKICAKICAjIElmIHRoZSBwYWNrYWdlIGlzIG5vdCBpbiB0aGUgc3lzdGVtIHRoZW4gaXQgd2lsbCBiZSBpbnN0YWxsCiAgaW5zdGFsbC5wYWNrYWdlcygiZ3JpZEV4dHJhIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkKICAKICAjIEhlcmUgd2UgYXJlIGxvYWRpbmcgdGhlIHBhY2thZ2UKICBsaWJyYXJ5KGdyaWRFeHRyYSkKfQoKYGBgCgotLS0tLS0tLS0tLS0tCgojIyBUYXNrIDE6IFF1YW50aXRhdGl2ZSBBbmFseXNpcwoKLS0tLS0tLS0tLS0tLQoKIyMjIDFBKSBSZWFkIHRoZSBjc3YgZmlsZSBpbnRvIFIgU3R1ZGlvIGFuZCBkaXNwbGF5IHRoZSBkYXRhc2V0LiAKCiogTmFtZSB5b3VyIGRhdGFzZXQgJ215ZGF0YScgc28gaXQgZWFzeSB0byB3b3JrIHdpdGguCgoqIENvbW1hbmRzOiByZWFkX2NzdigpIGhlYWQoKSBtYXgoKSBtaW4oKSB2YXIoKSBzZCgpCgojIyMjIEV4dHJhY3QgdGhlIGFzc2lnbmVkIGZlYXR1cmVzIChjb2x1bW5zKSB0byBwZXJmb3JtIHNvbWUgYW5hbHl0aWNzLiAKCmBgYHtyfSAKbXlkYXRhID0gcmVhZF9jc3YoZmlsZT0iZGF0YS9BZHZlcnRpc2luZy5jc3YiKQpoZWFkKG15ZGF0YSkKYGBgCgojIyMjIENoYW5nZSB0aGUgdmFyaWFibGUgbmFtZSAiWDEiIHRvIGNhc2VfbnVtYmVyIHVzaW5nIHRoZSBmdW5jdGlvbiByZW5hbWUoKQoKKiBteWRhdGEgPC0gcmVuYW1lKG15ZGF0YSwgIk5FV19WQVJfTkFNRSIgPSAiT0xEX1ZBUl9OQU1FIikKCmBgYHtyfSAKbXlkYXRhID0gcmVuYW1lKG15ZGF0YSwgImNhc2VfbnVtYmVyIiA9ICJYMSIpCm15ZGF0YQpgYGAKCiMjIyAxQikgRmluZCB0aGUgcmFuZ2UgKCBkaWZmZXJlbmNlIGJldHdlZW4gbWluIGFuZCBtYXggKSwgbWluLCBtYXgsIHN0YW5kYXJkIGRldmlhdGlvbiBhbmQgdmFyaWFuY2UgZm9yIGVhY2ggYXNzaWduZWQgZmVhdHVyZSAoIFVzZSBzZXBhcmF0ZSBjaHVua3MgZm9yIGVhY2ggZmVhdHVyZSApLiBDb21wYXJlIGVhY2ggZmVhdHVyZSBhbmQgbm90ZSBhbnkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMKCioqVFYqKgpgYGB7cn0KCiN2YXJpYWJsZV9tYXgKbWF4VFYgPSBtYXgobXlkYXRhJFRWKQptYXhUVgoKI3ZhcmlhYmxlX21pbgptaW5UViA9IG1pbihteWRhdGEkVFYpCm1pblRWCgojdmFyaWFibGVfUmFuZ2UgbWF4LW1pbgpyYW5nZVRWID0gc3VtKG1heFRWIC0gbWluVFYpCnJhbmdlVFYKCiN2YXJpYWJsZV9tZWFuIAptZWFuVFYgPSBtZWFuKG15ZGF0YSRUVikKbWVhblRWCgojdmFyaWFibGVfc2QgU3RhbmRhcmQgRGV2aWF0aW9uCnNkVFYgPSBzZChteWRhdGEkVFYpCnNkVFYKCiN2YXJpYWJsZV92YXJpYW5jZQp2YXJpYW5jZVRWID0gdmFyKG15ZGF0YSRUVikKdmFyaWFuY2VUVgoKYGBgCgoqKlJBRElPKioKYGBge3J9CgojdmFyaWFibGVfbWF4Cm1heHJhZGlvID0gbWF4KG15ZGF0YSRyYWRpbykKbWF4cmFkaW8KCiN2YXJpYWJsZV9taW4KbWlucmFkaW8gPSBtaW4obXlkYXRhJHJhZGlvKQptaW5yYWRpbwoKI3ZhcmlhYmxlX1JhbmdlIG1heC1taW4KcmFuZ2VyYWRpbyA9IHN1bShtYXhyYWRpbyAtIG1pbnJhZGlvKQpyYW5nZXJhZGlvCgojdmFyaWFibGVfbWVhbiAKbWVhbnJhZGlvID0gbWVhbihteWRhdGEkcmFkaW8pCm1lYW5yYWRpbwoKI3ZhcmlhYmxlX3NkIFN0YW5kYXJkIERldmlhdGlvbgpzZHJhZGlvID0gc2QobXlkYXRhJHJhZGlvKQpzZHJhZGlvCgojdmFyaWFibGVfdmFyaWFuY2UKdmFyaWFuY2VyYWRpbyA9IHZhcihteWRhdGEkcmFkaW8pCnZhcmlhbmNlcmFkaW8KCmBgYAoKKipORVdTUEFQRVIqKgpgYGB7cn0KCiN2YXJpYWJsZV9tYXgKbWF4bmV3c3BhcGVyID0gbWF4KG15ZGF0YSRuZXdzcGFwZXIpCm1heG5ld3NwYXBlcgoKI3ZhcmlhYmxlX21pbgptaW5uZXdzcGFwZXIgPSBtaW4obXlkYXRhJG5ld3NwYXBlcikKbWlubmV3c3BhcGVyCgojdmFyaWFibGVfUmFuZ2UgbWF4LW1pbgpyYW5nZW5ld3NwYXBlciA9IHN1bShtYXhyYWRpbyAtIG1pbm5ld3NwYXBlcikKcmFuZ2VuZXdzcGFwZXIKCiN2YXJpYWJsZV9tZWFuIAptZWFubmV3c3BhcGVyID0gbWVhbihteWRhdGEkbmV3c3BhcGVyKQptZWFubmV3c3BhcGVyCgojdmFyaWFibGVfc2QgU3RhbmRhcmQgRGV2aWF0aW9uCnNkbmV3c3BhcGVyID0gc2QobXlkYXRhJG5ld3NwYXBlcikKc2RuZXdzcGFwZXIKCiN2YXJpYWJsZV92YXJpYW5jZQp2YXJpYW5jZW5ld3NwYXBlciA9IHZhcihteWRhdGEkbmV3c3BhcGVyKQp2YXJpYW5jZW5ld3NwYXBlcgoKYGBgCgoqKlNBTEVTKioKYGBge3J9CgojdmFyaWFibGVfbWF4Cm1heHNhbGVzID0gbWF4KG15ZGF0YSRzYWxlcykKbWF4c2FsZXMKCiN2YXJpYWJsZV9taW4KbWluc2FsZXMgPSBtaW4obXlkYXRhJHNhbGVzKQptaW5zYWxlcwoKI3ZhcmlhYmxlX1JhbmdlIG1heC1taW4KcmFuZ2VzYWxlcyA9IHN1bShtYXhyYWRpbyAtIG1pbnNhbGVzKQpyYW5nZXNhbGVzCgojdmFyaWFibGVfbWVhbiAKbWVhbnNhbGVzID0gbWVhbihteWRhdGEkc2FsZXMpCm1lYW5zYWxlcwoKI3ZhcmlhYmxlX3NkIFN0YW5kYXJkIERldmlhdGlvbgpzZHNhbGVzID0gc2QobXlkYXRhJHNhbGVzKQpzZHNhbGVzCgojdmFyaWFibGVfdmFyaWFuY2UKdmFyaWFuY2VzYWxlcyA9IHZhcihteWRhdGEkc2FsZXMpCnZhcmlhbmNlc2FsZXMKCmBgYAoKIyMjIDFDKSBVc2UgdGhlIHN1bW1hcnkoKSBmdW5jdGlvbiBvbiBhbGwgdGhlIGRhdGFzZXQgdG8gZ2l2ZSB5b3UgYSBnZW5lcmFsIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhLiBOb3RlIGFueSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGZlYXR1cmVzLgoKYGBge3J9CnN1bW1hcnkobXlkYXRhKQpgYGAKCiMjIyMgQXJlIHRoZXJlIGFueSBvdXRsaWVycywgaWYgbm90IGV4cGxhaW4gdGhlIGxhY2sgb2Ygb3V0bGllcnM/IGlmIGFueSBleHBsYWluIHdoYXQgdGhlIG91dGxpZXJzIHJlcHJlc2VudCBhbmQgaG93IG1hbnkgcmVjb3JkcyBhcmUgb3V0bGllcnM/ICggVXNlIGNvZGUgZnJvbSBub3RlYm9vay0wMyB0byBmaW5kIG91dGxpZXJzKSAKCmBgYHtyfQpsb3dlcnF1YW50aWxlVFYgPSBxdWFudGlsZShteWRhdGEkVFYpWzJdCnVwcGVycXVhbnRpbGVUViA9IHF1YW50aWxlKG15ZGF0YSRUVilbNF0KCmxvd2VycXVhbnRpbGVyYWRpbyA9IHF1YW50aWxlKG15ZGF0YSRyYWRpbylbMl0KdXBwZXJxdWFudGlsZXJhZGlvID0gcXVhbnRpbGUobXlkYXRhJHJhZGlvKVs0XQoKbG93ZXJxdWFudGlsZW5ld3NwYXBlciA9IHF1YW50aWxlKG15ZGF0YSRuZXdzcGFwZXIpWzJdCnVwcGVycXVhbnRpbGVuZXdzcGFwZXIgPSBxdWFudGlsZShteWRhdGEkbmV3c3BhcGVyKVs0XQoKbG93ZXJxdWFudGlsZXNhbGVzID0gcXVhbnRpbGUobXlkYXRhJHNhbGVzKVsyXQp1cHBlcnF1YW50aWxlc2FsZXMgPSBxdWFudGlsZShteWRhdGEkc2FsZXMpWzRdCmBgYAoKSVFSIGNhbGN1bGF0aW9ucwpgYGB7cn0KaXFyVFYgPSB1cHBlcnF1YW50aWxlVFYgLSBsb3dlcnF1YW50aWxlVFYKCmlxcnJhZGlvID0gdXBwZXJxdWFudGlsZXJhZGlvIC0gbG93ZXJxdWFudGlsZXJhZGlvCgppcXJuZXdzcGFwZXIgPSB1cHBlcnF1YW50aWxlbmV3c3BhcGVyIC0gbG93ZXJxdWFudGlsZW5ld3NwYXBlcgoKaXFyc2FsZXMgPSB1cHBlcnF1YW50aWxlc2FsZXMgLSBsb3dlcnF1YW50aWxlc2FsZXMKYGBgCgpVcHBlciBUaHJlc2hvbGQgCmBgYHtyfQpVVFRWID0gKGlxclRWICogMS41KSArIHVwcGVycXVhbnRpbGVUVgoKVVRyYWRpbyA9IChpcXJyYWRpbyAqIDEuNSkgKyB1cHBlcnF1YW50aWxlcmFkaW8KClVUbmV3c3BhcGVyID0gKGlxcm5ld3NwYXBlciAqIDEuNSkgKyB1cHBlcnF1YW50aWxlbmV3c3BhcGVyCgpVVHNhbGVzID0gKGlxcnNhbGVzICogMS41KSArIHVwcGVycXVhbnRpbGVzYWxlcwpgYGAKCkxPV0VSIFRIUkVTSE9MRApgYGB7cn0KTFRUViA9IGxvd2VycXVhbnRpbGVUViAtIChpcXJUViAqIDEuNSkKCkxUcmFkaW8gPSBsb3dlcnF1YW50aWxlcmFkaW8gLSAoaXFycmFkaW8gKiAxLjUpCgpMVG5ld3NwYXBlciA9IGxvd2VycXVhbnRpbGVuZXdzcGFwZXIgLSAoaXFybmV3c3BhcGVyICogMS41KQoKTFRzYWxlcyA9IGxvd2VycXVhbnRpbGVzYWxlcyAtIChpcXJzYWxlcyAqIDEuNSkKYGBgCgpgYGB7cn0KY291bnQobXlkYXRhW215ZGF0YSRUViA+IFVUVFYsIF0pCmNvdW50KG15ZGF0YVtteWRhdGEkVFYgPCBMVFRWLCBdKQpgYGAKCmBgYHtyfQpjb3VudChteWRhdGFbbXlkYXRhJHJhZGlvID4gVVRyYWRpbywgXSkKY291bnQobXlkYXRhW215ZGF0YSRyYWRpbyA8IExUcmFkaW8sIF0pCmBgYAoKYGBge3J9CmNvdW50KG15ZGF0YVtteWRhdGEkbmV3c3BhcGVyID4gVVRuZXdzcGFwZXIsIF0pCmNvdW50KG15ZGF0YVtteWRhdGEkbmV3c3BhcGVyIDwgTFRuZXdzcGFwZXIsIF0pCmBgYAoKYGBge3J9CmNvdW50KG15ZGF0YVtteWRhdGEkc2FsZXMgPiBVVHNhbGVzLCBdKQpjb3VudChteWRhdGFbbXlkYXRhJHNhbGVzIDwgTFRzYWxlcywgXSkKYGBgCgpUaGVyZSBhcmUgbm8gb3V0bGllcnMgZm9yIFRWLCByYWRpbyBvciBzYWxlcy4gSG93ZXZlciwgdGhlcmUgYXJlIHR3byBvdXRsaWVycyBpbiBuZXdzcGFwZXIgdGhhdCBleGNlZWQgdGhlIHVwcGVyIHRocmVzaG9sZC4gVGhpcyBtZWFucyB0aGF0IHRoZSB2YWx1ZXMgb2YgdGhlc2UgdHdvIGRhdGEgcG9pbnRzIGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIGFsbCB0aGUgb3RoZXIgcG9pbnRzIGluIHRoaXMgZGF0YS4gCgoKIyMjIDFEKSBXcml0ZSBhIGdlbmVyYWwgZGVzY3JpcHRpb24gb2YgdGhlIGRhdGFzZXQgdXNpbmcgdGhlIHN0YXRpc3RpY3MgZm91bmQgaW4gdGhlIHN0ZXBzIGFib3ZlLiBVc2UgdGhlIG1pbixtYXggcmFuZ2UgdG8gY29tcGFyZSB0aGUgZmVhdHVyZXMsIG5vdGUgYW55IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzLgpUaGUgbWVhbiBmb3IgVFYgaXMgMTQ3LjA0IGFuZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIDg1Ljg1LiBUaGUgbWF4IHZhbHVlIGZvciBUViBpcyAyOTYuNCBhbmQgdGhlIG1pbmltdW0gdmFsdWUgaXMgMC43LiBUaGUgbWVhbiBmb3IgcmFkaW8gaXMgMjMuMjYsIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gaXMgMTQuODQsIHRoZSBtYXggaXMgNDkuNiBhbmQgdGhlIG1pbiB2YWx1ZSBpcyAwLiBGb3IgbmV3c3BhcGVyLCB0aGUgbWVhbiBpcyAzMC41NSwgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBpcyAyMS43NywgdGhlIG1heCBpcyAxMTQgYW5kIHRoZSBtaW4gaXMgMC4zLiBMYXN0bHksIHRoZSBtZWFuIGZvciBzYWxlcyBpcyAxNC4wMiwgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBpcyA1LjIxLCB0aGUgbWF4IGlzIDI3IGFuZCB0aGUgbWluIGlzIDEuNi4gVGhpcyBkYXRhIHNob3dzIHRoYXQgb24gYXZlcmFnZSB0aGUgbW9zdCBtb25leSBzcGVudCBvbiBhZHZlcnRpc2luZyB3ZW50IHRvIFRWIGFuZCB0aGUgbGVhc3QgbW9uZXkgc3BlbnQgb24gYWR2ZXJ0aXNpbmcgd2VudCB0byBzYWxlcy4gVGhpcyBtYWtlcyBzZW5zZSBpbiBtb3N0IGFwcGxpY2F0aW9ucyBvZiBhZHZlcnRpc2luZywgYmVjYXVzZSBUViBhZHMgdGVuZCB0byBiZSBvbmUgb2YgdGhlIG1vc3QgZXhwZW5zaXZlIGZvcm1zIG9mIGFkdmVydGlzaW5nLiAKCi0tLS0tLS0tLS0tLS0KCiMjIFRhc2sgMjogUXVhbGl0YXRpdmUgQW5hbHlzaXMKCi0tLS0tLS0tLS0tLS0KCgojIyMgMkEpIFBsb3QgYWxsIHRoZSBhc3NpZ25lZCBmZWF0dXJlcyBhcyB5LWF4aXMgZm9yIHgtYXhpcyB1c2UgY2FzZV9udW1iZXIuIFVzZSB0aGUgZ2l2ZW4gY29tbWFuZHMgdG8gY3JlYXRlIGVhY2ggcGxvdCBhbmQgY3JlYXRlIGEgZ3JpZCB0byBwbG90IGFsbCBmZWF0dXJlcyBOb3RlIGFueSB0cmVuZHMvcGF0dGVycyBpbiB0aGUgZGF0YQoKKiBDb21tYW5kczogVkFSSUFCTEVfcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG15ZGF0YSwgYWVzKHggPSBWQVJJQUJMRSwgeSA9IFZBUklBQkxFKSkgKyBnZW9tX3BvaW50KCkKKiBDb21tYW5kczogZ3JpZC5hcnJhbmdlKFZBUklBQkxFX3Bsb3QxLCBWQVJJQUJMRV9wbG90MiwgVkFSSUFCTEVfcGxvdDMsIFZBUklBQkxFX3Bsb3Q0LCBuY29sPTIpCgpgYGB7cn0KI2dyaWQuYXJyYW5nZShWQVJJQUJMRV9wbG90MSwgVkFSSUFCTEVfcGxvdDIsIFZBUklBQkxFX3Bsb3QzLCBWQVJJQUJMRV9wbG90NCwgbmNvbD0yKQoKVFZfcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG15ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlciwgeSA9IFRWKSkgKyBnZW9tX3BvaW50KCkKcmFkaW9fcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG15ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlciwgeSA9IHJhZGlvKSkgKyBnZW9tX3BvaW50KCkKbmV3c3BhcGVyX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBteWRhdGEsIGFlcyh4ID0gY2FzZV9udW1iZXIsIHkgPSBuZXdzcGFwZXIpKSArIGdlb21fcG9pbnQoKQpzYWxlc19wbG90IDwtIGdncGxvdChkYXRhID0gbXlkYXRhLCBhZXMoeCA9IGNhc2VfbnVtYmVyLCB5ID0gc2FsZXMpKSArIGdlb21fcG9pbnQoKQoKZ3JpZC5hcnJhbmdlKHNhbGVzX3Bsb3QsIFRWX3Bsb3QsIHJhZGlvX3Bsb3QsIG5ld3NwYXBlcl9wbG90LCBuY29sPTIpCmBgYApUaGVyZSBkb2VzIG5vdCBzZWVtIHRvIGJlIGFuIGlkZW50aWZpYWJsZSB0cmVuZCBpbiBhbnkgb2YgdGhlc2Ugc2NhdHRlcnBsb3RzLiAKCiogV2hlbiBsb29raW5nIGF0IHRoZXNlIHBsb3RzIGl0IGlzIGhhcmQgdG8gc2VlIGEgcGFydGljdWxhciB0cmVuZC4gCiogT25lIHdheSB0byBvYnNlcnZlIGFueSBwb3NzaWJsZSB0cmVuZCBpbiB0aGUgc2FsZXMgZGF0YSB3b3VsZCBiZSB0byByZS1vcmRlciB0aGUgZGF0YSBmcm9tIGxvdyB0byBoaWdoLiAKKiBUaGUgMjAwIG1vbnRocyBvYnNlcnZhdGlvbnMgYXJlIGluIG5vIHBhcnRpY3VsYXIgY2hyb25vbG9naWNhbCB0aW1lIHNlcXVlbmNlLiAKKiBUaGUgY2FzZSBudW1iZXJzIGFyZSBpbmRlcGVuZGVudCBzZXF1ZW50aWFsbHkgZ2VuZXJhdGVkIG51bWJlcnMuIFNpbmNlIGVhY2ggY2FzZSBpcyBpbmRlcGVuZGVudCwgd2UgY2FuIHJlb3JkZXIgdGhlbS4gCgoKIyMjIDJCKSBSZS1vcmRlciBzYWxlcyBmcm9tIGxvdyB0byBoaWdoLCBhbmQgc2F2ZSByZS1vcmRlcmVkIGRhdGEgaW4gYSBuZXcgc2V0LiBBcyBzYWxlcyBkYXRhIGlzIHJlLXJlb3JkZWQgYXNzb2NpYXRlZCBvdGhlciBjb2x1bW4gZmllbGRzIGZvbGxvdy4KCiogQ29tbWFuZHM6IG5ld2RhdGEgPC0gbXlkYXRhWyBvcmRlcihteWRhdGEkVkFSSUFCTEUpLCBdCgpgYGB7cn0KIyBFeHRyYWN0IGNhc2VfbnVtYmVyIGZyb20gdGhlIG5ld2RhdGEKbmV3ZGF0YSA9IG15ZGF0YVsgb3JkZXIobXlkYXRhJHNhbGVzKSwgXQoKY2FzZV9udW1iZXIgPC0gbmV3ZGF0YSRjYXNlX251bWJlcgpoZWFkKG5ld2RhdGEpCmBgYAoKCiMjIyMgRXh0cmFjdCB0aGUgdmFyaWFibGVzIGZyb20gdGhlIG5ldyBkYXRhCgpgYGB7cn0KIyBuZXdfVkFSSUFCTEUgPSBuZXdkYXRhJFZBUklBQkxFCgpuZXdfVFYgPSBuZXdkYXRhJFRWCm5ld19yYWRpbyA9IG5ld2RhdGEkcmFkaW8KbmV3X25ld3NwYXBlciA9IG5ld2RhdGEkbmV3c3BhcGVyCm5ld19zYWxlcyA9IG5ld2RhdGEkc2FsZXMKYGBgCgojIyMgMkMpIFJlcGVhdCB0aGUgNCBncmFwaHMgd2l0aCB0aGUgbmV3ZGF0YSB0byBzcG90IGFueSB0cmVuZHMuIE5vdGUgeW91ciBvYnNlcnZhdGlvbnMgb24gd2hhdCB0aGUgbmV3IHBsb3RzIGFyZSByZXZlYWxpbmcgaW4gdGVybXMgb2YgdHJlbmRpbmcgcmVsYXRpb25zaGlwLiAKCiogQ29tbWFuZHM6IFZBUklBQkxFX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBteWRhdGEsIGFlcyh4ID0gVkFSSUFCTEUsIHkgPSBWQVJJQUJMRSkpICsgZ2VvbV9wb2ludCgpCiogQ29tbWFuZHM6IEZvciB4IHZhcmlhYmxlIGluIHRoZSBwbG90IHVzZTogYWVzKHggPSBjYXNlX251bWJlcltvcmRlcihjYXNlX251bWJlcildKQoqIENvbW1hbmRzOiBncmlkLmFycmFuZ2UoVkFSSUFCTEVfcGxvdDEsIFZBUklBQkxFX3Bsb3QyLCBWQVJJQUJMRV9wbG90MywgVkFSSUFCTEVfcGxvdDQsIG5jb2w9MikKCmBgYHtyfQojZ3JpZC5hcnJhbmdlKG5ld3NhbGVzX3Bsb3QsIG5ld3R2X3Bsb3QsIG5ld3JhZGlvX3Bsb3QsIG5ld25ld3NfcGxvdCwgbmNvbD0yKQoKbmV3VFZfcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG5ld2RhdGEsIGFlcyh4ID0gY2FzZV9udW1iZXJbb3JkZXIoY2FzZV9udW1iZXIpXSwgeSA9IG5ld19UVikpICsgZ2VvbV9wb2ludCgpCm5ld3JhZGlvX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBteWRhdGEsIGFlcyh4ID0gY2FzZV9udW1iZXJbb3JkZXIoY2FzZV9udW1iZXIpXSwgeSA9IG5ld19yYWRpbykpICsgZ2VvbV9wb2ludCgpCm5ld25ld3NwYXBlcl9wbG90IDwtIGdncGxvdChkYXRhID0gbXlkYXRhLCBhZXMoeCA9IGNhc2VfbnVtYmVyW29yZGVyKGNhc2VfbnVtYmVyKV0sIHkgPSBuZXdfbmV3c3BhcGVyKSkgKyBnZW9tX3BvaW50KCkKbmV3c2FsZXNfcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG15ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlcltvcmRlcihjYXNlX251bWJlcildLCB5ID0gbmV3X3NhbGVzKSkgKyBnZW9tX3BvaW50KCkKCmdyaWQuYXJyYW5nZShuZXdzYWxlc19wbG90LCBuZXdUVl9wbG90LCBuZXdyYWRpb19wbG90LCBuZXduZXdzcGFwZXJfcGxvdCwgbmNvbD0yKQpgYGAKQWZ0ZXIgcmUtb3JkZXJpbmcgdGhlIHNhbGVzIGl0IGlzIG11Y2ggZWFzaWVyIHRvIHNlZSBzb21lIGlkZW50aWZpYWJsZSBwYXR0ZXJucyBpbiB0aGVzZSBzY2F0dGVycGxvdHMsIHNwZWNpZmljYWxseSBmb3Igc2FsZXMuIEFsbCB0aGUgZGF0YSBwb2ludHMgZm9yIHNhbGVzIHNlZW0gdG8gZmFsbCBpbiBhIHBvc2l0aXZlbHkgc2xvcGVkIGxpbmUuIFRoZSBkYXRhIHBvaW50cyBmb3IgVFYgc3RhcnQgb2YgdmVyeSBoZWF2aWx5IGNvbmNlbnRyYXRlZCBhdCBhIHNwZWNpZmljIHBvaW50IGFuZCB0aGVuIGJlZ2luIHRvIGRpc3BlcnNlIGV2ZW4gbW9yZSwgYnV0IHN0aWxsIGluIHRoZSBkaXJlY3Rpb24gb2YgYSBwb3NpdGl2ZSBzbG9wZS4gU2ltaWxhcmx5LCB0aGUgbmV3IHJhZGlvIHBsb3Qgc2hvd3MgZGF0YSB0aGF0IGlzIG1vc3RseSBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQuIEhvd2V2ZXIsIHRoZXJlIHN0aWxsIGRvZXMgbm90IHNlZW0gdG8gYmUgYW55IGlkZW50aWZpYWJsZSBwYXR0ZXJuIGZvciB0aGUgbmV3c3BhcGVyIGRhdGEuIAoKLS0tLS0tLS0tLQoKIyMgVGFzayAzOiBTdGFuZGFyZGl6ZWQgWi1WYWx1ZQoKLS0tLS0tLS0tLQoKCiMjIyAzQSkgQ3JlYXRlIGEgaGlzdG9ncmFtIG9mIHRoZSBhc3NpZ25lZCBmZWF0dXJlIHotc2NvcmVzLiBEZXNjcmliZSB0aGUgb3V0cHV0IG5vdGUgYW55IHJlbGV2YW50IHZhbHVlcy4KCiogQ29tbWFuZDogel9zY29yZSA9ICggVkFSSUFCTEUgLSBtZWFuKFZBUklBQkxFKSApIC8gc2QoVkFSSUFCTEUpCiogQ29tbWFuZHM6IHFwbG90KCB4ID0gVkFSSUFCTEUgLGdlb209Imhpc3RvZ3JhbSIsIGJpbndpZHRoID0gMC4zKQoKYGBge3J9Cnpfc2NvcmVUViA9IChteWRhdGEkVFYgLSBtZWFuVFYpIC8gc2RUVgp6X3Njb3JlcmFkaW8gPSAobXlkYXRhJHJhZGlvIC0gbWVhbnJhZGlvKSAvIHNkcmFkaW8Kel9zY29yZW5ld3NwYXBlciA9IChteWRhdGEkbmV3c3BhcGVyIC0gbWVhbm5ld3NwYXBlcikgLyBzZG5ld3NwYXBlcgp6X3Njb3Jlc2FsZXMgPSAobXlkYXRhJHNhbGVzIC0gbWVhbnNhbGVzKSAvIHNkc2FsZXMKCnFwbG90KCB4ID0gel9zY29yZVRWICxnZW9tPSJoaXN0b2dyYW0iLCBiaW53aWR0aCA9IDAuMykKYGBgCgpgYGB7cn0KcXBsb3QoIHggPSB6X3Njb3JlcmFkaW8gLGdlb209Imhpc3RvZ3JhbSIsIGJpbndpZHRoID0gMC4zKQpgYGAKCmBgYHtyfQpxcGxvdCggeCA9IHpfc2NvcmVuZXdzcGFwZXIgLGdlb209Imhpc3RvZ3JhbSIsIGJpbndpZHRoID0gMC4zKQpgYGAKCmBgYHtyfQpxcGxvdCggeCA9IHpfc2NvcmVzYWxlcyAsZ2VvbT0iaGlzdG9ncmFtIiwgYmlud2lkdGggPSAwLjMpCmBgYAoKVGhlIHNhbGVzIGhpc3RvZ3JhbSBhcHBlYXJzIHRoZSBjbG9zZXN0IHRvIHJlc2VtYmxpbmcgYSBub3JtYWwgZGlzdHJpYnV0aW9uIHdoaWxlIG5ld3NwYXBlciBpcyBwb3NpdGl2ZWx5IHNrZXdlZC4gVGhpcyBpcyBsaWtlbHkgYmVjYXVzZSBvZiB0aGUgb3V0bGllcnMgaW4gdGhlIG5ld3NwYXBlciBkYXRhLiAKCiMjIyAzQikgR2l2ZW4gYSBzYWxlcyB2YWx1ZSBvZiAkMjY3MDAsIGNhbGN1bGF0ZSB0aGUgY29ycmVzcG9uZGluZyB6LXZhbHVlIG9yIHotc2NvcmUuIAoKKiBDb21tYW5kOiB6X3Njb3JlID0gKCBWQVJJQUJMRSAtIG1lYW4oVkFSSUFCTEUpICkgLyBzZChWQVJJQUJMRSkKCmBgYHtyfQp6X3Njb3Jlc2FsZXNjYWxjdWxhdGlvbiA9ICggMjYuNyAtIG1lYW4obXlkYXRhJHNhbGVzKSApIC8gc2QobXlkYXRhJHNhbGVzKQp6X3Njb3Jlc2FsZXNjYWxjdWxhdGlvbgpgYGAKCgojIyMgM0MpIEJhc2VkIG9uIHRoZSB6LXZhbHVlLCBob3cgd291bGQgeW91IHJhdGUgYSAkMjY3MDAgc2FsZXMgdmFsdWU6IHBvb3IsIGF2ZXJhZ2UsIGdvb2QsIG9yIHZlcnkgZ29vZCBwZXJmb3JtYW5jZT8gRXhwbGFpbiB5b3VyIGxvZ2ljLiAKSSB3b3VsZCBzYXkgdGhhdCBhIHotc2NvcmUgb2YgMi40MyByZXNlbWJsZXMgYSBnb29kIHBlcmZvcm1hY2UuIEl0IGlzIGEgcG9zaXRpdmUgbnVtYmVyIGFuZCBpdCBpcyBhYm91dCB0d28gc3RhbmRhcmQgZGV2aWF0aW9ucyBhYm92ZSB0aGUgbWVhbiB3aGljaCBzaG93cyB0aGF0IHNhbGVzIGFyZSBhYm92ZSBhdmVyYWdlIGFuZCB0aGVyZSBpcyBhIGdvb2QgcGVyZm9ybWFuY2UuIAoK