Case 1
Ben’s Knick Knacks sells a consumer durable product with a unit
margin of $161.50 and per customer mailing costs of $0.3343. They have
formed 126 segments based on past purchase history. They do a test
mailing to 3.24% of their database. You can see the outcomes of the test
in file knick_knack_test.csv. The columns are segment number,
the number of people in that segment that were mailed, and the number of
people who responded.
ktest <- read_csv("knick_knack_test.csv")
Setting the parameters:
m <- 161.50
c <- 0.3343
nseg <- 126
tsize <- 0.0324
1. What is the response breakeven threshold for mailing?
Provide your answer with four decimals separated by a dot, not a
comma (e.g. 0.1234).
brk = c/m
## Breakeven Point: 0.0021
2. How many segments would you target (out of 126)?
Provide a number (e.g. 34).
ktest <- ktest %>%
mutate(resp_rate = x_s/m_s) %>%
arrange(desc(resp_rate))
ktest <- as.data.frame(ktest)
bp <- barplot(ktest[,7])
axis(1, at = bp[,1], labels=ktest[,1], cex.axis=0.7, las=2)
abline(h=brk)
text(85, brk, "breakeven", cex=1, pos=3, col="black")
How many segments should be targeted? What segments are they? As a
percentage of the total segments?
n_segments <- sum(ktest$resp_rate >= brk)
## Optimal Number of segments: 51
Case 2
The company ended up rolling out to 71 segments. See the file
knick_knack_roll.csv for the segments, whether they were rolled
out to, the number of customers rolled out to in each segment, and the
responses.
kroll <- read_csv("knick_knack_roll.csv")
You can now compare the test response rate and the rollout response
rates (for the 71 segments that were rolled out to).
kroll <- kroll %>%
mutate(resp_rate = case_when(Resp_s== 0 ~ 0 ,
TRUE ~ Resp_s/Roll_s)) %>%
arrange(desc(resp_rate))
kroll1 <- kroll[!is.na(kroll$Resp_s), ] # 71 segments
How well do test rates predict roll rates? One way to measure this is
the correlation. If they predict perfectly, this would be 1.
3. Calculate the correlation between test and roll rates.
Provide your answer with three decimals separated by a dot, not a
comma (hint; in the cor function use, use = “complete.obs”).
ktest_arrange0 <- ktest %>% arrange(Segment)
kroll_arrange0 <- kroll %>% arrange(Segment)
corr1 <- cor(ktest_arrange0$resp_rate, kroll_arrange0$resp_rate, use = "complete.obs")
round(corr1, 3)
## [1] 0.915
4. Fit a beta-binomial model to the test data: What is the
parameter estimate for the first shape parameter a?
Provide your answer with three decimals separated by a dot, not a
comma (e.g. 0.123).
ktest <- ktest %>%
mutate(nonx_s = m_s-x_s)
ktest_arrange0 <- ktest %>%
mutate(nonx_s = m_s-x_s)
We run the MLE Estimator:
fit <- vglm(cbind(ktest_arrange0$x_s, ktest_arrange0$nonx_s) ~ 1, betabinomialff, trace=TRUE)
## VGLM linear loop 1 : loglikelihood = -201.76139
## VGLM linear loop 2 : loglikelihood = -200.56819
## VGLM linear loop 3 : loglikelihood = -200.54941
## VGLM linear loop 4 : loglikelihood = -200.54812
## VGLM linear loop 5 : loglikelihood = -200.54804
## VGLM linear loop 6 : loglikelihood = -200.54804
## VGLM linear loop 7 : loglikelihood = -200.54804
a <- Coef(fit)[[1]]
b <- Coef(fit)[[2]]
round(a, 3)
## [1] 0.439
5. What is the shape of the beta distribution you estimate?
x <- seq(0,.05,length=1000)
par(mai=c(.9,.8,.2,.2))
hist(ktest$resp_rate, density=10, breaks=100, main="Distribution of response rates across segments", xlab="segment-specific probability of response")
curve(dbeta(x, a, b), add = TRUE, type="l", col="red")
6. How many segments would you target using the Beta-Binomial
model?
ktest1 <- ktest %>%
mutate(post_mean_resp = (a+x_s)/(a+b+m_s))
## [1] 66
Comparison Plot:
plot(ktest1$resp_rate, xaxt="n",col="red",xlab="RFM segments",ylab="response rate (x/n) and posterior mean response rate")
points(ktest1$post_mean_resp, col='blue')
legend('topleft',legend=c("estimate response rate", "posterior expected response rate"),col=c("red","blue"), pch=1)
axis(1, at = 1:126, labels=ktest1$Segment, cex.axis=0.7, las=2)
abline(h=brk)
text(120, brk, "breakeven", cex=1, pos=3, col="black")
7. Does the posterior mean response rate fit the rollout
response rate better than the test response rate?
Calculate the correlation as in Question 3.
#need to arrange!
ktest_arrange <- ktest1 %>% arrange(Segment)
kroll_arrange <- kroll %>% arrange(Segment)
corr1 <- cor(ktest_arrange$resp_rate, kroll_arrange$resp_rate, use = "complete.obs")
round(corr1, 3) #0.915
## [1] 0.915
corr2 <- cor(ktest_arrange$post_mean_resp, kroll_arrange$resp_rate, use = "complete.obs")
round(corr2, 3) #0.916
## [1] 0.916
8. Calculate the Return on Investment (ROI) of targeting using the
posterior mean.
For the 71 segments we observe rollout outcomes for, calculate the
return on investment of targeting using the posterior mean. Use the data
on the actual number of customers mailed and responses, along with
margin and cost per marketing, in your calculation.
Provide your answer with zero decimals without the percent sign
(e.g. 120).
We Calculate ROI for 71 segments
# what about the return on investment ROI?
sum_profit = sum(kroll2$RFMprofit*kroll2$Roll_s)
sum_cost = sum(kroll2$RFMcost*kroll2$Roll_s)
roi <- sum_profit/sum_cost
## ROI: 401 %
LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMjogUkZNIEFuYWx5c2lzIg0KYXV0aG9yOiAiRGFuaWVsIFJlZGVsIg0KZGF0ZTogIjIwMjItMTEtMDMiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCnJtKGxpc3QgPSBscygpKQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoZ3Rvb2xzKQ0KbGlicmFyeShWR0FNKQ0KbGlicmFyeShyZWFkcikNCmBgYA0KDQojIyBDYXNlIDENCg0KQmVuJ3MgS25pY2sgS25hY2tzIHNlbGxzIGEgY29uc3VtZXIgZHVyYWJsZSBwcm9kdWN0IHdpdGggYSB1bml0IG1hcmdpbiBvZiBcJDE2MS41MCBhbmQgcGVyIGN1c3RvbWVyIG1haWxpbmcgY29zdHMgb2YgXCQwLjMzNDMuIFRoZXkgaGF2ZSBmb3JtZWQgMTI2IHNlZ21lbnRzIGJhc2VkIG9uIHBhc3QgcHVyY2hhc2UgaGlzdG9yeS4gVGhleSBkbyBhIHRlc3QgbWFpbGluZyB0byAzLjI0JSBvZiB0aGVpciBkYXRhYmFzZS4gWW91IGNhbiBzZWUgdGhlIG91dGNvbWVzIG9mIHRoZSB0ZXN0IGluIGZpbGUgKmtuaWNrX2tuYWNrX3Rlc3QuY3N2Ki4gVGhlIGNvbHVtbnMgYXJlIHNlZ21lbnQgbnVtYmVyLCB0aGUgbnVtYmVyIG9mIHBlb3BsZSBpbiB0aGF0IHNlZ21lbnQgdGhhdCB3ZXJlIG1haWxlZCwgYW5kIHRoZSBudW1iZXIgb2YgcGVvcGxlIHdobyByZXNwb25kZWQuDQoNCmBgYHtyIGltcG9ydCwgbWVzc2FnZT1GQUxTRX0NCmt0ZXN0IDwtIHJlYWRfY3N2KCJrbmlja19rbmFja190ZXN0LmNzdiIpDQpgYGANCg0KU2V0dGluZyB0aGUgcGFyYW1ldGVyczoNCg0KYGBge3J9DQptIDwtIDE2MS41MA0KYyA8LSAwLjMzNDMNCm5zZWcgPC0gMTI2DQp0c2l6ZSA8LSAwLjAzMjQNCmBgYA0KDQojIyMgMS4gV2hhdCBpcyB0aGUgcmVzcG9uc2UgYnJlYWtldmVuIHRocmVzaG9sZCBmb3IgbWFpbGluZz8NCg0KKlByb3ZpZGUgeW91ciBhbnN3ZXIgd2l0aCBmb3VyIGRlY2ltYWxzIHNlcGFyYXRlZCBieSBhIGRvdCwgbm90IGEgY29tbWEgKGUuZy4gMC4xMjM0KSouDQoNCmBgYHtyfQ0KYnJrID0gYy9tDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0V9DQpjYXQoIkJyZWFrZXZlbiBQb2ludDoiLCByb3VuZChicmssNCkpDQpgYGANCg0KIyMjIDIuIEhvdyBtYW55IHNlZ21lbnRzIHdvdWxkIHlvdSB0YXJnZXQgKG91dCBvZiAxMjYpPw0KDQoqUHJvdmlkZSBhIG51bWJlciAoZS5nLiAzNCkqLg0KDQpgYGB7cn0NCmt0ZXN0IDwtIGt0ZXN0ICU+JSANCiAgbXV0YXRlKHJlc3BfcmF0ZSA9IHhfcy9tX3MpICU+JSANCiAgYXJyYW5nZShkZXNjKHJlc3BfcmF0ZSkpDQprdGVzdCA8LSBhcy5kYXRhLmZyYW1lKGt0ZXN0KQ0KDQpicCA8LSBiYXJwbG90KGt0ZXN0Wyw3XSkNCmF4aXMoMSwgYXQgPSBicFssMV0sIGxhYmVscz1rdGVzdFssMV0sIGNleC5heGlzPTAuNywgbGFzPTIpDQphYmxpbmUoaD1icmspDQp0ZXh0KDg1LCBicmssICJicmVha2V2ZW4iLCBjZXg9MSwgcG9zPTMsIGNvbD0iYmxhY2siKQ0KYGBgDQoNCkhvdyBtYW55IHNlZ21lbnRzIHNob3VsZCBiZSB0YXJnZXRlZD8gV2hhdCBzZWdtZW50cyBhcmUgdGhleT8gQXMgYSBwZXJjZW50YWdlIG9mIHRoZSB0b3RhbCBzZWdtZW50cz8NCg0KYGBge3J9DQpuX3NlZ21lbnRzIDwtIHN1bShrdGVzdCRyZXNwX3JhdGUgPj0gYnJrKQ0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KY2F0KCJPcHRpbWFsIE51bWJlciBvZiBzZWdtZW50czoiLCBuX3NlZ21lbnRzKQ0KYGBgDQoNCiMjIENhc2UgMg0KDQpUaGUgY29tcGFueSBlbmRlZCB1cCByb2xsaW5nIG91dCB0byA3MSBzZWdtZW50cy4gU2VlIHRoZSBmaWxlICprbmlja19rbmFja19yb2xsLmNzdiogZm9yIHRoZSBzZWdtZW50cywgd2hldGhlciB0aGV5IHdlcmUgcm9sbGVkIG91dCB0bywgdGhlIG51bWJlciBvZiBjdXN0b21lcnMgcm9sbGVkIG91dCB0byBpbiBlYWNoIHNlZ21lbnQsIGFuZCB0aGUgcmVzcG9uc2VzLg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCmtyb2xsIDwtIHJlYWRfY3N2KCJrbmlja19rbmFja19yb2xsLmNzdiIpDQpgYGANCg0KWW91IGNhbiBub3cgY29tcGFyZSB0aGUgdGVzdCByZXNwb25zZSByYXRlIGFuZCB0aGUgcm9sbG91dCByZXNwb25zZSByYXRlcyAoZm9yIHRoZSA3MSBzZWdtZW50cyB0aGF0IHdlcmUgcm9sbGVkIG91dCB0bykuDQoNCmBgYHtyfQ0Ka3JvbGwgPC0ga3JvbGwgJT4lIA0KICBtdXRhdGUocmVzcF9yYXRlID0gY2FzZV93aGVuKFJlc3Bfcz09IDAgfiAwICwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IFJlc3Bfcy9Sb2xsX3MpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhyZXNwX3JhdGUpKQ0Ka3JvbGwxIDwtIGtyb2xsWyFpcy5uYShrcm9sbCRSZXNwX3MpLCBdICMgNzEgc2VnbWVudHMNCmBgYA0KDQpIb3cgd2VsbCBkbyB0ZXN0IHJhdGVzIHByZWRpY3Qgcm9sbCByYXRlcz8gT25lIHdheSB0byBtZWFzdXJlIHRoaXMgaXMgdGhlIGNvcnJlbGF0aW9uLiBJZiB0aGV5IHByZWRpY3QgcGVyZmVjdGx5LCB0aGlzIHdvdWxkIGJlIDEuDQoNCiMjIyAzLiBDYWxjdWxhdGUgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGVzdCBhbmQgcm9sbCByYXRlcy4NCg0KKlByb3ZpZGUgeW91ciBhbnN3ZXIgd2l0aCB0aHJlZSBkZWNpbWFscyBzZXBhcmF0ZWQgYnkgYSBkb3QsIG5vdCBhIGNvbW1hIChoaW50OyBpbiB0aGUgY29yIGZ1bmN0aW9uIHVzZSwgdXNlID0gImNvbXBsZXRlLm9icyIpKi4NCg0KYGBge3J9DQprdGVzdF9hcnJhbmdlMCA8LSBrdGVzdCAlPiUgYXJyYW5nZShTZWdtZW50KQ0Ka3JvbGxfYXJyYW5nZTAgPC0ga3JvbGwgJT4lIGFycmFuZ2UoU2VnbWVudCkNCg0KY29ycjEgPC0gY29yKGt0ZXN0X2FycmFuZ2UwJHJlc3BfcmF0ZSwga3JvbGxfYXJyYW5nZTAkcmVzcF9yYXRlLCB1c2UgPSAiY29tcGxldGUub2JzIikNCg0Kcm91bmQoY29ycjEsIDMpDQpgYGANCg0KIyMjIDQuIEZpdCBhIGJldGEtYmlub21pYWwgbW9kZWwgdG8gdGhlICp0ZXN0IGRhdGEqOiBXaGF0IGlzIHRoZSBwYXJhbWV0ZXIgZXN0aW1hdGUgZm9yIHRoZSBmaXJzdCBzaGFwZSBwYXJhbWV0ZXIgYT8NCg0KKlByb3ZpZGUgeW91ciBhbnN3ZXIgd2l0aCB0aHJlZSBkZWNpbWFscyBzZXBhcmF0ZWQgYnkgYSBkb3QsIG5vdCBhIGNvbW1hIChlLmcuIDAuMTIzKSouDQoNCmBgYHtyfQ0Ka3Rlc3QgPC0ga3Rlc3QgJT4lIA0KICBtdXRhdGUobm9ueF9zID0gbV9zLXhfcykNCmt0ZXN0X2FycmFuZ2UwIDwtIGt0ZXN0ICU+JSANCiAgbXV0YXRlKG5vbnhfcyA9IG1fcy14X3MpDQpgYGANCg0KV2UgcnVuIHRoZSBNTEUgRXN0aW1hdG9yOg0KDQpgYGB7ciwgY2FjaGU9VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmZpdCA8LSB2Z2xtKGNiaW5kKGt0ZXN0X2FycmFuZ2UwJHhfcywga3Rlc3RfYXJyYW5nZTAkbm9ueF9zKSB+IDEsIGJldGFiaW5vbWlhbGZmLCB0cmFjZT1UUlVFKQ0KYSA8LSBDb2VmKGZpdClbWzFdXQ0KYiA8LSBDb2VmKGZpdClbWzJdXSANCg0Kcm91bmQoYSwgMykNCmBgYA0KDQojIyMgNS4gV2hhdCBpcyB0aGUgc2hhcGUgb2YgdGhlIGJldGEgZGlzdHJpYnV0aW9uIHlvdSBlc3RpbWF0ZT8NCg0KYGBge3J9DQp4IDwtIHNlcSgwLC4wNSxsZW5ndGg9MTAwMCkNCg0KcGFyKG1haT1jKC45LC44LC4yLC4yKSkNCmhpc3Qoa3Rlc3QkcmVzcF9yYXRlLCBkZW5zaXR5PTEwLCBicmVha3M9MTAwLCBtYWluPSJEaXN0cmlidXRpb24gb2YgcmVzcG9uc2UgcmF0ZXMgYWNyb3NzIHNlZ21lbnRzIiwgeGxhYj0ic2VnbWVudC1zcGVjaWZpYyBwcm9iYWJpbGl0eSBvZiByZXNwb25zZSIpDQpjdXJ2ZShkYmV0YSh4LCBhLCBiKSwgYWRkID0gVFJVRSwgIHR5cGU9ImwiLCBjb2w9InJlZCIpDQoNCmBgYA0KDQojIyMgNi4gSG93IG1hbnkgc2VnbWVudHMgd291bGQgeW91IHRhcmdldCB1c2luZyB0aGUgQmV0YS1CaW5vbWlhbCBtb2RlbD8NCg0KYGBge3J9DQprdGVzdDEgPC0ga3Rlc3QgJT4lIA0KICBtdXRhdGUocG9zdF9tZWFuX3Jlc3AgPSAoYSt4X3MpLyhhK2IrbV9zKSkNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnN1bShrdGVzdDEkcG9zdF9tZWFuX3Jlc3AgPj0gYnJrKQ0KYGBgDQoNCkNvbXBhcmlzb24gUGxvdDoNCg0KYGBge3J9DQoNCnBsb3Qoa3Rlc3QxJHJlc3BfcmF0ZSwgeGF4dD0ibiIsY29sPSJyZWQiLHhsYWI9IlJGTSBzZWdtZW50cyIseWxhYj0icmVzcG9uc2UgcmF0ZSAoeC9uKSBhbmQgcG9zdGVyaW9yIG1lYW4gcmVzcG9uc2UgcmF0ZSIpDQpwb2ludHMoa3Rlc3QxJHBvc3RfbWVhbl9yZXNwLCBjb2w9J2JsdWUnKQ0KbGVnZW5kKCd0b3BsZWZ0JyxsZWdlbmQ9YygiZXN0aW1hdGUgcmVzcG9uc2UgcmF0ZSIsICJwb3N0ZXJpb3IgZXhwZWN0ZWQgcmVzcG9uc2UgcmF0ZSIpLGNvbD1jKCJyZWQiLCJibHVlIiksIHBjaD0xKQ0KYXhpcygxLCBhdCA9IDE6MTI2LCBsYWJlbHM9a3Rlc3QxJFNlZ21lbnQsIGNleC5heGlzPTAuNywgbGFzPTIpDQphYmxpbmUoaD1icmspDQp0ZXh0KDEyMCwgYnJrLCAiYnJlYWtldmVuIiwgY2V4PTEsIHBvcz0zLCBjb2w9ImJsYWNrIikNCmBgYA0KDQojIyMgNy4gRG9lcyB0aGUgcG9zdGVyaW9yIG1lYW4gcmVzcG9uc2UgcmF0ZSBmaXQgdGhlICpyb2xsb3V0IHJlc3BvbnNlKiByYXRlIGJldHRlciB0aGFuIHRoZSB0ZXN0IHJlc3BvbnNlIHJhdGU/DQoNCipDYWxjdWxhdGUgdGhlIGNvcnJlbGF0aW9uIGFzIGluIFF1ZXN0aW9uIDMqLg0KDQpgYGB7cn0NCiNuZWVkIHRvIGFycmFuZ2UhDQoNCmt0ZXN0X2FycmFuZ2UgPC0ga3Rlc3QxICU+JSBhcnJhbmdlKFNlZ21lbnQpDQprcm9sbF9hcnJhbmdlIDwtIGtyb2xsICU+JSBhcnJhbmdlKFNlZ21lbnQpDQoNCmNvcnIxIDwtIGNvcihrdGVzdF9hcnJhbmdlJHJlc3BfcmF0ZSwga3JvbGxfYXJyYW5nZSRyZXNwX3JhdGUsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQ0Kcm91bmQoY29ycjEsIDMpICMwLjkxNQ0KDQpjb3JyMiA8LSBjb3Ioa3Rlc3RfYXJyYW5nZSRwb3N0X21lYW5fcmVzcCwga3JvbGxfYXJyYW5nZSRyZXNwX3JhdGUsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQ0Kcm91bmQoY29ycjIsIDMpICMwLjkxNg0KDQpgYGANCg0KIyMjIDguIENhbGN1bGF0ZSB0aGUgUmV0dXJuIG9uIEludmVzdG1lbnQgKFJPSSkgb2YgdGFyZ2V0aW5nIHVzaW5nIHRoZSAqKnBvc3RlcmlvciBtZWFuKiouDQoNCkZvciB0aGUgNzEgc2VnbWVudHMgd2Ugb2JzZXJ2ZSByb2xsb3V0IG91dGNvbWVzIGZvciwgY2FsY3VsYXRlIHRoZSByZXR1cm4gb24gaW52ZXN0bWVudCBvZiB0YXJnZXRpbmcgdXNpbmcgdGhlIHBvc3RlcmlvciBtZWFuLiBVc2UgdGhlIGRhdGEgb24gdGhlIGFjdHVhbCBudW1iZXIgb2YgY3VzdG9tZXJzIG1haWxlZCBhbmQgcmVzcG9uc2VzLCBhbG9uZyB3aXRoIG1hcmdpbiBhbmQgY29zdCBwZXIgbWFya2V0aW5nLCBpbiB5b3VyIGNhbGN1bGF0aW9uLg0KDQoqUHJvdmlkZSB5b3VyIGFuc3dlciB3aXRoIHplcm8gZGVjaW1hbHMgd2l0aG91dCB0aGUgcGVyY2VudCBzaWduIChlLmcuIDEyMCkqLg0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCmtyb2xsMiA8LSBjYmluZChrcm9sbF9hcnJhbmdlLCBwb3N0X21lYW5fcmVzcD1rdGVzdF9hcnJhbmdlJHBvc3RfbWVhbl9yZXNwKQ0KYGBgDQoNCldlIENhbGN1bGF0ZSBST0kgZm9yIDcxIHNlZ21lbnRzDQoNCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQ0KIyMgUHJvZml0cw0Ka3JvbGwyIDwtIGtyb2xsMiAlPiUgDQogIGZpbHRlcihgUm9sbD9gID09ICJZIikgJT4lIA0KICBtdXRhdGUoUkZNaW5jb21lID0gcG9zdF9tZWFuX3Jlc3AqbSwgUkZNY29zdCA9IGMsIFJGTXByb2ZpdCA9IHBvc3RfbWVhbl9yZXNwKm0gLSBjLCANCiAgICAgICAgIFRvdGFsX2luY29tZSA9IFJvbGxfcypSRk1pbmNvbWUsIFRvdGFsX2Nvc3QgPSBSb2xsX3MqUkZNY29zdCwgVG90YWxfcHJvZml0ID0gUm9sbF9zKlJGTXByb2ZpdCkNCmBgYA0KDQpgYGB7cn0NCiMgd2hhdCBhYm91dCB0aGUgcmV0dXJuIG9uIGludmVzdG1lbnQgUk9JPw0KDQpzdW1fcHJvZml0ID0gc3VtKGtyb2xsMiRSRk1wcm9maXQqa3JvbGwyJFJvbGxfcykNCnN1bV9jb3N0ID0gc3VtKGtyb2xsMiRSRk1jb3N0Kmtyb2xsMiRSb2xsX3MpDQpyb2kgPC0gc3VtX3Byb2ZpdC9zdW1fY29zdCANCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmNhdCgiUk9JOiIsIHJvdW5kKHJvaSoxMDAsMCksIiUiKQ0KYGBgDQo=