library(dplyr)
library(ggplot2)
library(readr)
library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ lubridate 1.9.4 ✔ tibble 3.2.1
✔ purrr 1.0.2 ✔ tidyr 1.3.1── Conflicts ──────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(conflicted)
library(skimr)
library(ggcorrplot)
#Reading the data set and printing first 5rows
data <- read.csv("dataset.csv")
conflicted::conflicts_prefer(dplyr::filter)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::filter over any other package.
# Filtering dataset where explicit is "True" and taking a sample of 9,000 rows
sample_data <- data |> filter(explicit == "True") |> sample_n(9000)
data <- sample_data
nrow(data)
[1] 9000
# Display first few rows
head(data)
Step 1: Grouping Data and Analyzing Probabilities
Group 1: Grouping by Track Genre
group1 <- data |>
group_by(track_genre) |>
summarise(Count = n(), Mean_Popularity = mean(popularity, na.rm = TRUE))
print(group1)
The genres with lower counts have a lower probability of occurrence
in the dataset(black-metal).
ggplot(group1, aes(x =reorder(track_genre, -Mean_Popularity), y = Mean_Popularity)) +
geom_bar(stat = "identity", fill = "blue") +
labs(title = "Mean Popularity by Track Genre",
x = "Track Genre",
y = "Mean Popularity") +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5,size = 6),
panel.grid.major.x = element_blank(), # Remove vertical grid lines
plot.margin = margin(b = 100) # Add bottom margin for labels
)

The graph shows a clear hierarchy in genre popularity, with the
highest-rated genres reaching nearly 60 on the popularity scale while
the lowest-rated genres fall below 10, demonstrating significant
variation in listener preferences.
Group2: Grouping by Genre and Explicit Content
group2 <- data |>
group_by(track_genre, explicit) |>
summarise(Count = n(), Median_Danceability = median(danceability, na.rm = TRUE))
`summarise()` has grouped output by 'track_genre'. You can override using the `.groups` argument.
print(group2)
# Create faceted bar chart
ggplot(group2, aes(x = reorder(track_genre, -Median_Danceability),
y = Median_Danceability,
fill = explicit)) +
geom_bar(stat = "identity") +
facet_wrap(~explicit) +
scale_fill_manual(values = c( "True" = "coral")) +
labs(title = "Median Danceability by Genre and Explicit Content",
x = "Track Genre",
y = "Median Danceability",
fill = "Explicit") +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 90,
hjust = 1, vjust = 0.5,
size = 4),
legend.position = "none",
panel.grid.major.x = element_blank(),
plot.margin = margin(b = 100)
)

By grouping and graph, we can know-
Most genres have significantly more non-explicit tracks than explicit
ones - for example, acoustic has 948 non-explicit vs only 52 explicit
tracks, and ambient has 995 non-explicit tracks, showing a clear
preference for clean content in these genres.
Alternative music shows the highest proportion of explicit content
(164 explicit tracks out of 1000) compared to other genres, while
ambient and afrobeat have very few explicit tracks (less than 20
each).
Danceability varies notably between explicit and non-explicit tracks
within the same genre - for instance, alternative music shows higher
danceability in explicit tracks (0.663) compared to non-explicit ones
(0.538), while acoustic music shows the opposite trend with non-explicit
tracks being more danceable (0.564 vs 0.491).
Group 3: Grouping by Binned Popularity Scores
data <- data |> mutate(Popularity_Bin = cut(popularity, breaks = 5))
group3 <- data |>
group_by(track_genre, Popularity_Bin) |>
summarise(Count = n())
`summarise()` has grouped output by 'track_genre'. You can override using the `.groups` argument.
print(group3)
ggplot(group3, aes(x = Count, y = track_genre, fill = Popularity_Bin)) +
geom_bar(stat = "identity", position = "stack") +
scale_fill_brewer(palette = "RdYlBu") +
labs(title = "Distribution of Popularity Scores Across Music Genres",
x = "Number of Tracks",
y = "Genre") +
theme_minimal() +
theme(
axis.text.y = element_text(size = 5, # Increase text size
margin = margin(r = 10)), # Add right margin
plot.margin = margin(r = 8), # Add right margin for legend
legend.position = "right",
legend.title = element_text(size = 10),
legend.text = element_text(size = 9),
panel.grid.major.y = element_blank()
)

Popularity Distribution is Skewed: Most genres show a concentration
of tracks in the middle popularity ranges (20-60), with very few tracks
reaching the highest popularity bracket (80-100). For example, acoustic
has only 1 track in the highest range but 518 tracks in the middle range
(40-60).
Genre-Specific Patterns: Different genres show distinct popularity
patterns:
Acoustic music has a bell-shaped distribution with most tracks in the
middle ranges Afrobeat shows a left-skewed distribution with most tracks
in lower popularity ranges (482 tracks in the lowest bracket) Alt-rock
demonstrates a similar pattern to afrobeat with high counts in lower
popularity ranges Extreme Popularity is Rare: Across all genres, very
few tracks achieve the highest popularity bracket (80-100), suggesting
that reaching top popularity is exceptionally challenging regardless of
genre. The middle ranges (20-60) contain the bulk of tracks for most
genres.
Step 2 : Investigating Combinations of Genre and Explicitness
category_combinations <- data |> count(track_genre, explicit)
print(category_combinations)
# Find missing combinations
all_combinations <- expand.grid(unique(data$track_genre), unique(data$explicit))
missing_combinations <- anti_join(all_combinations, category_combinations, by = c("Var1" = "track_genre", "Var2" ="explicit"))
print(missing_combinations)
Step 3 : Finding combinations
# Find missing combinations
all_combinations <- expand.grid(unique(data$track_genre), unique(data$explicit))
missing_combinations <- anti_join(all_combinations, category_combinations, by = c("Var1" = "track_genre", "Var2" ="explicit"))
print(missing_combinations)
# Most common combinations
common_combinations <- group3 |>
group_by(track_genre, Popularity_Bin) |>
summarise(Count = n()) |>
arrange(desc(Count))
# Least common combinations
least_common_combinations <- group3 |>
group_by(track_genre, Popularity_Bin) |>
summarise(Count = n()) |>
arrange(Count)
# Display the most common combinations
print("Most common combinations:")
head(common_combinations, 10) # Views top 10 most common combinations
# Display the least common combinations
print("Least common combinations:")
head(least_common_combinations, 10) # Views top 10 least common combinations
From the least common and most common combinations, we can notice- 1.
Music genres like “acoustic,” “afrobeat,” and “alt-rock” are spread
across multiple popularity bins.
2. The count distribution is relatively even across different popularity
bins.
3. Some genres may perform better in higher popularity ranges, like
“alt-rock.”
4. Certain genres, like “acoustic” and “afrobeat,” could appeal to niche
audiences.
Summary:
Grouping by different categorical variables reveals patterns in
occurrence probabilities. The rarest groups can be identified and
analyzed for anomalies. Missing genre-explicitness combinations hint at
structured gaps in the dataset. Visualizations enhance interpretability
and hypothesis testing.
Further Questions to Investigate-
What factors contribute to the rarity of high-popularity tracks
across all genres?
Is there a temporal component affecting popularity distributions?
How do other track features (danceability, energy) correlate with
these popularity patterns?
Are there regional or cultural factors influencing these
distributions?
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShjb25mbGljdGVkKQ0KbGlicmFyeShza2ltcikNCmxpYnJhcnkoZ2djb3JycGxvdCkNCmBgYA0KDQpgYGB7cn0NCiNSZWFkaW5nIHRoZSBkYXRhIHNldCBhbmQgcHJpbnRpbmcgZmlyc3QgNXJvd3MNCmRhdGEgPC0gcmVhZC5jc3YoImRhdGFzZXQuY3N2IikNCg0KY29uZmxpY3RlZDo6Y29uZmxpY3RzX3ByZWZlcihkcGx5cjo6ZmlsdGVyKQ0KDQojIEZpbHRlcmluZyBkYXRhc2V0IHdoZXJlIGV4cGxpY2l0IGlzICJUcnVlIiBhbmQgdGFraW5nIGEgc2FtcGxlIG9mIDksMDAwIHJvd3MNCnNhbXBsZV9kYXRhIDwtIGRhdGEgfD4gZmlsdGVyKGV4cGxpY2l0ID09ICJUcnVlIikgfD4gc2FtcGxlX24oOTAwMCkNCmRhdGEgPC0gc2FtcGxlX2RhdGENCm5yb3coZGF0YSkNCg0KIyBEaXNwbGF5IGZpcnN0IGZldyByb3dzDQpoZWFkKGRhdGEpDQpgYGANCiMjIyBTdGVwIDE6IEdyb3VwaW5nIERhdGEgYW5kIEFuYWx5emluZyBQcm9iYWJpbGl0aWVzDQojIyMgR3JvdXAgMTogR3JvdXBpbmcgYnkgVHJhY2sgR2VucmUNCmBgYHtyfQ0KZ3JvdXAxIDwtIGRhdGEgfD4gDQogIGdyb3VwX2J5KHRyYWNrX2dlbnJlKSB8Pg0KICBzdW1tYXJpc2UoQ291bnQgPSBuKCksIE1lYW5fUG9wdWxhcml0eSA9IG1lYW4ocG9wdWxhcml0eSwgbmEucm0gPSBUUlVFKSkNCnByaW50KGdyb3VwMSkNCmBgYA0KVGhlIGdlbnJlcyB3aXRoIGxvd2VyIGNvdW50cyBoYXZlIGEgbG93ZXIgcHJvYmFiaWxpdHkgb2Ygb2NjdXJyZW5jZSBpbiB0aGUgZGF0YXNldChibGFjay1tZXRhbCkuDQpgYGB7cn0NCg0KZ2dwbG90KGdyb3VwMSwgYWVzKHggPXJlb3JkZXIodHJhY2tfZ2VucmUsIC1NZWFuX1BvcHVsYXJpdHkpLCB5ID0gTWVhbl9Qb3B1bGFyaXR5KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJibHVlIikgKw0KICBsYWJzKHRpdGxlID0gIk1lYW4gUG9wdWxhcml0eSBieSBUcmFjayBHZW5yZSIsDQogICAgICAgeCA9ICJUcmFjayBHZW5yZSIsDQogICAgICAgeSA9ICJNZWFuIFBvcHVsYXJpdHkiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLjUsc2l6ZSA9IDYpLCAgDQogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLCAgICMgUmVtb3ZlIHZlcnRpY2FsIGdyaWQgbGluZXMNCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihiID0gMTAwKSAgICAgICAgICAgIyBBZGQgYm90dG9tIG1hcmdpbiBmb3IgbGFiZWxzDQogICkNCmBgYA0KVGhlIGdyYXBoIHNob3dzIGEgY2xlYXIgaGllcmFyY2h5IGluIGdlbnJlIHBvcHVsYXJpdHksIHdpdGggdGhlIGhpZ2hlc3QtcmF0ZWQgZ2VucmVzIHJlYWNoaW5nIG5lYXJseSA2MCBvbiB0aGUgcG9wdWxhcml0eSBzY2FsZSB3aGlsZSB0aGUgbG93ZXN0LXJhdGVkIGdlbnJlcyBmYWxsIGJlbG93IDEwLCBkZW1vbnN0cmF0aW5nIHNpZ25pZmljYW50IHZhcmlhdGlvbiBpbiBsaXN0ZW5lciBwcmVmZXJlbmNlcy4NCg0KIyMjIEdyb3VwMjogR3JvdXBpbmcgYnkgR2VucmUgYW5kIEV4cGxpY2l0IENvbnRlbnQNCmBgYHtyfQ0KZ3JvdXAyIDwtIGRhdGEgfD4NCiAgZ3JvdXBfYnkodHJhY2tfZ2VucmUsIGV4cGxpY2l0KSB8Pg0KICBzdW1tYXJpc2UoQ291bnQgPSBuKCksIE1lZGlhbl9EYW5jZWFiaWxpdHkgPSBtZWRpYW4oZGFuY2VhYmlsaXR5LCBuYS5ybSA9IFRSVUUpKQ0KcHJpbnQoZ3JvdXAyKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDcmVhdGUgZmFjZXRlZCBiYXIgY2hhcnQNCmdncGxvdChncm91cDIsIGFlcyh4ID0gcmVvcmRlcih0cmFja19nZW5yZSwgLU1lZGlhbl9EYW5jZWFiaWxpdHkpLCANCiAgICAgICAgICAgICAgICAgICB5ID0gTWVkaWFuX0RhbmNlYWJpbGl0eSwNCiAgICAgICAgICAgICAgICAgICBmaWxsID0gZXhwbGljaXQpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIGZhY2V0X3dyYXAofmV4cGxpY2l0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoICJUcnVlIiA9ICJjb3JhbCIpKSArDQogIGxhYnModGl0bGUgPSAiTWVkaWFuIERhbmNlYWJpbGl0eSBieSBHZW5yZSBhbmQgRXhwbGljaXQgQ29udGVudCIsDQogICAgICAgeCA9ICJUcmFjayBHZW5yZSIsDQogICAgICAgeSA9ICJNZWRpYW4gRGFuY2VhYmlsaXR5IiwNCiAgICAgICBmaWxsID0gIkV4cGxpY2l0IikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxLCB2anVzdCA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSA0KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgDQogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKGIgPSAxMDApIA0KICApDQpgYGANCiMjIyBCeSBncm91cGluZyBhbmQgZ3JhcGgsIHdlIGNhbiBrbm93LQ0KDQpNb3N0IGdlbnJlcyBoYXZlIHNpZ25pZmljYW50bHkgbW9yZSBub24tZXhwbGljaXQgdHJhY2tzIHRoYW4gZXhwbGljaXQgb25lcyAtIGZvciBleGFtcGxlLCBhY291c3RpYyBoYXMgOTQ4IG5vbi1leHBsaWNpdCB2cyBvbmx5IDUyIGV4cGxpY2l0IHRyYWNrcywgYW5kIGFtYmllbnQgaGFzIDk5NSBub24tZXhwbGljaXQgdHJhY2tzLCBzaG93aW5nIGEgY2xlYXIgcHJlZmVyZW5jZSBmb3IgY2xlYW4gY29udGVudCBpbiB0aGVzZSBnZW5yZXMuDQoNCkFsdGVybmF0aXZlIG11c2ljIHNob3dzIHRoZSBoaWdoZXN0IHByb3BvcnRpb24gb2YgZXhwbGljaXQgY29udGVudCAoMTY0IGV4cGxpY2l0IHRyYWNrcyBvdXQgb2YgMTAwMCkgY29tcGFyZWQgdG8gb3RoZXIgZ2VucmVzLCB3aGlsZSBhbWJpZW50IGFuZCBhZnJvYmVhdCBoYXZlIHZlcnkgZmV3IGV4cGxpY2l0IHRyYWNrcyAobGVzcyB0aGFuIDIwIGVhY2gpLg0KDQpEYW5jZWFiaWxpdHkgdmFyaWVzIG5vdGFibHkgYmV0d2VlbiBleHBsaWNpdCBhbmQgbm9uLWV4cGxpY2l0IHRyYWNrcyB3aXRoaW4gdGhlIHNhbWUgZ2VucmUgLSBmb3IgaW5zdGFuY2UsIGFsdGVybmF0aXZlIG11c2ljIHNob3dzIGhpZ2hlciBkYW5jZWFiaWxpdHkgaW4gZXhwbGljaXQgdHJhY2tzICgwLjY2MykgY29tcGFyZWQgdG8gbm9uLWV4cGxpY2l0IG9uZXMgKDAuNTM4KSwgd2hpbGUgYWNvdXN0aWMgbXVzaWMgc2hvd3MgdGhlIG9wcG9zaXRlIHRyZW5kIHdpdGggbm9uLWV4cGxpY2l0IHRyYWNrcyBiZWluZyBtb3JlIGRhbmNlYWJsZSAoMC41NjQgdnMgMC40OTEpLg0KDQojIyMgR3JvdXAgMzogR3JvdXBpbmcgYnkgQmlubmVkIFBvcHVsYXJpdHkgU2NvcmVzDQpgYGB7cn0NCmRhdGEgPC0gZGF0YSB8PiBtdXRhdGUoUG9wdWxhcml0eV9CaW4gPSBjdXQocG9wdWxhcml0eSwgYnJlYWtzID0gNSkpDQpncm91cDMgPC0gZGF0YSB8Pg0KICBncm91cF9ieSh0cmFja19nZW5yZSwgUG9wdWxhcml0eV9CaW4pIHw+DQogIHN1bW1hcmlzZShDb3VudCA9IG4oKSkNCnByaW50KGdyb3VwMykNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZ3JvdXAzLCBhZXMoeCA9IENvdW50LCB5ID0gdHJhY2tfZ2VucmUsIGZpbGwgPSBQb3B1bGFyaXR5X0JpbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIikgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlJkWWxCdSIpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUG9wdWxhcml0eSBTY29yZXMgQWNyb3NzIE11c2ljIEdlbnJlcyIsDQogICAgICAgeCA9ICJOdW1iZXIgb2YgVHJhY2tzIiwNCiAgICAgICB5ID0gIkdlbnJlIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNSwgICAgIyBJbmNyZWFzZSB0ZXh0IHNpemUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IG1hcmdpbihyID0gMTApKSwgIyBBZGQgcmlnaHQgbWFyZ2luDQogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDgpLCAgICAgICAgICAgICMgQWRkIHJpZ2h0IG1hcmdpbiBmb3IgbGVnZW5kDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksDQogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpIA0KICApDQpgYGANClBvcHVsYXJpdHkgRGlzdHJpYnV0aW9uIGlzIFNrZXdlZDogTW9zdCBnZW5yZXMgc2hvdyBhIGNvbmNlbnRyYXRpb24gb2YgdHJhY2tzIGluIHRoZSBtaWRkbGUgcG9wdWxhcml0eSByYW5nZXMgKDIwLTYwKSwgd2l0aCB2ZXJ5IGZldyB0cmFja3MgcmVhY2hpbmcgdGhlIGhpZ2hlc3QgcG9wdWxhcml0eSBicmFja2V0ICg4MC0xMDApLiBGb3IgZXhhbXBsZSwgYWNvdXN0aWMgaGFzIG9ubHkgMSB0cmFjayBpbiB0aGUgaGlnaGVzdCByYW5nZSBidXQgNTE4IHRyYWNrcyBpbiB0aGUgbWlkZGxlIHJhbmdlICg0MC02MCkuDQoNCkdlbnJlLVNwZWNpZmljIFBhdHRlcm5zOiBEaWZmZXJlbnQgZ2VucmVzIHNob3cgZGlzdGluY3QgcG9wdWxhcml0eSBwYXR0ZXJuczoNCg0KQWNvdXN0aWMgbXVzaWMgaGFzIGEgYmVsbC1zaGFwZWQgZGlzdHJpYnV0aW9uIHdpdGggbW9zdCB0cmFja3MgaW4gdGhlIG1pZGRsZSByYW5nZXMNCkFmcm9iZWF0IHNob3dzIGEgbGVmdC1za2V3ZWQgZGlzdHJpYnV0aW9uIHdpdGggbW9zdCB0cmFja3MgaW4gbG93ZXIgcG9wdWxhcml0eSByYW5nZXMgKDQ4MiB0cmFja3MgaW4gdGhlIGxvd2VzdCBicmFja2V0KQ0KQWx0LXJvY2sgZGVtb25zdHJhdGVzIGEgc2ltaWxhciBwYXR0ZXJuIHRvIGFmcm9iZWF0IHdpdGggaGlnaCBjb3VudHMgaW4gbG93ZXIgcG9wdWxhcml0eSByYW5nZXMNCkV4dHJlbWUgUG9wdWxhcml0eSBpcyBSYXJlOiBBY3Jvc3MgYWxsIGdlbnJlcywgdmVyeSBmZXcgdHJhY2tzIGFjaGlldmUgdGhlIGhpZ2hlc3QgcG9wdWxhcml0eSBicmFja2V0ICg4MC0xMDApLCBzdWdnZXN0aW5nIHRoYXQgcmVhY2hpbmcgdG9wIHBvcHVsYXJpdHkgaXMgZXhjZXB0aW9uYWxseSBjaGFsbGVuZ2luZyByZWdhcmRsZXNzIG9mIGdlbnJlLiBUaGUgbWlkZGxlIHJhbmdlcyAoMjAtNjApIGNvbnRhaW4gdGhlIGJ1bGsgb2YgdHJhY2tzIGZvciBtb3N0IGdlbnJlcy4NCg0KIyMjIFN0ZXAgMiA6IEludmVzdGlnYXRpbmcgQ29tYmluYXRpb25zIG9mIEdlbnJlIGFuZCBFeHBsaWNpdG5lc3MNCmBgYHtyfQ0KY2F0ZWdvcnlfY29tYmluYXRpb25zIDwtIGRhdGEgfD4gY291bnQodHJhY2tfZ2VucmUsIGV4cGxpY2l0KQ0KcHJpbnQoY2F0ZWdvcnlfY29tYmluYXRpb25zKQ0KYGBgDQoNCiMjIyBTdGVwIDMgOiBGaW5kaW5nIGNvbWJpbmF0aW9ucw0KYGBge3J9DQojIEZpbmQgbWlzc2luZyBjb21iaW5hdGlvbnMNCmFsbF9jb21iaW5hdGlvbnMgPC0gZXhwYW5kLmdyaWQodW5pcXVlKGRhdGEkdHJhY2tfZ2VucmUpLCB1bmlxdWUoZGF0YSRleHBsaWNpdCkpDQptaXNzaW5nX2NvbWJpbmF0aW9ucyA8LSBhbnRpX2pvaW4oYWxsX2NvbWJpbmF0aW9ucywgY2F0ZWdvcnlfY29tYmluYXRpb25zLCBieSA9IGMoIlZhcjEiID0gInRyYWNrX2dlbnJlIiwgIlZhcjIiID0iZXhwbGljaXQiKSkNCnByaW50KG1pc3NpbmdfY29tYmluYXRpb25zKQ0KYGBgDQoNCmBgYHtyfQ0KIyBNb3N0IGNvbW1vbiBjb21iaW5hdGlvbnMNCmNvbW1vbl9jb21iaW5hdGlvbnMgPC0gZ3JvdXAzIHw+DQogIGdyb3VwX2J5KHRyYWNrX2dlbnJlLCBQb3B1bGFyaXR5X0JpbikgfD4NCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKSB8Pg0KICBhcnJhbmdlKGRlc2MoQ291bnQpKQ0KDQojIExlYXN0IGNvbW1vbiBjb21iaW5hdGlvbnMNCmxlYXN0X2NvbW1vbl9jb21iaW5hdGlvbnMgPC0gZ3JvdXAzIHw+DQogIGdyb3VwX2J5KHRyYWNrX2dlbnJlLCBQb3B1bGFyaXR5X0JpbikgfD4NCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKSB8Pg0KICBhcnJhbmdlKENvdW50KQ0KDQojIERpc3BsYXkgdGhlIG1vc3QgY29tbW9uIGNvbWJpbmF0aW9ucw0KcHJpbnQoIk1vc3QgY29tbW9uIGNvbWJpbmF0aW9uczoiKQ0KaGVhZChjb21tb25fY29tYmluYXRpb25zLCAxMCkgICMgVmlld3MgdG9wIDEwIG1vc3QgY29tbW9uIGNvbWJpbmF0aW9ucw0KDQojIERpc3BsYXkgdGhlIGxlYXN0IGNvbW1vbiBjb21iaW5hdGlvbnMNCnByaW50KCJMZWFzdCBjb21tb24gY29tYmluYXRpb25zOiIpDQpoZWFkKGxlYXN0X2NvbW1vbl9jb21iaW5hdGlvbnMsIDEwKSAgIyBWaWV3cyB0b3AgMTAgbGVhc3QgY29tbW9uIGNvbWJpbmF0aW9ucw0KDQpgYGANCkZyb20gdGhlIGxlYXN0IGNvbW1vbiBhbmQgbW9zdCBjb21tb24gY29tYmluYXRpb25zLCB3ZSBjYW4gbm90aWNlLQ0KMS4gTXVzaWMgZ2VucmVzIGxpa2UgImFjb3VzdGljLCIgImFmcm9iZWF0LCIgYW5kICJhbHQtcm9jayIgYXJlIHNwcmVhZCBhY3Jvc3MgbXVsdGlwbGUgcG9wdWxhcml0eSBiaW5zLiAgDQoyLiBUaGUgY291bnQgZGlzdHJpYnV0aW9uIGlzIHJlbGF0aXZlbHkgZXZlbiBhY3Jvc3MgZGlmZmVyZW50IHBvcHVsYXJpdHkgYmlucy4gIA0KMy4gU29tZSBnZW5yZXMgbWF5IHBlcmZvcm0gYmV0dGVyIGluIGhpZ2hlciBwb3B1bGFyaXR5IHJhbmdlcywgbGlrZSAiYWx0LXJvY2suIiAgDQo0LiBDZXJ0YWluIGdlbnJlcywgbGlrZSAiYWNvdXN0aWMiIGFuZCAiYWZyb2JlYXQsIiBjb3VsZCBhcHBlYWwgdG8gbmljaGUgYXVkaWVuY2VzLg0KDQoNCiMjIyBTdW1tYXJ5Og0KR3JvdXBpbmcgYnkgZGlmZmVyZW50IGNhdGVnb3JpY2FsIHZhcmlhYmxlcyByZXZlYWxzIHBhdHRlcm5zIGluIG9jY3VycmVuY2UgcHJvYmFiaWxpdGllcy4NClRoZSByYXJlc3QgZ3JvdXBzIGNhbiBiZSBpZGVudGlmaWVkIGFuZCBhbmFseXplZCBmb3IgYW5vbWFsaWVzLg0KTWlzc2luZyBnZW5yZS1leHBsaWNpdG5lc3MgY29tYmluYXRpb25zIGhpbnQgYXQgc3RydWN0dXJlZCBnYXBzIGluIHRoZSBkYXRhc2V0Lg0KVmlzdWFsaXphdGlvbnMgZW5oYW5jZSBpbnRlcnByZXRhYmlsaXR5IGFuZCBoeXBvdGhlc2lzIHRlc3RpbmcuDQoNCiMjIyBGdXJ0aGVyIFF1ZXN0aW9ucyB0byBJbnZlc3RpZ2F0ZS0NCldoYXQgZmFjdG9ycyBjb250cmlidXRlIHRvIHRoZSByYXJpdHkgb2YgaGlnaC1wb3B1bGFyaXR5IHRyYWNrcyBhY3Jvc3MgYWxsIGdlbnJlcz8NCg0KSXMgdGhlcmUgYSB0ZW1wb3JhbCBjb21wb25lbnQgYWZmZWN0aW5nIHBvcHVsYXJpdHkgZGlzdHJpYnV0aW9ucz8NCg0KSG93IGRvIG90aGVyIHRyYWNrIGZlYXR1cmVzIChkYW5jZWFiaWxpdHksIGVuZXJneSkgY29ycmVsYXRlIHdpdGggdGhlc2UgcG9wdWxhcml0eSBwYXR0ZXJucz8NCg0KQXJlIHRoZXJlIHJlZ2lvbmFsIG9yIGN1bHR1cmFsIGZhY3RvcnMgaW5mbHVlbmNpbmcgdGhlc2UgZGlzdHJpYnV0aW9ucz8NCg==