Notebook Instructions
For your assignment you may be using different dataset than what is included here.
Always read carefully the instructions on Sakai.
Tasks/questions to be completed/answered are highlighted in larger bolded fonts and numbered according to their section.
Load Packages in R/RStudio
We are going to use tidyverse a collection of R packages designed for data science.
Task 1: Quantitative Analysis
1A) Read the csv file into R Studio and display the dataset.
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" = "X")
head(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
TV <- mydata$TV
TV_max <- max(mydata$TV)
TV_max
[1] 296.4
TV_min <-min(mydata$TV)
TV_min
[1] 0.7
TV_range <-range(TV_max - TV_min)
TV_range
[1] 295.7 295.7
TV_mean <- mean(mydata$TV)
TV_mean
[1] 147.0425
TV_sd <- sd(mydata$TV)
TV_sd
[1] 85.85424
TV_variance <- var(mydata$TV)
TV_variance
[1] 7370.95
the variance seems unreasonably high
Radio
radio <- mydata$radio
Radio_max <- max(mydata$radio)
Radio_max
[1] 49.6
Radio_min <-min(mydata$radio)
Radio_min
[1] 0
Radio_range <-range(Radio_max - Radio_min)
Radio_range
[1] 49.6 49.6
Radio_mean <- mean(mydata$radio)
Radio_mean
[1] 23.264
Radio_sd <- sd(mydata$radio)
Radio_sd
[1] 14.84681
Radio_variance <- var(mydata$radio)
Radio_variance
[1] 220.4277
radio is the only feature that has a proper 0 for minimum
Newspaper
newspaper_max <- max(mydata$newspaper)
newspaper_max
[1] 114
newspaper_min <-min(mydata$newspaper)
newspaper_min
[1] 0.3
newspaper_range <-range(newspaper_max - newspaper_min)
newspaper_range
[1] 113.7 113.7
newspaper_mean <- mean(mydata$newspaper)
newspaper_mean
[1] 30.554
newspaper_sd <- sd(mydata$newspaper)
newspaper_sd
[1] 21.77862
newspaper_variance <- var(mydata$newspaper)
newspaper_variance
[1] 474.3083
newspaper kind of lies in the middle of the rest as far as the values go
Sales
sales <- mydata$sales
sales_max <- max(mydata$sales)
sales_max
[1] 27
sales_min <-min(mydata$sales)
sales_min
[1] 1.6
sales_range <-range(sales_max - sales_min)
sales_range
[1] 25.4 25.4
sales_mean <- mean(mydata$sales)
sales_mean
[1] 14.0225
sales_sd <- sd(mydata$sales)
sales_sd
[1] 5.217457
sales_variance <- var(mydata$sales)
sales_variance
[1] 27.22185
sales has the lowest standard deviation of the bunch
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
Min. : 1.00 Min. : 0.70
1st Qu.: 50.75 1st Qu.: 74.38
Median :100.50 Median :149.75
Mean :100.50 Mean :147.04
3rd Qu.:150.25 3rd Qu.:218.82
Max. :200.00 Max. :296.40
radio newspaper sales
Min. : 0.000 Min. : 0.30 Min. : 1.60
1st Qu.: 9.975 1st Qu.: 12.75 1st Qu.:10.38
Median :22.900 Median : 25.75 Median :12.90
Mean :23.264 Mean : 30.55 Mean :14.02
3rd Qu.:36.525 3rd Qu.: 45.10 3rd Qu.:17.40
Max. :49.600 Max. :114.00 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)
iqrTV = quantile(mydata$TV)[4] - quantile(mydata$TV)[2]
iqrRadio = quantile(mydata$radio)[4] - quantile(mydata$radio)[2]
iqrNewspaper = quantile(mydata$newspaper)[4] - quantile(mydata$newspaper)[2]
iqrSales = quantile(mydata$sales)[4] - quantile(mydata$sales)[2]
UpperTV = (iqrTV * 1.5) + quantile(mydata$TV)[4]
UpperRadio = (iqrRadio * 1.5) + quantile(mydata$radio)[4]
UpperNewspaper = (iqrNewspaper * 1.5) + quantile(mydata$newspaper)[4]
UpperSales = (iqrSales * 1.5) + quantile(mydata$sales)[4]
LowerTV = quantile(mydata$TV)[2] - (iqrTV * 1.5)
LowerRadio = quantile(mydata$radio)[2] - (iqrRadio * 1.5)
LowerNewspaper = quantile(mydata$newspaper)[2] - (iqrNewspaper * 1.5)
LowerSales = quantile(mydata$sales)[2] - (iqrSales * 1.5)
count(mydata[mydata$TV < LowerTV, ])
count(mydata[mydata$TV > UpperTV, ])
count(mydata[mydata$radio > UpperRadio, ])
count(mydata[mydata$radio < LowerRadio, ])
count(mydata[mydata$newspaper > UpperNewspaper, ])
count(mydata[mydata$newspaper < LowerNewspaper, ])
count(mydata[mydata$sales > UpperSales, ])
count(mydata[mydata$sales < LowerSales, ])
there are two outliers in newspaper that go past the upper threshold, meaning that the difference in these two data points is significantly different from the rest
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.
On average, the most money spent was in TV as the mean is the highest by quite a bit, next up was newspaper followed by radio, this makes sense as far as the tv part goes but I am not one hundred percent sure if it makes sense as far as newspaper and stuff goes. It’s possible this company just has a focus on print over radio.
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)
TVplot = ggplot(data = mydata, aes(x = case_number, y = TV)) + geom_point()
Radioplot = ggplot(data = mydata, aes(x = case_number, y = radio)) + geom_point()
newsplot = ggplot(data = mydata, aes(x = case_number, y = newspaper)) + geom_point()
salesplot = ggplot(data = mydata, aes(x = case_number, y = sales)) + geom_point()
grid.arrange(TVplot, Radioplot, newsplot,salesplot, ncol=2)

- 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)
2C) Repeat the 4 graphs with the newdata to spot any trends. Note your observations on what the new plots are revealing in terms of trending relationship.
- Commands: VARIABLE_plot <- ggplot(data = mydata, aes(x = VARIABLE, y = VARIABLE)) + geom_point()
- Commands: For x variable in the plot use: aes(x = case_number[order(case_number)])
- Commands: grid.arrange(VARIABLE_plot1, VARIABLE_plot2, VARIABLE_plot3, VARIABLE_plot4, ncol=2)
newTVplot = ggplot(data = newdata, aes(x = case_number[order(case_number)], y = TV)) + geom_point()
newRadioplot = ggplot(data = newdata, aes(x = case_number[order(case_number)],, y = radio)) + geom_point()
newnewsplot = ggplot(data = newdata, aes(x = case_number[order(case_number)],, y = newspaper)) + geom_point()
newsalesplot = ggplot(data = newdata, aes(x = case_number[order(case_number)],, y = sales)) + geom_point()
grid.arrange(newTVplot, newRadioplot, newnewsplot,newsalesplot, ncol=2)

#After the ordering of the data it is a lot easier to see some correlations, specifically in sales and tv, radio also, but definitely not newspaper which still is very all over the place.
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 - TV_mean) / TV_sd
z_scoreradio = (mydata$radio - Radio_mean) / Radio_sd
z_scorenewspaper = (mydata$newspaper - newspaper_mean) / newspaper_sd
z_scoresales = (mydata$sales - sales_mean) / sales_sd
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)

3B) Given a sales value of $26700, calculate the corresponding z-value or z-score.
- Command: z_score = ( VARIABLE - mean(VARIABLE) ) / sd(VARIABLE)
z_score = ( 26.7 - mean(mydata$sales) ) / sd(mydata$sales)
z_score
[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.
The z-score shows that the sales values is more than two standard deviations above the mean, so the sales are well above average so it should be considered a good performance.
LS0tCnRpdGxlOiAiRGVzY3JpcHRpdmUgQW5hbHl0aWNzIgphdXRob3I6ICJOaWNrIEtyYW5qZWMiCmRhdGU6ICIyLzI2LzE4IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdApzdWJ0aXRsZTogQ01FIEdyb3VwIEZvdW5kYXRpb24gQnVzaW5lc3MgQW5hbHl0aWNzIExhYgotLS0KCi0tLS0tLS0tLS0tLS0KCiMjIE5vdGVib29rIEluc3RydWN0aW9ucwoKLS0tLS0tLS0tLS0tLQoKKiBGb3IgeW91ciBhc3NpZ25tZW50IHlvdSBtYXkgYmUgdXNpbmcgZGlmZmVyZW50IGRhdGFzZXQgdGhhbiB3aGF0IGlzIGluY2x1ZGVkIGhlcmUuIAoKKiBBbHdheXMgcmVhZCBjYXJlZnVsbHkgdGhlIGluc3RydWN0aW9ucyBvbiBTYWthaS4gIAoKKiBUYXNrcy9xdWVzdGlvbnMgdG8gYmUgY29tcGxldGVkL2Fuc3dlcmVkIGFyZSBoaWdobGlnaHRlZCBpbiBsYXJnZXIgYm9sZGVkIGZvbnRzIGFuZCBudW1iZXJlZCBhY2NvcmRpbmcgdG8gdGhlaXIgc2VjdGlvbi4KCiMjIyBMb2FkIFBhY2thZ2VzIGluIFIvUlN0dWRpbyAKCldlIGFyZSBnb2luZyB0byB1c2UgdGlkeXZlcnNlIGEgY29sbGVjdGlvbiBvZiBSIHBhY2thZ2VzIGRlc2lnbmVkIGZvciBkYXRhIHNjaWVuY2UuIAoKKiBJbmZvOiBodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLwoKYGBge3IsIGVjaG89RkFMU0V9CgojIEhlcmUgd2UgYXJlIGNoZWNraW5nIGlmIHRoZSBwYWNrYWdlIGlzIGluc3RhbGxlZAppZighcmVxdWlyZSh0aWR5dmVyc2UpKXsKICAKICAjIElmIHRoZSBwYWNrYWdlIGlzIG5vdCBpbiB0aGUgc3lzdGVtIHRoZW4gaXQgd2lsbCBiZSBpbnN0YWxsCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkKICAKICAjIEhlcmUgd2UgYXJlIGxvYWRpbmcgdGhlIHBhY2thZ2UKICBsaWJyYXJ5KHRpZHl2ZXJzZSkKfQoKaWYoIXJlcXVpcmUoZ3JpZEV4dHJhKSl7CiAgCiAgIyBJZiB0aGUgcGFja2FnZSBpcyBub3QgaW4gdGhlIHN5c3RlbSB0aGVuIGl0IHdpbGwgYmUgaW5zdGFsbAogIGluc3RhbGwucGFja2FnZXMoImdyaWRFeHRyYSIsIGRlcGVuZGVuY2llcyA9IFRSVUUpCiAgCiAgIyBIZXJlIHdlIGFyZSBsb2FkaW5nIHRoZSBwYWNrYWdlCiAgbGlicmFyeShncmlkRXh0cmEpCn0KCmBgYAoKLS0tLS0tLS0tLS0tLQoKIyMgVGFzayAxOiBRdWFudGl0YXRpdmUgQW5hbHlzaXMKCi0tLS0tLS0tLS0tLS0KCiMjIyAxQSkgUmVhZCB0aGUgY3N2IGZpbGUgaW50byBSIFN0dWRpbyBhbmQgZGlzcGxheSB0aGUgZGF0YXNldC4gCgoqIE5hbWUgeW91ciBkYXRhc2V0ICdteWRhdGEnIHNvIGl0IGVhc3kgdG8gd29yayB3aXRoLgoKKiBDb21tYW5kczogcmVhZF9jc3YoKSBoZWFkKCkgbWF4KCkgbWluKCkgdmFyKCkgc2QoKQoKIyMjIyBFeHRyYWN0IHRoZSBhc3NpZ25lZCBmZWF0dXJlcyAoY29sdW1ucykgdG8gcGVyZm9ybSBzb21lIGFuYWx5dGljcy4gCgpgYGB7cn0gCm15ZGF0YSA9IHJlYWQuY3N2KCJBZHZlcnRpc2luZy5jc3YiKQpoZWFkKG15ZGF0YSkKYGBgCgojIyMjIENoYW5nZSB0aGUgdmFyaWFibGUgbmFtZSAiWDEiIHRvIGNhc2VfbnVtYmVyIHVzaW5nIHRoZSBmdW5jdGlvbiByZW5hbWUoKQoKKiBteWRhdGEgPC0gcmVuYW1lKG15ZGF0YSwgIk5FV19WQVJfTkFNRSIgPSAiT0xEX1ZBUl9OQU1FIikKCmBgYHtyfSAKbXlkYXRhIDwtIHJlbmFtZShteWRhdGEsICJjYXNlX251bWJlciIgPSAiWCIpCmhlYWQobXlkYXRhKQpgYGAKCiMjIyAxQikgRmluZCB0aGUgcmFuZ2UgKCBkaWZmZXJlbmNlIGJldHdlZW4gbWluIGFuZCBtYXggKSwgbWluLCBtYXgsIHN0YW5kYXJkIGRldmlhdGlvbiBhbmQgdmFyaWFuY2UgZm9yIGVhY2ggYXNzaWduZWQgZmVhdHVyZSAoIFVzZSBzZXBhcmF0ZSBjaHVua3MgZm9yIGVhY2ggZmVhdHVyZSApLiBDb21wYXJlIGVhY2ggZmVhdHVyZSBhbmQgbm90ZSBhbnkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMKCioqVFYqKgpgYGB7cn0KVFYgPC0gbXlkYXRhJFRWClRWX21heCA8LSBtYXgobXlkYXRhJFRWKQpUVl9tYXgKYGBgCgpgYGB7cn0KVFZfbWluIDwtbWluKG15ZGF0YSRUVikKVFZfbWluCmBgYAoKYGBge3J9ClRWX3JhbmdlIDwtcmFuZ2UoVFZfbWF4IC0gVFZfbWluKQpUVl9yYW5nZQpgYGAKCmBgYHtyfQpUVl9tZWFuIDwtIG1lYW4obXlkYXRhJFRWKQpUVl9tZWFuCmBgYAoKYGBge3J9ClRWX3NkIDwtIHNkKG15ZGF0YSRUVikKVFZfc2QKYGBgCgpgYGB7cn0KVFZfdmFyaWFuY2UgPC0gdmFyKG15ZGF0YSRUVikKVFZfdmFyaWFuY2UKYGBgCiN0aGUgdmFyaWFuY2Ugc2VlbXMgdW5yZWFzb25hYmx5IGhpZ2gKCgoqKlJhZGlvKioKYGBge3J9CnJhZGlvIDwtIG15ZGF0YSRyYWRpbwpSYWRpb19tYXggPC0gbWF4KG15ZGF0YSRyYWRpbykKUmFkaW9fbWF4CmBgYAoKYGBge3J9ClJhZGlvX21pbiA8LW1pbihteWRhdGEkcmFkaW8pClJhZGlvX21pbgpgYGAKCmBgYHtyfQpSYWRpb19yYW5nZSA8LXJhbmdlKFJhZGlvX21heCAtIFJhZGlvX21pbikKUmFkaW9fcmFuZ2UKYGBgCgpgYGB7cn0KUmFkaW9fbWVhbiA8LSBtZWFuKG15ZGF0YSRyYWRpbykKUmFkaW9fbWVhbgpgYGAKCmBgYHtyfQpSYWRpb19zZCA8LSBzZChteWRhdGEkcmFkaW8pClJhZGlvX3NkCmBgYAoKYGBge3J9ClJhZGlvX3ZhcmlhbmNlIDwtIHZhcihteWRhdGEkcmFkaW8pClJhZGlvX3ZhcmlhbmNlCmBgYAojcmFkaW8gaXMgdGhlIG9ubHkgZmVhdHVyZSB0aGF0IGhhcyBhIHByb3BlciAwIGZvciBtaW5pbXVtCioqTmV3c3BhcGVyKioKYGBge3J9Cm5ld3NwYXBlcl9tYXggPC0gbWF4KG15ZGF0YSRuZXdzcGFwZXIpCm5ld3NwYXBlcl9tYXgKYGBgCgpgYGB7cn0KbmV3c3BhcGVyX21pbiA8LW1pbihteWRhdGEkbmV3c3BhcGVyKQpuZXdzcGFwZXJfbWluCmBgYAoKYGBge3J9Cm5ld3NwYXBlcl9yYW5nZSA8LXJhbmdlKG5ld3NwYXBlcl9tYXggLSBuZXdzcGFwZXJfbWluKQpuZXdzcGFwZXJfcmFuZ2UKYGBgCgpgYGB7cn0KbmV3c3BhcGVyX21lYW4gPC0gbWVhbihteWRhdGEkbmV3c3BhcGVyKQpuZXdzcGFwZXJfbWVhbgpgYGAKCmBgYHtyfQpuZXdzcGFwZXJfc2QgPC0gc2QobXlkYXRhJG5ld3NwYXBlcikKbmV3c3BhcGVyX3NkCmBgYAoKYGBge3J9Cm5ld3NwYXBlcl92YXJpYW5jZSA8LSB2YXIobXlkYXRhJG5ld3NwYXBlcikKbmV3c3BhcGVyX3ZhcmlhbmNlCmBgYAojbmV3c3BhcGVyIGtpbmQgb2YgbGllcyBpbiB0aGUgbWlkZGxlIG9mIHRoZSByZXN0IGFzIGZhciBhcyB0aGUgdmFsdWVzIGdvCioqU2FsZXMqKgpgYGB7cn0Kc2FsZXMgPC0gbXlkYXRhJHNhbGVzCnNhbGVzX21heCA8LSBtYXgobXlkYXRhJHNhbGVzKQpzYWxlc19tYXgKYGBgCgpgYGB7cn0Kc2FsZXNfbWluIDwtbWluKG15ZGF0YSRzYWxlcykKc2FsZXNfbWluCmBgYAoKYGBge3J9CnNhbGVzX3JhbmdlIDwtcmFuZ2Uoc2FsZXNfbWF4IC0gc2FsZXNfbWluKQpzYWxlc19yYW5nZQpgYGAKCmBgYHtyfQpzYWxlc19tZWFuIDwtIG1lYW4obXlkYXRhJHNhbGVzKQpzYWxlc19tZWFuCmBgYAoKYGBge3J9CnNhbGVzX3NkIDwtIHNkKG15ZGF0YSRzYWxlcykKc2FsZXNfc2QKYGBgCgpgYGB7cn0Kc2FsZXNfdmFyaWFuY2UgPC0gdmFyKG15ZGF0YSRzYWxlcykKc2FsZXNfdmFyaWFuY2UKYGBgCiNzYWxlcyBoYXMgdGhlIGxvd2VzdCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGJ1bmNoCiMjIyAxQykgVXNlIHRoZSBzdW1tYXJ5KCkgZnVuY3Rpb24gb24gYWxsIHRoZSBkYXRhc2V0IHRvIGdpdmUgeW91IGEgZ2VuZXJhbCBkZXNjcmlwdGlvbiBvZiB0aGUgZGF0YS4gTm90ZSBhbnkgZGlmZmVyZW5jZXMgYmV0d2VlbiBmZWF0dXJlcy4KCmBgYHtyfQpzdW1tYXJ5KG15ZGF0YSkKYGBgCgojIyMjIEFyZSB0aGVyZSBhbnkgb3V0bGllcnMsIGlmIG5vdCBleHBsYWluIHRoZSBsYWNrIG9mIG91dGxpZXJzPyBpZiBhbnkgZXhwbGFpbiB3aGF0IHRoZSBvdXRsaWVycyByZXByZXNlbnQgYW5kIGhvdyBtYW55IHJlY29yZHMgYXJlIG91dGxpZXJzPyAoIFVzZSBjb2RlIGZyb20gbm90ZWJvb2stMDMgdG8gZmluZCBvdXRsaWVycykgCgpgYGB7cn0KaXFyVFYgPSBxdWFudGlsZShteWRhdGEkVFYpWzRdIC0gcXVhbnRpbGUobXlkYXRhJFRWKVsyXQppcXJSYWRpbyA9IHF1YW50aWxlKG15ZGF0YSRyYWRpbylbNF0gLSBxdWFudGlsZShteWRhdGEkcmFkaW8pWzJdCmlxck5ld3NwYXBlciA9IHF1YW50aWxlKG15ZGF0YSRuZXdzcGFwZXIpWzRdIC0gcXVhbnRpbGUobXlkYXRhJG5ld3NwYXBlcilbMl0KaXFyU2FsZXMgPSBxdWFudGlsZShteWRhdGEkc2FsZXMpWzRdIC0gcXVhbnRpbGUobXlkYXRhJHNhbGVzKVsyXQpgYGAKYGBge3J9ClVwcGVyVFYgPSAoaXFyVFYgKiAxLjUpICsgcXVhbnRpbGUobXlkYXRhJFRWKVs0XQpVcHBlclJhZGlvID0gKGlxclJhZGlvICogMS41KSArIHF1YW50aWxlKG15ZGF0YSRyYWRpbylbNF0KVXBwZXJOZXdzcGFwZXIgPSAoaXFyTmV3c3BhcGVyICogMS41KSArIHF1YW50aWxlKG15ZGF0YSRuZXdzcGFwZXIpWzRdClVwcGVyU2FsZXMgPSAoaXFyU2FsZXMgKiAxLjUpICsgcXVhbnRpbGUobXlkYXRhJHNhbGVzKVs0XQpgYGAKYGBge3J9Ckxvd2VyVFYgPSBxdWFudGlsZShteWRhdGEkVFYpWzJdIC0gKGlxclRWICogMS41KQpMb3dlclJhZGlvID0gcXVhbnRpbGUobXlkYXRhJHJhZGlvKVsyXSAtIChpcXJSYWRpbyAqIDEuNSkKTG93ZXJOZXdzcGFwZXIgPSBxdWFudGlsZShteWRhdGEkbmV3c3BhcGVyKVsyXSAtIChpcXJOZXdzcGFwZXIgKiAxLjUpCkxvd2VyU2FsZXMgPSBxdWFudGlsZShteWRhdGEkc2FsZXMpWzJdIC0gKGlxclNhbGVzICogMS41KQpgYGAKCmBgYHtyfQpjb3VudChteWRhdGFbbXlkYXRhJFRWIDwgTG93ZXJUViwgXSkKYGBgCgpgYGB7cn0KY291bnQobXlkYXRhW215ZGF0YSRUViA+IFVwcGVyVFYsIF0pCmBgYApgYGB7cn0KY291bnQobXlkYXRhW215ZGF0YSRyYWRpbyA+IFVwcGVyUmFkaW8sIF0pCmBgYAoKYGBge3J9CmNvdW50KG15ZGF0YVtteWRhdGEkcmFkaW8gPCBMb3dlclJhZGlvLCBdKQpgYGAKCmBgYHtyfQpjb3VudChteWRhdGFbbXlkYXRhJG5ld3NwYXBlciA+IFVwcGVyTmV3c3BhcGVyLCBdKQpgYGAKCmBgYHtyfQpjb3VudChteWRhdGFbbXlkYXRhJG5ld3NwYXBlciA8IExvd2VyTmV3c3BhcGVyLCBdKQpgYGAKCmBgYHtyfQpjb3VudChteWRhdGFbbXlkYXRhJHNhbGVzID4gVXBwZXJTYWxlcywgXSkKYGBgCgpgYGB7cn0KY291bnQobXlkYXRhW215ZGF0YSRzYWxlcyA8IExvd2VyU2FsZXMsIF0pCmBgYAoKI3RoZXJlIGFyZSB0d28gb3V0bGllcnMgaW4gbmV3c3BhcGVyIHRoYXQgZ28gcGFzdCB0aGUgdXBwZXIgdGhyZXNob2xkLCBtZWFuaW5nIHRoYXQgdGhlIGRpZmZlcmVuY2UgaW4gdGhlc2UgdHdvIGRhdGEgcG9pbnRzIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gdGhlIHJlc3QKIyMjIDFEKSBXcml0ZSBhIGdlbmVyYWwgZGVzY3JpcHRpb24gb2YgdGhlIGRhdGFzZXQgdXNpbmcgdGhlIHN0YXRpc3RpY3MgZm91bmQgaW4gdGhlIHN0ZXBzIGFib3ZlLiBVc2UgdGhlIG1pbixtYXggcmFuZ2UgdG8gY29tcGFyZSB0aGUgZmVhdHVyZXMsIG5vdGUgYW55IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzLgojT24gYXZlcmFnZSwgdGhlIG1vc3QgbW9uZXkgc3BlbnQgd2FzIGluIFRWIGFzIHRoZSBtZWFuIGlzIHRoZSBoaWdoZXN0IGJ5IHF1aXRlIGEgYml0LCBuZXh0IHVwIHdhcyBuZXdzcGFwZXIgZm9sbG93ZWQgYnkgcmFkaW8sIHRoaXMgbWFrZXMgc2Vuc2UgYXMgZmFyIGFzIHRoZSB0diBwYXJ0IGdvZXMgYnV0IEkgYW0gbm90IG9uZSBodW5kcmVkIHBlcmNlbnQgc3VyZSBpZiBpdCBtYWtlcyBzZW5zZSBhcyBmYXIgYXMgbmV3c3BhcGVyIGFuZCBzdHVmZiBnb2VzLiBJdCdzIHBvc3NpYmxlIHRoaXMgY29tcGFueSBqdXN0IGhhcyBhIGZvY3VzIG9uIHByaW50IG92ZXIgcmFkaW8uCgotLS0tLS0tLS0tLS0tCgojIyBUYXNrIDI6IFF1YWxpdGF0aXZlIEFuYWx5c2lzCgotLS0tLS0tLS0tLS0tCgoKIyMjIDJBKSBQbG90IGFsbCB0aGUgYXNzaWduZWQgZmVhdHVyZXMgYXMgeS1heGlzIGZvciB4LWF4aXMgdXNlIGNhc2VfbnVtYmVyLiBVc2UgdGhlIGdpdmVuIGNvbW1hbmRzIHRvIGNyZWF0ZSBlYWNoIHBsb3QgYW5kIGNyZWF0ZSBhIGdyaWQgdG8gcGxvdCBhbGwgZmVhdHVyZXMgTm90ZSBhbnkgdHJlbmRzL3BhdHRlcnMgaW4gdGhlIGRhdGEKCiogQ29tbWFuZHM6IFZBUklBQkxFX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBteWRhdGEsIGFlcyh4ID0gVkFSSUFCTEUsIHkgPSBWQVJJQUJMRSkpICsgZ2VvbV9wb2ludCgpCiogQ29tbWFuZHM6IGdyaWQuYXJyYW5nZShWQVJJQUJMRV9wbG90MSwgVkFSSUFCTEVfcGxvdDIsIFZBUklBQkxFX3Bsb3QzLCBWQVJJQUJMRV9wbG90NCwgbmNvbD0yKQoKYGBge3J9CgojZ3JpZC5hcnJhbmdlKFZBUklBQkxFX3Bsb3QxLCBWQVJJQUJMRV9wbG90MiwgVkFSSUFCTEVfcGxvdDMsIFZBUklBQkxFX3Bsb3Q0LCBuY29sPTIpClRWcGxvdCA9IGdncGxvdChkYXRhID0gbXlkYXRhLCBhZXMoeCA9IGNhc2VfbnVtYmVyLCB5ID0gVFYpKSArIGdlb21fcG9pbnQoKQpSYWRpb3Bsb3QgPSBnZ3Bsb3QoZGF0YSA9IG15ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlciwgeSA9IHJhZGlvKSkgKyBnZW9tX3BvaW50KCkKbmV3c3Bsb3QgPSBnZ3Bsb3QoZGF0YSA9IG15ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlciwgeSA9IG5ld3NwYXBlcikpICsgZ2VvbV9wb2ludCgpCnNhbGVzcGxvdCA9IGdncGxvdChkYXRhID0gbXlkYXRhLCBhZXMoeCA9IGNhc2VfbnVtYmVyLCB5ID0gc2FsZXMpKSArIGdlb21fcG9pbnQoKQpncmlkLmFycmFuZ2UoVFZwbG90LCBSYWRpb3Bsb3QsIG5ld3NwbG90LHNhbGVzcGxvdCwgbmNvbD0yKQoKYGBgCgoKKiBXaGVuIGxvb2tpbmcgYXQgdGhlc2UgcGxvdHMgaXQgaXMgaGFyZCB0byBzZWUgYSBwYXJ0aWN1bGFyIHRyZW5kLiAKKiBPbmUgd2F5IHRvIG9ic2VydmUgYW55IHBvc3NpYmxlIHRyZW5kIGluIHRoZSBzYWxlcyBkYXRhIHdvdWxkIGJlIHRvIHJlLW9yZGVyIHRoZSBkYXRhIGZyb20gbG93IHRvIGhpZ2guIAoqIFRoZSAyMDAgbW9udGhzIG9ic2VydmF0aW9ucyBhcmUgaW4gbm8gcGFydGljdWxhciBjaHJvbm9sb2dpY2FsIHRpbWUgc2VxdWVuY2UuIAoqIFRoZSBjYXNlIG51bWJlcnMgYXJlIGluZGVwZW5kZW50IHNlcXVlbnRpYWxseSBnZW5lcmF0ZWQgbnVtYmVycy4gU2luY2UgZWFjaCBjYXNlIGlzIGluZGVwZW5kZW50LCB3ZSBjYW4gcmVvcmRlciB0aGVtLiAKCgojIyMgMkIpIFJlLW9yZGVyIHNhbGVzIGZyb20gbG93IHRvIGhpZ2gsIGFuZCBzYXZlIHJlLW9yZGVyZWQgZGF0YSBpbiBhIG5ldyBzZXQuIEFzIHNhbGVzIGRhdGEgaXMgcmUtcmVvcmRlZCBhc3NvY2lhdGVkIG90aGVyIGNvbHVtbiBmaWVsZHMgZm9sbG93LgoKKiBDb21tYW5kczogbmV3ZGF0YSA8LSBteWRhdGFbIG9yZGVyKG15ZGF0YSRWQVJJQUJMRSksIF0KCmBgYHtyfQoKIyBFeHRyYWN0IGNhc2VfbnVtYmVyIGZyb20gdGhlIG5ld2RhdGEKbmV3ZGF0YSA9IG15ZGF0YVsgb3JkZXIobXlkYXRhJHNhbGVzKSwgXQpjYXNlX251bWJlciA8LSBuZXdkYXRhJGNhc2VfbnVtYmVyCgpoZWFkKG5ld2RhdGEpCmBgYAoKCiMjIyMgRXh0cmFjdCB0aGUgdmFyaWFibGVzIGZyb20gdGhlIG5ldyBkYXRhCgpgYGB7cn0KIyBuZXdfVkFSSUFCTEUgPSBuZXdkYXRhJFZBUklBQkxFCm5ld19UViA9IG5ld2RhdGEkVFYKbmV3X3JhZGlvID0gbmV3ZGF0YSRyYWRpbwpuZXdfbmV3c3BhcGVyID0gbmV3ZGF0YSRuZXdzcGFwZXIKbmV3X3NhbGVzID0gbmV3ZGF0YSRzYWxlcwpgYGAKCiMjIyAyQykgUmVwZWF0IHRoZSA0IGdyYXBocyB3aXRoIHRoZSBuZXdkYXRhIHRvIHNwb3QgYW55IHRyZW5kcy4gTm90ZSB5b3VyIG9ic2VydmF0aW9ucyBvbiB3aGF0IHRoZSBuZXcgcGxvdHMgYXJlIHJldmVhbGluZyBpbiB0ZXJtcyBvZiB0cmVuZGluZyByZWxhdGlvbnNoaXAuIAoKKiBDb21tYW5kczogVkFSSUFCTEVfcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG15ZGF0YSwgYWVzKHggPSBWQVJJQUJMRSwgeSA9IFZBUklBQkxFKSkgKyBnZW9tX3BvaW50KCkKKiBDb21tYW5kczogRm9yIHggdmFyaWFibGUgaW4gdGhlIHBsb3QgdXNlOiBhZXMoeCA9IGNhc2VfbnVtYmVyW29yZGVyKGNhc2VfbnVtYmVyKV0pCiogQ29tbWFuZHM6IGdyaWQuYXJyYW5nZShWQVJJQUJMRV9wbG90MSwgVkFSSUFCTEVfcGxvdDIsIFZBUklBQkxFX3Bsb3QzLCBWQVJJQUJMRV9wbG90NCwgbmNvbD0yKQoKYGBge3J9Cm5ld1RWcGxvdCA9IGdncGxvdChkYXRhID0gbmV3ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlcltvcmRlcihjYXNlX251bWJlcildLCB5ID0gVFYpKSArIGdlb21fcG9pbnQoKQpuZXdSYWRpb3Bsb3QgPSBnZ3Bsb3QoZGF0YSA9IG5ld2RhdGEsIGFlcyh4ID0gY2FzZV9udW1iZXJbb3JkZXIoY2FzZV9udW1iZXIpXSwsIHkgPSByYWRpbykpICsgZ2VvbV9wb2ludCgpCm5ld25ld3NwbG90ID0gZ2dwbG90KGRhdGEgPSBuZXdkYXRhLCBhZXMoeCA9IGNhc2VfbnVtYmVyW29yZGVyKGNhc2VfbnVtYmVyKV0sLCB5ID0gbmV3c3BhcGVyKSkgKyBnZW9tX3BvaW50KCkKbmV3c2FsZXNwbG90ID0gZ2dwbG90KGRhdGEgPSBuZXdkYXRhLCBhZXMoeCA9IGNhc2VfbnVtYmVyW29yZGVyKGNhc2VfbnVtYmVyKV0sLCB5ID0gc2FsZXMpKSArIGdlb21fcG9pbnQoKQpncmlkLmFycmFuZ2UobmV3VFZwbG90LCBuZXdSYWRpb3Bsb3QsIG5ld25ld3NwbG90LG5ld3NhbGVzcGxvdCwgbmNvbD0yKQoKYGBgCiNBZnRlciB0aGUgb3JkZXJpbmcgb2YgdGhlIGRhdGEgaXQgaXMgYSBsb3QgZWFzaWVyIHRvIHNlZSBzb21lIGNvcnJlbGF0aW9ucywgc3BlY2lmaWNhbGx5IGluIHNhbGVzIGFuZCB0diwgcmFkaW8gYWxzbywgYnV0IGRlZmluaXRlbHkgbm90IG5ld3NwYXBlciB3aGljaCBzdGlsbCBpcyB2ZXJ5IGFsbCBvdmVyIHRoZSBwbGFjZS4KLS0tLS0tLS0tLQoKIyMgVGFzayAzOiBTdGFuZGFyZGl6ZWQgWi1WYWx1ZQoKLS0tLS0tLS0tLQoKCiMjIyAzQSkgQ3JlYXRlIGEgaGlzdG9ncmFtIG9mIHRoZSBhc3NpZ25lZCBmZWF0dXJlIHotc2NvcmVzLiBEZXNjcmliZSB0aGUgb3V0cHV0IG5vdGUgYW55IHJlbGV2YW50IHZhbHVlcy4KCiogQ29tbWFuZDogel9zY29yZSA9ICggVkFSSUFCTEUgLSBtZWFuKFZBUklBQkxFKSApIC8gc2QoVkFSSUFCTEUpCiogQ29tbWFuZHM6IHFwbG90KCB4ID0gVkFSSUFCTEUgLGdlb209Imhpc3RvZ3JhbSIsIGJpbndpZHRoID0gMC4zKQoKYGBge3J9Cnpfc2NvcmVUViA9IChteWRhdGEkVFYgLSBUVl9tZWFuKSAvIFRWX3NkCnpfc2NvcmVyYWRpbyA9IChteWRhdGEkcmFkaW8gLSBSYWRpb19tZWFuKSAvIFJhZGlvX3NkCnpfc2NvcmVuZXdzcGFwZXIgPSAobXlkYXRhJG5ld3NwYXBlciAtIG5ld3NwYXBlcl9tZWFuKSAvIG5ld3NwYXBlcl9zZAp6X3Njb3Jlc2FsZXMgPSAobXlkYXRhJHNhbGVzIC0gc2FsZXNfbWVhbikgLyBzYWxlc19zZApxcGxvdCggeCA9IHpfc2NvcmVUViAsZ2VvbT0iaGlzdG9ncmFtIiwgYmlud2lkdGggPSAwLjMpCmBgYAoKYGBge3J9CnFwbG90KCB4ID0gel9zY29yZXJhZGlvICxnZW9tPSJoaXN0b2dyYW0iLCBiaW53aWR0aCA9IDAuMykKYGBgCgpgYGB7cn0KcXBsb3QoIHggPSB6X3Njb3JlbmV3c3BhcGVyICxnZW9tPSJoaXN0b2dyYW0iLCBiaW53aWR0aCA9IDAuMykKYGBgCmBgYHtyfQpxcGxvdCggeCA9IHpfc2NvcmVzYWxlcyAsZ2VvbT0iaGlzdG9ncmFtIiwgYmlud2lkdGggPSAwLjMpCmBgYAoKIyMjIDNCKSBHaXZlbiBhIHNhbGVzIHZhbHVlIG9mICQyNjcwMCwgY2FsY3VsYXRlIHRoZSBjb3JyZXNwb25kaW5nIHotdmFsdWUgb3Igei1zY29yZS4gCgoqIENvbW1hbmQ6IHpfc2NvcmUgPSAoIFZBUklBQkxFIC0gbWVhbihWQVJJQUJMRSkgKSAvIHNkKFZBUklBQkxFKQoKYGBge3J9Cnpfc2NvcmUgPSAoIDI2LjcgLSBtZWFuKG15ZGF0YSRzYWxlcykgKSAvIHNkKG15ZGF0YSRzYWxlcykKel9zY29yZQpgYGAKCgojIyMgM0MpIEJhc2VkIG9uIHRoZSB6LXZhbHVlLCBob3cgd291bGQgeW91IHJhdGUgYSAkMjY3MDAgc2FsZXMgdmFsdWU6IHBvb3IsIGF2ZXJhZ2UsIGdvb2QsIG9yIHZlcnkgZ29vZCBwZXJmb3JtYW5jZT8gRXhwbGFpbiB5b3VyIGxvZ2ljLiAKI1RoZSB6LXNjb3JlIHNob3dzIHRoYXQgdGhlIHNhbGVzIHZhbHVlcyBpcyBtb3JlIHRoYW4gdHdvIHN0YW5kYXJkIGRldmlhdGlvbnMgYWJvdmUgdGhlIG1lYW4sIHNvIHRoZSBzYWxlcyBhcmUgd2VsbCBhYm92ZSBhdmVyYWdlIHNvIGl0IHNob3VsZCBiZSBjb25zaWRlcmVkIGEgZ29vZCBwZXJmb3JtYW5jZS4KCg==