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=