Exercise 2: Exploratory Data Analysis
Zillow provides data on home prices, including median rental price per square feet and the median estimated home value. There are many more statistics provided by zillow in this website that you can explore.
zillow_url1 <- paste0("http://files.zillowstatic.com/research/public/City/",
"City_MedianRentalPricePerSqft_AllHomes.csv")
zillow_url2 <- paste0("http://files.zillowstatic.com/research/public/City/",
"City_ZriPerSqft_AllHomes.csv")
price_per_sqft <- read_csv(zillow_url1)
Parsed with column specification:
cols(
.default = col_double(),
RegionName = col_character(),
State = col_character(),
Metro = col_character(),
CountyName = col_character(),
SizeRank = col_integer()
)
See spec(...) for full column specifications.
value_per_sqft <- read_csv(zillow_url2)
Parsed with column specification:
cols(
.default = col_double(),
RegionID = col_integer(),
RegionName = col_character(),
State = col_character(),
Metro = col_character(),
CountyName = col_character(),
SizeRank = col_integer()
)
See spec(...) for full column specifications.
# First, we tidy the datasets:
price_per_sqft <- price_per_sqft %>%
select(-Metro) %>%
gather(`2010-01`:`2018-08`, key = "date", value = "price")
value_per_sqft <- value_per_sqft %>%
select(RegionID:CountyName, `2011-01`:`2018-08`) %>%
gather(`2011-01`:`2018-08`, key = "date", value = "value")
# Do the inner join:
home_per_sqft <- price_per_sqft %>%
inner_join(value_per_sqft)
Joining, by = c("RegionName", "State", "CountyName", "date")
# Format dates:
home_per_sqft <- home_per_sqft %>%
mutate(date = paste0(date, "-01"),
date = as.Date(date))
# We filter to only top 10 priciest states this year
# excluding DC and HI:
top10_States <- home_per_sqft %>%
filter(date >= as.Date("2018-01-01")) %>%
filter(State != "HI", State != "DC") %>%
group_by(State) %>%
summarise(price = mean(price, na.rm = TRUE)) %>%
top_n(10)
Selecting by price
home_per_sqft <- home_per_sqft %>%
filter(State %in% top10_States$State)
#rm(price_per_sqft, value_per_sqft)
The most expensive states by median home price per sq. ft. are:
top10_States$State
[1] "CA" "CO" "CT" "MA" "MD" "ME" "NH" "NJ" "NY" "RI"
- For the current year (2018), using the filtered
home_per_sqft
dataset show the relationship between the value and the price per square foot of homes in 10 chosen states. The value is a dollar-denominated and estimated by Zillow.
- Is there a correlation between the price and the value per square foot?
- Are there any atypical trends you observe?
- Are there any clusters of regions that are pricier than, expected based on their estimated value? Find, the
RegionName
for an example these outliers, and see if it makes sense.
- Are there any clusters of regions that have higher value than, expected based on how cheap they are? Find, the
RegionName
for an example of these outliers, and see if it makes sense.
Collapse the data by computing the average of the median home price per square foot for each (state, date) pair. Then show the price trend over time for each of the top 10 states.
Now, subset your home_per_sqft
dataset to homes located in the Bay Area:
bayarea_counties <- c("Alameda", "Napa", "Santa Clara", "Contra Costa",
"San Francisco", "Solano", "Marin", "San Mateo",
"Sonoma")
bay_area_home <- home_per_sqft %>%
filter(CountyName %in% bayarea_counties)
Filter your observations to the once after “2013-09-01”. Then generate a boxplot of home prices per square foot for the following regions:
cities <- c("Oakland", "San Francisco", "Berkeley", "San Jose",
"San Mateo", "Redwood City", "Mountain View", "Napa",
"South San Francisco", "Menlo Park", "Cupertino")
For which region were the median home prices per square foot highest over the most recent 5 years period?
- For the same regions plot the prices over time.
If you are curious, you can repeat this type of analysis for the listing prices of home sales using the following files from zillow: ‘City_MedianListingPricePerSqft_AllHomes.csv’, ‘City_Zhvi_AllHomes.csv’.
Exercise 3: Interactive graphics with plotly
First generate the following (x,y,z) coordinates for your scatter 3D plot:
library(plotly)
Attaching package: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
theta <- 2 * pi * runif(1000)
phi <- pi * runif(1000)
x <- sin(phi) * cos(theta)
y <- sin(phi) * sin(theta)
z <- cos(phi)
dat <- data.frame(x, y, z)
Generate a scatter plot with (x, y, z) coordinates, just computed. What do you observe?
Now generate new points as follows.
N <- 10
theta <- rep(2*pi * seq(0, 1, length.out = 100), N)
phi <- rep(pi * seq(0, 1, length.out = N*100))
x <- sin(phi) * cos(theta)
y <- sin(phi) * sin(theta)
z <- cos(phi)
dat <- data.frame(x, y, z)
Then, use plotly
to create a 3D scatter point plot and a separate line plot. Color the points by their ordering in the data-frame.
LS0tCnRpdGxlOiAiTGVjdHVyZSA1OiBFeGVyY2lzZXMiCmRhdGU6IE9jdG9iZXIgMTF0aCwgMjAxOApvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQotLS0KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgoKIyBFeGVyY2lzZSAxOiBEYXRhIE1hbmlwdWxhdGlvbgoKIyMgUGFydCAxOiBUaGUgbWFwIGZ1bmN0aW9ucyBmcm9tIGBwdXJycmAgCgphLiBVc2UgYHB1cnJyYCBmdW5jdGlvbnMgdG8gZmluZCB0aGUgY29sdW1uIG1lYW5zIGZvciBgbXRjYXJzYCBkYXRhc2V0LgpOb3RlIHRoYXQgdGhlIG1lYW4gcGVyZm9ybWFuY2UgY2FycyBpbiB0aGlzIGRhdGFzZXQgaXMgdmVyeSAKcG9vci4gVGhhdCdzIGJlY2F1c2UgdGhlc2UgbW9kZWxzIGFyZSBmcm9tIHRoZSA3MHMhCgpiLiBVc2UgYHB1cnJyYCBmdW5jdGlvbnMgdG8gZ2VuZXJhdGUgMTAgcmFuZG9tIG5vcm1hbHMgZm9yIGVhY2ggb2YgCnRoZSBtZWFuIHBhcmFtZXRlcjogJFxtdSA9IC0xOCwgNSwgMTAsIDMwJC4KCgpjLiBXaGF0IGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gcnVubmluZyBgYG1hcCgxOjUsIHJ1bmlmKWAgCmBtYXAobGlzdCgxOjUpLCBybm9ybSlgLCBgbWFwKGxpc3QoMSwgMiwgMywgNCwgNSksIHJub3JtKWAgYW5kIApgbWFwKDE6NSwgcm5vcm0sIG4gPSA1KWA/CgoKZC4gRm9yIGxvb3Bpbmcgb3ZlciBtdWx0aXBsZSBhcmd1bWVudHMgeW91IGNhbiB1c2UgYG1hcDIoKWAgb3IgYHBtYXAoKWAKZnVuY3Rpb24uIFVzZSBgbWFwMigpYCB0byBnZW5lcmF0ZSA1IHJhbmRvbSBudW1iZXJzIHdpdGggZm9yIAplYWNoIHBhaXIgb2YgbWVhbiwgYW5kIHN0YW5kYXJkIGRldnRhaW9uIGVxdWFsIHRvOgpgYygyLCAxKSwgYygtMywgMTApLCBjKDIwLCAwLjEpLCBjKC0xNywgMilgLgoKIyMgUGFydCAyOiBNZXJnaW5nCgphLiBJZGVudGlmeSB0aGUga2V5cyBpbiB0aGUgZm9sbG93aW5nIGRhdGFzZXRzCih5b3UgbWlnaHQgbmVlZCB0byBpbnN0YWxsIHNvbWUgcGFja2FnZXMgYW5kIHJlYWQgc29tZSBkb2N1bWVudGF0aW9uKToKCgoqIGBMYWhtYW46OkJhdHRpbmdgCiogYG5hc2F3ZWF0aGVyOjphdG1vc2AKKiBgZ2dwbG90Mjo6ZGlhbW9uZHNgCgoKYi4gQWRkIHRoZSBsb2NhdGlvbiAoaS5lLiB0aGUgbGF0IGFuZCBsb24pIG9mIHRoZSBkZXN0aW5hdGlvbiBhaXJwb3J0ICAKdG8gYGZsaWdodHNgIGRhdGFzZXQgZnJvbSBgbnljZmxpZ2h0czEzYCBwYWNrYWdlLiBUaGVuLCBjb25zdHJ1Y3QgYSBuZXcKZGF0YSB0YWJsZSBgbWVhbl9kZWxheWAgY29udGFpbmluZyBpbmZvcm1hdGlvbiBvbiB0aGUgYXZlcmFnZSBhcnJpdmFsCmRlbGF5IGZvciBlYWNoIGRlc3RpbmF0aW9uIGFpcnBvcnQgYW5kIGl0cyBsb2NhdGlvbiAoaS5lLiB0aGUgbGF0IGFuZCBsb24pLgpSZW1lbWJlciB0aGF0IHNvbWUgb2YgdGhlIHJlY29yZHMgYXJlIG1pc3NpbmcsIHNvIHVzZSBgbmEucm0gPSBUUlVFYAp3aGVuIGNvbXB1dGluZyBtZWFucy4KCgojIyBQYXJ0IDM6IEV4cG9ydCBkYXRhc2V0cwoKYS4gRXhwb3J0IHRoZSBgbWVhbl9kZWxheWAgZGF0YSBhcyBhICcudHN2JyBmaWxlLiBTYXZlIGl0IG9uIHlvdXIgIkRlc2t0b3AiCnRoZW4gY2hlY2sgdGhlIGZpbGUgd2FzIHByb3Blcmx5IHNhdmVkLCB0aGVuIGRlbGV0ZSBpdC4KCmIuIENoZWNrIHdoYXQgb2JqZWN0cyBhcmUgY3VycmVudGx5IHN0b3JlZCBpbiB5b3VyIGVudmlyb25tZW50IHVzaW5nIGBscygpYC4KU2F2ZSBgbWVhbl9kZWxheWAgYXMgYSBSIG9iamVjdCB1c2luZyBgc2F2ZVJEUygpYCBmdW5jdGlvbiB0byBzYXZlCml0IGFzIGFtICcucmRzJyBmaWxlLiBUaGVuLCBzZWxlY3QgMiBkaWZmZXJlbnQgb2JqZWN0cyBmcm9tIHRoZSBlbnZpcm9ubWVudCAKYW5kIHVzZSBgc2F2ZSgpYCB0byBzYXZlIHRoZW0gdG8gYW4gJy5yZGEnIGZpbGUuIFRoZW4sIHJlbW92ZSB0aGVzZQpvYmplY3RzIGFuZCB0aGUgYG1lYW5fZGVsYXlgIHRpYmJsZS4gQ2hlY2sgdGhhdCB5b3UgY2FuIHJlbG9hZCB0aGVzZQpvYmplY3RzIGZyb20gZmlsZXMgeW91IHNhdmVkLgoKCiMgRXhlcmNpc2UgMjogRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcwoKWmlsbG93IHByb3ZpZGVzIGRhdGEgb24gaG9tZSBwcmljZXMsIGluY2x1ZGluZyBtZWRpYW4gcmVudGFsCnByaWNlIHBlciBzcXVhcmUgZmVldCBhbmQgdGhlIG1lZGlhbiBlc3RpbWF0ZWQgaG9tZSB2YWx1ZS4gClRoZXJlIGFyZSBtYW55IG1vcmUgc3RhdGlzdGljcyBwcm92aWRlZCBieSB6aWxsb3cgaW4gW3RoaXMgd2Vic2l0ZV0oaHR0cHM6Ly93d3cuemlsbG93LmNvbS9yZXNlYXJjaC9kYXRhLykgCnRoYXQgeW91IGNhbiBleHBsb3JlLgoKYGBge3J9CnppbGxvd191cmwxIDwtIHBhc3RlMCgiaHR0cDovL2ZpbGVzLnppbGxvd3N0YXRpYy5jb20vcmVzZWFyY2gvcHVibGljL0NpdHkvIiwKICAgICAgICAgICAgICAgICAgICAiQ2l0eV9NZWRpYW5SZW50YWxQcmljZVBlclNxZnRfQWxsSG9tZXMuY3N2IikKemlsbG93X3VybDIgPC0gcGFzdGUwKCJodHRwOi8vZmlsZXMuemlsbG93c3RhdGljLmNvbS9yZXNlYXJjaC9wdWJsaWMvQ2l0eS8iLAogICAgICAgICAgICAgICAgICAgICAgIkNpdHlfWnJpUGVyU3FmdF9BbGxIb21lcy5jc3YiKQoKcHJpY2VfcGVyX3NxZnQgPC0gcmVhZF9jc3YoemlsbG93X3VybDEpIAp2YWx1ZV9wZXJfc3FmdCA8LSByZWFkX2Nzdih6aWxsb3dfdXJsMikgCmBgYAoKCmBgYHtyfQojIEZpcnN0LCB3ZSB0aWR5IHRoZSBkYXRhc2V0czoKcHJpY2VfcGVyX3NxZnQgPC0gcHJpY2VfcGVyX3NxZnQgJT4lCiAgICBzZWxlY3QoLU1ldHJvKSAlPiUKICAgIGdhdGhlcihgMjAxMC0wMWA6YDIwMTgtMDhgLCBrZXkgPSAiZGF0ZSIsIHZhbHVlID0gInByaWNlIikgCnZhbHVlX3Blcl9zcWZ0IDwtIHZhbHVlX3Blcl9zcWZ0ICU+JQogICAgc2VsZWN0KFJlZ2lvbklEOkNvdW50eU5hbWUsIGAyMDExLTAxYDpgMjAxOC0wOGApICU+JQogICAgZ2F0aGVyKGAyMDExLTAxYDpgMjAxOC0wOGAsIGtleSA9ICJkYXRlIiwgdmFsdWUgPSAidmFsdWUiKSAKCiMgRG8gdGhlIGlubmVyIGpvaW46CmhvbWVfcGVyX3NxZnQgPC0gcHJpY2VfcGVyX3NxZnQgJT4lCiAgICBpbm5lcl9qb2luKHZhbHVlX3Blcl9zcWZ0KQoKIyBGb3JtYXQgZGF0ZXM6CmhvbWVfcGVyX3NxZnQgPC0gaG9tZV9wZXJfc3FmdCAlPiUKICAgIG11dGF0ZShkYXRlID0gcGFzdGUwKGRhdGUsICItMDEiKSwKICAgICAgICAgICBkYXRlID0gYXMuRGF0ZShkYXRlKSkKCiMgV2UgZmlsdGVyIHRvIG9ubHkgdG9wIDEwIHByaWNpZXN0IHN0YXRlcyB0aGlzIHllYXIKIyBleGNsdWRpbmcgREMgYW5kIEhJOgp0b3AxMF9TdGF0ZXMgPC0gaG9tZV9wZXJfc3FmdCAlPiUKICAgIGZpbHRlcihkYXRlID49IGFzLkRhdGUoIjIwMTgtMDEtMDEiKSkgJT4lCiAgICBmaWx0ZXIoU3RhdGUgIT0gIkhJIiwgU3RhdGUgIT0gIkRDIikgJT4lCiAgICBncm91cF9ieShTdGF0ZSkgJT4lCiAgICBzdW1tYXJpc2UocHJpY2UgPSBtZWFuKHByaWNlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICAgIHRvcF9uKDEwKQoKaG9tZV9wZXJfc3FmdCA8LSBob21lX3Blcl9zcWZ0ICU+JQogICAgZmlsdGVyKFN0YXRlICVpbiUgdG9wMTBfU3RhdGVzJFN0YXRlKQoKI3JtKHByaWNlX3Blcl9zcWZ0LCB2YWx1ZV9wZXJfc3FmdCkKYGBgCgpUaGUgbW9zdCBleHBlbnNpdmUgc3RhdGVzIGJ5IG1lZGlhbiBob21lIHByaWNlIHBlciBzcS4gZnQuIGFyZToKCmBgYHtyfQp0b3AxMF9TdGF0ZXMkU3RhdGUKYGBgCgoKYS4gRm9yIHRoZSBjdXJyZW50IHllYXIgKDIwMTgpLCAKdXNpbmcgdGhlIGZpbHRlcmVkIGBob21lX3Blcl9zcWZ0YCBkYXRhc2V0IHNob3cgdGhlIHJlbGF0aW9uc2hpcApiZXR3ZWVuIHRoZSB2YWx1ZSBhbmQgdGhlIHByaWNlIHBlciBzcXVhcmUgZm9vdCBvZiBob21lcyBpbgoxMCBjaG9zZW4gc3RhdGVzLiBUaGUgdmFsdWUgaXMgYSBkb2xsYXItZGVub21pbmF0ZWQgCmFuZCBlc3RpbWF0ZWQgYnkgWmlsbG93LgoKKiBJcyB0aGVyZSBhIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHByaWNlIGFuZCB0aGUgdmFsdWUgcGVyIHNxdWFyZSBmb290PwoqIEFyZSB0aGVyZSBhbnkgYXR5cGljYWwgdHJlbmRzIHlvdSBvYnNlcnZlPwoqIEFyZSB0aGVyZSBhbnkgY2x1c3RlcnMgb2YgcmVnaW9ucyB0aGF0IGFyZSBwcmljaWVyIHRoYW4sCmV4cGVjdGVkIGJhc2VkIG9uIHRoZWlyIGVzdGltYXRlZCB2YWx1ZT8gRmluZCwgdGhlIGBSZWdpb25OYW1lYApmb3IgYW4gZXhhbXBsZSB0aGVzZSBvdXRsaWVycywgYW5kIHNlZSBpZiBpdCBtYWtlcyBzZW5zZS4KKiBBcmUgdGhlcmUgYW55IGNsdXN0ZXJzIG9mIHJlZ2lvbnMgdGhhdCBoYXZlIGhpZ2hlciB2YWx1ZSB0aGFuLApleHBlY3RlZCBiYXNlZCBvbiBob3cgY2hlYXAgdGhleSBhcmU/IEZpbmQsIHRoZSBgUmVnaW9uTmFtZWAKZm9yIGFuIGV4YW1wbGUgb2YgdGhlc2Ugb3V0bGllcnMsIGFuZCBzZWUgaWYgaXQgbWFrZXMgc2Vuc2UuCgoKYi4gQ29sbGFwc2UgdGhlIGRhdGEgYnkgY29tcHV0aW5nIHRoZSBhdmVyYWdlIG9mIHRoZSBtZWRpYW4gaG9tZSBwcmljZSAKcGVyIHNxdWFyZSBmb290IGZvciBlYWNoIChzdGF0ZSwgZGF0ZSkgcGFpci4gVGhlbiBzaG93IHRoZSBwcmljZSB0cmVuZCAKb3ZlciB0aW1lIGZvciBlYWNoIG9mIHRoZSB0b3AgMTAgc3RhdGVzLiAKCgpjLiBOb3csIHN1YnNldCB5b3VyIGBob21lX3Blcl9zcWZ0YCBkYXRhc2V0IHRvIGhvbWVzIGxvY2F0ZWQgaW4gdGhlIEJheSBBcmVhOgoKYGBge3J9CmJheWFyZWFfY291bnRpZXMgPC0gYygiQWxhbWVkYSIsICJOYXBhIiwgIlNhbnRhIENsYXJhIiwgIkNvbnRyYSBDb3N0YSIsIAogICAgICAgICAgICAgICAgICAgICAgIlNhbiBGcmFuY2lzY28iLCAiU29sYW5vIiwgIk1hcmluIiwgIlNhbiBNYXRlbyIsIAogICAgICAgICAgICAgICAgICAgICAgIlNvbm9tYSIpCmJheV9hcmVhX2hvbWUgPC0gaG9tZV9wZXJfc3FmdCAlPiUKICAgIGZpbHRlcihDb3VudHlOYW1lICVpbiUgYmF5YXJlYV9jb3VudGllcykKYGBgCgohW10oaHR0cDovL3d3dy5iYXlhcmVhY2Vuc3VzLmNhLmdvdi9ncmFwaGljcy9CYXlBcmVhQ291bnRpZXMxMC5naWYpCgpGaWx0ZXIgeW91ciBvYnNlcnZhdGlvbnMgdG8gdGhlIG9uY2UgYWZ0ZXIgIjIwMTMtMDktMDEiLgpUaGVuIGdlbmVyYXRlIGEgYm94cGxvdCBvZiBob21lIHByaWNlcyBwZXIgc3F1YXJlIGZvb3QgZm9yCnRoZSBmb2xsb3dpbmcgcmVnaW9uczogCgpgYGB7cn0KY2l0aWVzIDwtIGMoIk9ha2xhbmQiLCAiU2FuIEZyYW5jaXNjbyIsICJCZXJrZWxleSIsICJTYW4gSm9zZSIsCiAgICAgICAgICAgICJTYW4gTWF0ZW8iLCAiUmVkd29vZCBDaXR5IiwgIk1vdW50YWluIFZpZXciLCAiTmFwYSIsCiAgICAgICAgICAgICJTb3V0aCBTYW4gRnJhbmNpc2NvIiwgIk1lbmxvIFBhcmsiLCAiQ3VwZXJ0aW5vIikKYGBgCgpGb3Igd2hpY2ggcmVnaW9uIHdlcmUgdGhlIG1lZGlhbiBob21lIHByaWNlcyBwZXIgc3F1YXJlIGZvb3QKaGlnaGVzdCBvdmVyIHRoZSBtb3N0IHJlY2VudCA1IHllYXJzIHBlcmlvZD8KCgpkLiBGb3IgdGhlIHNhbWUgcmVnaW9ucyBwbG90IHRoZSBwcmljZXMgb3ZlciB0aW1lLgoKCklmIHlvdSBhcmUgY3VyaW91cywgeW91IGNhbiByZXBlYXQgdGhpcyB0eXBlIG9mIGFuYWx5c2lzIGZvciAKdGhlIGxpc3RpbmcgcHJpY2VzIG9mIGhvbWUgc2FsZXMgdXNpbmcgdGhlIGZvbGxvd2luZwpmaWxlcyBmcm9tIHppbGxvdzogJ0NpdHlfTWVkaWFuTGlzdGluZ1ByaWNlUGVyU3FmdF9BbGxIb21lcy5jc3YnLAonQ2l0eV9aaHZpX0FsbEhvbWVzLmNzdicuCgoKIyBFeGVyY2lzZSAzOiBJbnRlcmFjdGl2ZSBncmFwaGljcyB3aXRoIGBwbG90bHlgCgpGaXJzdCBnZW5lcmF0ZSB0aGUgZm9sbG93aW5nICh4LHkseikgY29vcmRpbmF0ZXMgZm9yIHlvdXIgc2NhdHRlciAzRCBwbG90OgpgYGB7cn0KbGlicmFyeShwbG90bHkpCnRoZXRhIDwtIDIgKiBwaSAqIHJ1bmlmKDEwMDApCnBoaSA8LSBwaSAqIHJ1bmlmKDEwMDApCnggPC0gc2luKHBoaSkgKiBjb3ModGhldGEpCnkgPC0gc2luKHBoaSkgKiBzaW4odGhldGEpCnogPC0gY29zKHBoaSkKZGF0IDwtIGRhdGEuZnJhbWUoeCwgeSwgeikKYGBgCgphLiBHZW5lcmF0ZSBhIHNjYXR0ZXIgcGxvdCB3aXRoICh4LCB5LCB6KSBjb29yZGluYXRlcywganVzdCBjb21wdXRlZC4gV2hhdCBkbwp5b3Ugb2JzZXJ2ZT8KCmIuIE5vdyBnZW5lcmF0ZSBuZXcgcG9pbnRzIGFzIGZvbGxvd3MuIAoKYGBge3J9Ck4gPC0gMTAKdGhldGEgPC0gcmVwKDIqcGkgKiBzZXEoMCwgMSwgbGVuZ3RoLm91dCA9IDEwMCksIE4pCnBoaSA8LSByZXAocGkgKiBzZXEoMCwgMSwgbGVuZ3RoLm91dCA9IE4qMTAwKSkKeCA8LSBzaW4ocGhpKSAqIGNvcyh0aGV0YSkKeSA8LSBzaW4ocGhpKSAqIHNpbih0aGV0YSkKeiA8LSBjb3MocGhpKQpkYXQgPC0gZGF0YS5mcmFtZSh4LCB5LCB6KQpgYGAKClRoZW4sIHVzZSBgcGxvdGx5YCB0byBjcmVhdGUgYSAzRCAKc2NhdHRlciBwb2ludCBwbG90IGFuZCBhIHNlcGFyYXRlIGxpbmUgcGxvdC4gQ29sb3IgdGhlIHBvaW50cyBieQp0aGVpciBvcmRlcmluZyBpbiB0aGUgZGF0YS1mcmFtZS4KCgo=