Have you ever wanted to have a collection of something? It could be
trading cards, board games, art pieces, or whatever you want them to be.
In this project, we’ll suppose you collect something with a lot of data
- cars!
Your car collection is almost complete - it’s just missing one thing.
You think about it for a while, then it comes to you - you don’t have a
car from 1985! But there are so many cars from 1985 available for you to
collect! How will you know which 1985 car you will buy for your
collection?
Luckily for you, we have a dataset that stores precisely that
information. This dataset comes from the UCI Machine Learning Repository
and is linked here. This dataset has been adapted so that the variable
names are along the first rows.
As you’ll notice in this project, though, this dataset isn’t ready
for analysis yet. You will have to make some changes along the way to
clean and tidy up the dataset. Do that, and you’ll have the ability to
perform a great analysis!
Loading and Inspecting the Data
1.What good is an analysis if we don’t even have the tools to perform
the said analysis? Some of the tools you will need for this analysis are
the readr and dplyr tidyverse packages. Load the libraries at the top of
the notebook.Rmd file so you can access the functions you will need
later on.
Task 1
# load libraries
library(readr)
library(dplyr)
2.The last tool we need is the data itself! The file cars85.csv
stores the data that comes from the UCI Machine Learning Repository.
Load the file into a dataframe called cars to get started.
Task 2
# load data
cars <- read_csv('cars85.csv')
cars
3.It’s always a good idea to inspect the data you load into R. It
helps you to know what you are working with. Inspect cars with head()
and summary().
What kind of information do you have? What can you do with this
information?
Each row in this dataframe is a single car, and each column stores
some characteristic about that car. You want to get the best value for
your collection, so you want to analyze as much as you can before
buying. Doing so will help you make your choice easier!
Task 3
# inspect data
head(cars)
summary()
錯誤發生在 summary.default(): 缺少引數 "object",也沒有預設值
Clean the Data
4.After inspecting the dataframe, you notice something odd about the
normalized_losses column. This column has a lot of entries that are
question marks (?). This variable is not worth looking at since we don’t
have all the cars’ expected losses.
Let’s remove this column from the dataset. Select all columns from
cars but normalized_losses. Save your new dataframe to cars.
Task 4
# select columns
cars <- cars %>%
select(-normalized_losses)
cars
5.Print the column names of cars. Are they clear and descriptive?
Task 5
# view columns
colnames(cars)
[1] "symboling" "make" "fuel_type" "aspiration" "num_of_doors"
[6] "body_style" "drive_wheels" "engine_location" "wheel_base" "length"
[11] "width" "height" "curb_weight" "engine_type" "num_of_cylinders"
[16] "engine_size" "fuel_system" "bore" "stroke" "compression_ratio"
[21] "horsepower" "peak_rpm" "city_mpg" "highway_mpg" "price"
6.You know, symboling doesn’t say anything to you at first glance.
According to the UCI webpage, the symboling variable represents the
car’s risk factor. That variable name doesn’t seem to go with the
description. You should simplify this variable name to have it make more
sense.
Update that column name in cars as follows:
symboling -> risk_factor Print the column names of cars to confirm
the names of the columns have changed.
Task 6
# rename column
cars <- cars %>%
rename(risk_factor = symboling)
colnames(cars)
[1] "risk_factor" "make" "fuel_type" "aspiration" "num_of_doors"
[6] "body_style" "drive_wheels" "engine_location" "wheel_base" "length"
[11] "width" "height" "curb_weight" "engine_type" "num_of_cylinders"
[16] "engine_size" "fuel_system" "bore" "stroke" "compression_ratio"
[21] "horsepower" "peak_rpm" "city_mpg" "highway_mpg" "price"
7.Your car collection means a lot to you. You want each car to be of
value to you. What better way to do that than to buy a car with a lot of
miles-per-gallon on the highways? To determine this, first, suppose only
cars exceeding 30 mpg on the highways interest you. You seek to measure
how different each car’s highway mpg is from your 30 mpg threshold.
Create a variable called mpg_threshold with the value 30.
Task 7
# define threshold
mpg_threshold <- 30
mpg_threshold
[1] 30
8.Add a new column to cars called mpg_diff_from_threshold. This will
measure how far each car’s highway mpg is from 30 mpg. View the updated
cars dataframe.
Task 8
# add column
cars <- cars %>%
mutate(mpg_diff_from_threshold = highway_mpg - mpg_threshold)
cars
Filter and Arrange Rows
9.You’ll add a car to your collection only if it gets more than 30
miles per gallon on the highways. Filter the rows of cars to find all
the cars where mpg_diff_from_threshold is greater than 0. Save this new
dataframe to mpg_exceeds_threshold and view it.
Task 9
# filter rows
mpg_exceeds_threshold <- cars %>%
filter(mpg_diff_from_threshold > 0)
mpg_exceeds_threshold
10.Which cars have the highest miles per gallon on the highways? To
find this, arrange the rows of mpg_exceeds_threshold by
mpg_diff_from_threshold descending. Save this new dataframe as
mpg_exceeds_threshold.
Task 10
# arrange rows
mpg_exceeds_threshold <- cars %>%
arrange(desc(mpg_diff_from_threshold))
mpg_exceeds_threshold
11.Now suppose you want your next car to have a large engine. Order
the rows of cars by engine_size descending. Save the new data frame to
ordered_by_engine_size. View ordered_by_engine_size.
Task 11
# order rows by engine size
ordered_by_engine_size <- cars %>%
arrange(desc(engine_size))
ordered_by_engine_size
Specifying the Make of the Car
12.There’s a lot of makes of cars to choose from, but you may prefer
one over the others. Which make do you prefer the most? Create a
variable called chosen_make that contains the make you want to check.
The hint below provides the list of makes to choose from.
*Hint : The list below provides the makes for you to choose from.
Pick a make and assign it to chosen_make. alfa-romero, audi, bmw,
chevrolet, dodge, honda, isuzu, jaguar, mazda, mercedes-benz, mercury,
mitsubishi, nissan, peugot, plymouth, porsche, renault, saab, subaru,
toyota, volkswagen, volvo
Task 12
# choose make
chosen_make <- "mercedes-benz"
chosen_make
[1] "mercedes-benz"
13.Filter cars to only include rows where the make column is equal to
chosen_make. Save the new dataframe to chosen_make_details.
Task 13
# filter rows by make
chosen_make_details <- cars %>%
filter(make == chosen_make)
chosen_make_details
14.Order the rows of chosen_make_details by engine_size descending
and save the new dataframe to chosen_make_details. View
chosen_make_details.
How large are the engines in each of the cars from that make that you
chose? You can change the make stored in chosen_make to check out the
engine sizes for other makes.
Task 14
# order filtered rows by engine size
chosen_make_details <- cars %>%
arrange(desc(engine_size))
chosen_make_details
15.The process of buying a new car can cause a lot of stress - you
don’t want to buy a car you won’t like! You’ve now seen how performing
an analysis can ease some of the stress of making the decision of which
car to buy. You also get to add a nice new car to your collection! Great
work!
LS0tDQp0aXRsZTogIkV4cGxvcmUgdGhlIDE5ODUgQ2FycyBEYXRhc2V0Ig0KYXV0aG9yOiAiQW5uYWJlbCBLdW8iDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclWS0lbS0lZCAlSDolTScpYCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQpIYXZlIHlvdSBldmVyIHdhbnRlZCB0byBoYXZlIGEgY29sbGVjdGlvbiBvZiBzb21ldGhpbmc/IEl0IGNvdWxkIGJlIHRyYWRpbmcgY2FyZHMsIGJvYXJkIGdhbWVzLCBhcnQgcGllY2VzLCBvciB3aGF0ZXZlciB5b3Ugd2FudCB0aGVtIHRvIGJlLiBJbiB0aGlzIHByb2plY3QsIHdl4oCZbGwgc3VwcG9zZSB5b3UgY29sbGVjdCBzb21ldGhpbmcgd2l0aCBhIGxvdCBvZiBkYXRhIC0gY2FycyENCg0KWW91ciBjYXIgY29sbGVjdGlvbiBpcyBhbG1vc3QgY29tcGxldGUgLSBpdOKAmXMganVzdCBtaXNzaW5nIG9uZSB0aGluZy4gWW91IHRoaW5rIGFib3V0IGl0IGZvciBhIHdoaWxlLCB0aGVuIGl0IGNvbWVzIHRvIHlvdSAtIHlvdSBkb27igJl0IGhhdmUgYSBjYXIgZnJvbSAxOTg1ISBCdXQgdGhlcmUgYXJlIHNvIG1hbnkgY2FycyBmcm9tIDE5ODUgYXZhaWxhYmxlIGZvciB5b3UgdG8gY29sbGVjdCEgSG93IHdpbGwgeW91IGtub3cgd2hpY2ggMTk4NSBjYXIgeW91IHdpbGwgYnV5IGZvciB5b3VyIGNvbGxlY3Rpb24/DQoNCkx1Y2tpbHkgZm9yIHlvdSwgd2UgaGF2ZSBhIGRhdGFzZXQgdGhhdCBzdG9yZXMgcHJlY2lzZWx5IHRoYXQgaW5mb3JtYXRpb24uIFRoaXMgZGF0YXNldCBjb21lcyBmcm9tIHRoZSBVQ0kgTWFjaGluZSBMZWFybmluZyBSZXBvc2l0b3J5IGFuZCBpcyBsaW5rZWQgaGVyZS4gVGhpcyBkYXRhc2V0IGhhcyBiZWVuIGFkYXB0ZWQgc28gdGhhdCB0aGUgdmFyaWFibGUgbmFtZXMgYXJlIGFsb25nIHRoZSBmaXJzdCByb3dzLg0KDQpBcyB5b3XigJlsbCBub3RpY2UgaW4gdGhpcyBwcm9qZWN0LCB0aG91Z2gsIHRoaXMgZGF0YXNldCBpc27igJl0IHJlYWR5IGZvciBhbmFseXNpcyB5ZXQuIFlvdSB3aWxsIGhhdmUgdG8gbWFrZSBzb21lIGNoYW5nZXMgYWxvbmcgdGhlIHdheSB0byBjbGVhbiBhbmQgdGlkeSB1cCB0aGUgZGF0YXNldC4gRG8gdGhhdCwgYW5kIHlvdeKAmWxsIGhhdmUgdGhlIGFiaWxpdHkgdG8gcGVyZm9ybSBhIGdyZWF0IGFuYWx5c2lzIQ0KDQojIExvYWRpbmcgYW5kIEluc3BlY3RpbmcgdGhlIERhdGENCg0KMS5XaGF0IGdvb2QgaXMgYW4gYW5hbHlzaXMgaWYgd2UgZG9u4oCZdCBldmVuIGhhdmUgdGhlIHRvb2xzIHRvIHBlcmZvcm0gdGhlIHNhaWQgYW5hbHlzaXM/IFNvbWUgb2YgdGhlIHRvb2xzIHlvdSB3aWxsIG5lZWQgZm9yIHRoaXMgYW5hbHlzaXMgYXJlIHRoZSByZWFkciBhbmQgZHBseXIgdGlkeXZlcnNlIHBhY2thZ2VzLiBMb2FkIHRoZSBsaWJyYXJpZXMgYXQgdGhlIHRvcCBvZiB0aGUgbm90ZWJvb2suUm1kIGZpbGUgc28geW91IGNhbiBhY2Nlc3MgdGhlIGZ1bmN0aW9ucyB5b3Ugd2lsbCBuZWVkIGxhdGVyIG9uLg0KDQojIyBUYXNrIDENCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPVRSVUV9DQojIGxvYWQgbGlicmFyaWVzDQoNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KYGBgDQoNCjIuVGhlIGxhc3QgdG9vbCB3ZSBuZWVkIGlzIHRoZSBkYXRhIGl0c2VsZiEgVGhlIGZpbGUgY2Fyczg1LmNzdiBzdG9yZXMgdGhlIGRhdGEgdGhhdCBjb21lcyBmcm9tIHRoZSBVQ0kgTWFjaGluZSBMZWFybmluZyBSZXBvc2l0b3J5LiBMb2FkIHRoZSBmaWxlIGludG8gYSBkYXRhZnJhbWUgY2FsbGVkIGNhcnMgdG8gZ2V0IHN0YXJ0ZWQuDQoNCiMjIFRhc2sgMg0KYGBge3IgZXJyb3I9VFJVRX0NCiMgbG9hZCBkYXRhDQpjYXJzIDwtIHJlYWRfY3N2KCdjYXJzODUuY3N2JykNCmNhcnMNCmBgYA0KDQozLkl04oCZcyBhbHdheXMgYSBnb29kIGlkZWEgdG8gaW5zcGVjdCB0aGUgZGF0YSB5b3UgbG9hZCBpbnRvIFIuIEl0IGhlbHBzIHlvdSB0byBrbm93IHdoYXQgeW91IGFyZSB3b3JraW5nIHdpdGguIEluc3BlY3QgY2FycyB3aXRoIGhlYWQoKSBhbmQgc3VtbWFyeSgpLg0KDQpXaGF0IGtpbmQgb2YgaW5mb3JtYXRpb24gZG8geW91IGhhdmU/IFdoYXQgY2FuIHlvdSBkbyB3aXRoIHRoaXMgaW5mb3JtYXRpb24/DQoNCkVhY2ggcm93IGluIHRoaXMgZGF0YWZyYW1lIGlzIGEgc2luZ2xlIGNhciwgYW5kIGVhY2ggY29sdW1uIHN0b3JlcyBzb21lIGNoYXJhY3RlcmlzdGljIGFib3V0IHRoYXQgY2FyLiBZb3Ugd2FudCB0byBnZXQgdGhlIGJlc3QgdmFsdWUgZm9yIHlvdXIgY29sbGVjdGlvbiwgc28geW91IHdhbnQgdG8gYW5hbHl6ZSBhcyBtdWNoIGFzIHlvdSBjYW4gYmVmb3JlIGJ1eWluZy4gRG9pbmcgc28gd2lsbCBoZWxwIHlvdSBtYWtlIHlvdXIgY2hvaWNlIGVhc2llciENCg0KIyMgVGFzayAzDQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyBpbnNwZWN0IGRhdGENCmhlYWQoY2FycykNCnN1bW1hcnkoKQ0KYGBgDQoNCiMgQ2xlYW4gdGhlIERhdGENCg0KNC5BZnRlciBpbnNwZWN0aW5nIHRoZSBkYXRhZnJhbWUsIHlvdSBub3RpY2Ugc29tZXRoaW5nIG9kZCBhYm91dCB0aGUgbm9ybWFsaXplZF9sb3NzZXMgY29sdW1uLiBUaGlzIGNvbHVtbiBoYXMgYSBsb3Qgb2YgZW50cmllcyB0aGF0IGFyZSBxdWVzdGlvbiBtYXJrcyAoPykuIFRoaXMgdmFyaWFibGUgaXMgbm90IHdvcnRoIGxvb2tpbmcgYXQgc2luY2Ugd2UgZG9u4oCZdCBoYXZlIGFsbCB0aGUgY2Fyc+KAmSBleHBlY3RlZCBsb3NzZXMuDQoNCkxldOKAmXMgcmVtb3ZlIHRoaXMgY29sdW1uIGZyb20gdGhlIGRhdGFzZXQuIFNlbGVjdCBhbGwgY29sdW1ucyBmcm9tIGNhcnMgYnV0IG5vcm1hbGl6ZWRfbG9zc2VzLiBTYXZlIHlvdXIgbmV3IGRhdGFmcmFtZSB0byBjYXJzLg0KDQojIyBUYXNrIDQNCmBgYHtyIGVycm9yPVRSVUV9DQojIHNlbGVjdCBjb2x1bW5zDQpjYXJzIDwtIGNhcnMgJT4lDQogIHNlbGVjdCgtbm9ybWFsaXplZF9sb3NzZXMpDQpjYXJzDQpgYGANCg0KNS5QcmludCB0aGUgY29sdW1uIG5hbWVzIG9mIGNhcnMuIEFyZSB0aGV5IGNsZWFyIGFuZCBkZXNjcmlwdGl2ZT8NCg0KIyMgVGFzayA1DQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyB2aWV3IGNvbHVtbnMNCmNvbG5hbWVzKGNhcnMpDQpgYGANCg0KNi5Zb3Uga25vdywgc3ltYm9saW5nIGRvZXNu4oCZdCBzYXkgYW55dGhpbmcgdG8geW91IGF0IGZpcnN0IGdsYW5jZS4gQWNjb3JkaW5nIHRvIHRoZSBVQ0kgd2VicGFnZSwgdGhlIHN5bWJvbGluZyB2YXJpYWJsZSByZXByZXNlbnRzIHRoZSBjYXLigJlzIHJpc2sgZmFjdG9yLiBUaGF0IHZhcmlhYmxlIG5hbWUgZG9lc27igJl0IHNlZW0gdG8gZ28gd2l0aCB0aGUgZGVzY3JpcHRpb24uIFlvdSBzaG91bGQgc2ltcGxpZnkgdGhpcyB2YXJpYWJsZSBuYW1lIHRvIGhhdmUgaXQgbWFrZSBtb3JlIHNlbnNlLg0KDQpVcGRhdGUgdGhhdCBjb2x1bW4gbmFtZSBpbiBjYXJzIGFzIGZvbGxvd3M6DQoNCnN5bWJvbGluZyAtPiByaXNrX2ZhY3Rvcg0KUHJpbnQgdGhlIGNvbHVtbiBuYW1lcyBvZiBjYXJzIHRvIGNvbmZpcm0gdGhlIG5hbWVzIG9mIHRoZSBjb2x1bW5zIGhhdmUgY2hhbmdlZC4NCg0KIyMgVGFzayA2DQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyByZW5hbWUgY29sdW1uDQpjYXJzIDwtIGNhcnMgJT4lDQogIHJlbmFtZShyaXNrX2ZhY3RvciA9IHN5bWJvbGluZykNCmNvbG5hbWVzKGNhcnMpDQpgYGANCg0KNy5Zb3VyIGNhciBjb2xsZWN0aW9uIG1lYW5zIGEgbG90IHRvIHlvdS4gWW91IHdhbnQgZWFjaCBjYXIgdG8gYmUgb2YgdmFsdWUgdG8geW91LiBXaGF0IGJldHRlciB3YXkgdG8gZG8gdGhhdCB0aGFuIHRvIGJ1eSBhIGNhciB3aXRoIGEgbG90IG9mIG1pbGVzLXBlci1nYWxsb24gb24gdGhlIGhpZ2h3YXlzPyBUbyBkZXRlcm1pbmUgdGhpcywgZmlyc3QsIHN1cHBvc2Ugb25seSBjYXJzIGV4Y2VlZGluZyAzMCBtcGcgb24gdGhlIGhpZ2h3YXlzIGludGVyZXN0IHlvdS4gWW91IHNlZWsgdG8gbWVhc3VyZSBob3cgZGlmZmVyZW50IGVhY2ggY2Fy4oCZcyBoaWdod2F5IG1wZyBpcyBmcm9tIHlvdXIgMzAgbXBnIHRocmVzaG9sZC4gQ3JlYXRlIGEgdmFyaWFibGUgY2FsbGVkIG1wZ190aHJlc2hvbGQgd2l0aCB0aGUgdmFsdWUgMzAuDQoNCiMjIFRhc2sgNw0KYGBge3IgZXJyb3I9VFJVRX0NCiMgZGVmaW5lIHRocmVzaG9sZA0KbXBnX3RocmVzaG9sZCA8LSAzMA0KbXBnX3RocmVzaG9sZA0KYGBgDQoNCjguQWRkIGEgbmV3IGNvbHVtbiB0byBjYXJzIGNhbGxlZCBtcGdfZGlmZl9mcm9tX3RocmVzaG9sZC4gVGhpcyB3aWxsIG1lYXN1cmUgaG93IGZhciBlYWNoIGNhcuKAmXMgaGlnaHdheSBtcGcgaXMgZnJvbSAzMCBtcGcuIFZpZXcgdGhlIHVwZGF0ZWQgY2FycyBkYXRhZnJhbWUuDQoNCiMjIFRhc2sgOA0KYGBge3IgZXJyb3I9VFJVRX0NCiMgYWRkIGNvbHVtbg0KY2FycyA8LSBjYXJzICU+JQ0KICBtdXRhdGUobXBnX2RpZmZfZnJvbV90aHJlc2hvbGQgPSBoaWdod2F5X21wZyAtIG1wZ190aHJlc2hvbGQpDQpjYXJzDQpgYGANCg0KIyBGaWx0ZXIgYW5kIEFycmFuZ2UgUm93cw0KDQo5LllvdeKAmWxsIGFkZCBhIGNhciB0byB5b3VyIGNvbGxlY3Rpb24gb25seSBpZiBpdCBnZXRzIG1vcmUgdGhhbiAzMCBtaWxlcyBwZXIgZ2FsbG9uIG9uIHRoZSBoaWdod2F5cy4gRmlsdGVyIHRoZSByb3dzIG9mIGNhcnMgdG8gZmluZCBhbGwgdGhlIGNhcnMgd2hlcmUgbXBnX2RpZmZfZnJvbV90aHJlc2hvbGQgaXMgZ3JlYXRlciB0aGFuIDAuIFNhdmUgdGhpcyBuZXcgZGF0YWZyYW1lIHRvIG1wZ19leGNlZWRzX3RocmVzaG9sZCBhbmQgdmlldyBpdC4NCg0KIyMgVGFzayA5DQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyBmaWx0ZXIgcm93cw0KbXBnX2V4Y2VlZHNfdGhyZXNob2xkIDwtIGNhcnMgJT4lDQogIGZpbHRlcihtcGdfZGlmZl9mcm9tX3RocmVzaG9sZCA+IDApDQptcGdfZXhjZWVkc190aHJlc2hvbGQNCmBgYA0KDQoxMC5XaGljaCBjYXJzIGhhdmUgdGhlIGhpZ2hlc3QgbWlsZXMgcGVyIGdhbGxvbiBvbiB0aGUgaGlnaHdheXM/IFRvIGZpbmQgdGhpcywgYXJyYW5nZSB0aGUgcm93cyBvZiBtcGdfZXhjZWVkc190aHJlc2hvbGQgYnkgbXBnX2RpZmZfZnJvbV90aHJlc2hvbGQgZGVzY2VuZGluZy4gU2F2ZSB0aGlzIG5ldyBkYXRhZnJhbWUgYXMgbXBnX2V4Y2VlZHNfdGhyZXNob2xkLg0KDQojIyBUYXNrIDEwDQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyBhcnJhbmdlIHJvd3MNCm1wZ19leGNlZWRzX3RocmVzaG9sZCA8LSBjYXJzICU+JQ0KICBhcnJhbmdlKGRlc2MobXBnX2RpZmZfZnJvbV90aHJlc2hvbGQpKQ0KbXBnX2V4Y2VlZHNfdGhyZXNob2xkDQpgYGANCg0KMTEuTm93IHN1cHBvc2UgeW91IHdhbnQgeW91ciBuZXh0IGNhciB0byBoYXZlIGEgbGFyZ2UgZW5naW5lLiBPcmRlciB0aGUgcm93cyBvZiBjYXJzIGJ5IGVuZ2luZV9zaXplIGRlc2NlbmRpbmcuIFNhdmUgdGhlIG5ldyBkYXRhIGZyYW1lIHRvIG9yZGVyZWRfYnlfZW5naW5lX3NpemUuIFZpZXcgb3JkZXJlZF9ieV9lbmdpbmVfc2l6ZS4NCg0KIyMgVGFzayAxMQ0KYGBge3IgZXJyb3I9VFJVRX0NCiMgb3JkZXIgcm93cyBieSBlbmdpbmUgc2l6ZQ0Kb3JkZXJlZF9ieV9lbmdpbmVfc2l6ZSA8LSBjYXJzICU+JQ0KICBhcnJhbmdlKGRlc2MoZW5naW5lX3NpemUpKQ0Kb3JkZXJlZF9ieV9lbmdpbmVfc2l6ZQ0KYGBgDQoNCiMgU3BlY2lmeWluZyB0aGUgTWFrZSBvZiB0aGUgQ2FyDQoNCjEyLlRoZXJl4oCZcyBhIGxvdCBvZiBtYWtlcyBvZiBjYXJzIHRvIGNob29zZSBmcm9tLCBidXQgeW91IG1heSBwcmVmZXIgb25lIG92ZXIgdGhlIG90aGVycy4gV2hpY2ggbWFrZSBkbyB5b3UgcHJlZmVyIHRoZSBtb3N0PyBDcmVhdGUgYSB2YXJpYWJsZSBjYWxsZWQgY2hvc2VuX21ha2UgdGhhdCBjb250YWlucyB0aGUgbWFrZSB5b3Ugd2FudCB0byBjaGVjay4gVGhlIGhpbnQgYmVsb3cgcHJvdmlkZXMgdGhlIGxpc3Qgb2YgbWFrZXMgdG8gY2hvb3NlIGZyb20uDQoNCipIaW50IDogVGhlIGxpc3QgYmVsb3cgcHJvdmlkZXMgdGhlIG1ha2VzIGZvciB5b3UgdG8gY2hvb3NlIGZyb20uIFBpY2sgYSBtYWtlIGFuZCBhc3NpZ24gaXQgdG8gY2hvc2VuX21ha2UuDQphbGZhLXJvbWVybywgYXVkaSwgYm13LCBjaGV2cm9sZXQsIGRvZGdlLCBob25kYSwgaXN1enUsIGphZ3VhciwgbWF6ZGEsIG1lcmNlZGVzLWJlbnosIG1lcmN1cnksIG1pdHN1YmlzaGksIG5pc3NhbiwgcGV1Z290LCBwbHltb3V0aCwgcG9yc2NoZSwgcmVuYXVsdCwgc2FhYiwgc3ViYXJ1LCB0b3lvdGEsIHZvbGtzd2FnZW4sIHZvbHZvDQoNCiMjIFRhc2sgMTINCmBgYHtyIGVycm9yPVRSVUV9DQojIGNob29zZSBtYWtlDQpjaG9zZW5fbWFrZSA8LSAibWVyY2VkZXMtYmVueiINCmNob3Nlbl9tYWtlDQpgYGANCg0KMTMuRmlsdGVyIGNhcnMgdG8gb25seSBpbmNsdWRlIHJvd3Mgd2hlcmUgdGhlIG1ha2UgY29sdW1uIGlzIGVxdWFsIHRvIGNob3Nlbl9tYWtlLiBTYXZlIHRoZSBuZXcgZGF0YWZyYW1lIHRvIGNob3Nlbl9tYWtlX2RldGFpbHMuDQoNCiMjIFRhc2sgMTMNCmBgYHtyIGVycm9yPVRSVUV9DQojIGZpbHRlciByb3dzIGJ5IG1ha2UNCmNob3Nlbl9tYWtlX2RldGFpbHMgPC0gY2FycyAlPiUNCiAgZmlsdGVyKG1ha2UgPT0gY2hvc2VuX21ha2UpDQpjaG9zZW5fbWFrZV9kZXRhaWxzDQpgYGANCg0KMTQuT3JkZXIgdGhlIHJvd3Mgb2YgY2hvc2VuX21ha2VfZGV0YWlscyBieSBlbmdpbmVfc2l6ZSBkZXNjZW5kaW5nIGFuZCBzYXZlIHRoZSBuZXcgZGF0YWZyYW1lIHRvIGNob3Nlbl9tYWtlX2RldGFpbHMuIFZpZXcgY2hvc2VuX21ha2VfZGV0YWlscy4NCg0KSG93IGxhcmdlIGFyZSB0aGUgZW5naW5lcyBpbiBlYWNoIG9mIHRoZSBjYXJzIGZyb20gdGhhdCBtYWtlIHRoYXQgeW91IGNob3NlPyBZb3UgY2FuIGNoYW5nZSB0aGUgbWFrZSBzdG9yZWQgaW4gY2hvc2VuX21ha2UgdG8gY2hlY2sgb3V0IHRoZSBlbmdpbmUgc2l6ZXMgZm9yIG90aGVyIG1ha2VzLg0KDQojIyBUYXNrIDE0DQpgYGB7ciBlcnJvcj1UUlVFfQ0KIyBvcmRlciBmaWx0ZXJlZCByb3dzIGJ5IGVuZ2luZSBzaXplDQpjaG9zZW5fbWFrZV9kZXRhaWxzIDwtIGNhcnMgJT4lDQogIGFycmFuZ2UoZGVzYyhlbmdpbmVfc2l6ZSkpDQpjaG9zZW5fbWFrZV9kZXRhaWxzDQpgYGANCg0KMTUuVGhlIHByb2Nlc3Mgb2YgYnV5aW5nIGEgbmV3IGNhciBjYW4gY2F1c2UgYSBsb3Qgb2Ygc3RyZXNzIC0geW91IGRvbuKAmXQgd2FudCB0byBidXkgYSBjYXIgeW91IHdvbuKAmXQgbGlrZSEgWW914oCZdmUgbm93IHNlZW4gaG93IHBlcmZvcm1pbmcgYW4gYW5hbHlzaXMgY2FuIGVhc2Ugc29tZSBvZiB0aGUgc3RyZXNzIG9mIG1ha2luZyB0aGUgZGVjaXNpb24gb2Ygd2hpY2ggY2FyIHRvIGJ1eS4gWW91IGFsc28gZ2V0IHRvIGFkZCBhIG5pY2UgbmV3IGNhciB0byB5b3VyIGNvbGxlY3Rpb24hIEdyZWF0IHdvcmsh