Remember, before you can use the tidyverse, you need to load the package.
library(tidyverse)
First Steps
More plots with the mpg dataset
(Taken form R4DS)
- Run
ggplot(data = mpg). What do you see?
- How many rows are in mpg? How many columns?
- What does the
drv variable describe? You may want to use ?mpg to find out
- Make a scatter plot of
hwy vs cyl
- What happens if you make a scatter plot of
class vs drv? Why is the plot not useful?
Plots with other datasets
- Take a look at the
iris dataset. What are its dimensions? What do its columns represent?
- What are the ranges of each of the numeric columns. The
summary() function might help you here
- Make a plot of sepal width vs sepal length, and set all of the points to be green
- Repeat the previous plot but colour each point by the species of the flower
Remaking plots
- Take a look at the first and last few rows of the
mtcars dataset
- Access the
cyl column of the dataset. Is this variable categorical, discrete, or continuous?
- What steps would you go about to remake the following plot?

More Aesthetics
Size, Transparency, and Shape
- Using the
mpg dataset, make a plot of city mileage vs highway mileage where the size of each point is determined by engine size (displ)
- Plot sepal length vs sepal width using the
iris dataset and control the transparency (alpha) of each point using the species variable.
- Have a play with the
Orange data set (note the capital ‘O’). Make a scatter plot of circumference against age where the shape of each point is determined by which tree the observation belongs to
- Remake the standard
hwy vs displ plot using the mpg data set but make all of the points hollow diamonds. How about solid triangles?
Choosing Appropriate Aesthetics
(Q1/2 form R4DS)
- Which variables in
mpg are categorical? Which are continuous/discrete? (The data set help file may be of use)
- Map a continuous variable to colour, size, and shape. How does this differ from when you map a categorical variable?
- Plot the standard
hwy vs displ graph using mpg and map the variable class to the size aesthetic. Was this a good idea?
- Have a discussion with a partner or think for yourself: Which of the aesthetics you know are the clearest for displaying categorical data and which are best for continuous?
- In your own opinion, order the following aesthetics by how clear they are in representing a continuous variable: size, colour, transparency
Common Problems
- Using the
mpg data set, make a plot of city milage against engine size. Map the variable class to the aesthetic shape. Is everything as you would expect?
- Type the following code into the console. Why do you recieve an error message?
ggplot(iris) +
geom_point(x = Sepal.Length, y = Petal.Length)
- Take a look at the
airquality dataset. Type the following code into the console. Is the plot as you expected?
ggplot(airquality) +
geom_point(aes(x = Wind, y = Temp, col = Month))
- Why are the points in this plot not blue?
ggplot(mpg) +
geom_point(aes(x = displ, y = hwy, colour = 'blue'))

- What happens when you map a variable to multiple aesthetics (say colour and size)? (It’s okay to answer, “nothing”, to this question but make sure you verify that first!)
Facetting
Basic Faceting
(Taken form R4DS)
- What happens when you facet a continuous variable?
- What do the empty cells in a plot with
facet_grid(drv ~ cyl) mean? How do they relate to this plot?
ggplot(mpg) +
geom_point(aes(x = drv, y = cyl))
- What plots does the following code make? What does the
. do?
ggplot(mpg) +
geom_point(aes(x = displ, y = hwy)) +
facet_grid(drv ~ .)
ggplot(mpg) +
geom_point(aes(x = displ, y = hwy)) +
facet_grid(. ~ cyl)
- Take the first faceted plot from the presentation:
ggplot(mpg) +
geom_point(aes(x = displ, y = hwy)) +
facet_wrap(~ class, nrow = 2)
What are the advantages of faceting instead of the colour aesthetic? What are the disadvantages? How might the balance change if you had a larger data set?
- Read
?facet_wrap. What does nrow do? What does ncol do? What other options control the layout of the individual panels? Why doesn’t facet_grid() have nrow and ncol parameters?
- When using
facet_grid() you should usually put the variable with more unique levels in the columns. Why?
Combining Facets with Aesthetics
- Create a scatter plot of petal length vs petal width using the
iris dataset and facet by species
- Repeat the above plot whilst also colouring the species. Don’t forget to hide the colour legend
- Using the
mpg dataset, plot hwy vs cty, map displ to the size aesthetic, map class to point colour, and facet columns by cyl and rows by drv. This plot is ridiculous but it does demonstrate the flexibilty of ggplot2
Going Beyond
Labelling
- Run the following code. What does the extra
labs(...) layer do?
ggplot(mpg) +
geom_point(aes(x = displ, y = hwy, colour = class)) +
labs(x = "Engine Displacment (litres)", y = "Highway Milage (miles/gallon)",
colour = "Car Type",
title = "A scatter plot of engine displacment vs highway milage",
subtitle = "Coloured by car type",
caption = "Source: EPA (http://fueleconomy.gov)")
- Use this to take the plot from the ‘Remaking plots’ section and beautify it
- Pick any plot of your choosing an give it appropriate axis labels, a title, and - if possible - a data source
Diamonds and Overplotting
- Have a look at the
diamonds dataset
- Make a scatter plot of
price against caret (this may take a long time to run). Is this plot easy to read?
- How could you fix this problem? (perhaps you could manually set a certain aesthetic)
Explanatory and Response variables
- How do you decide which variable to map to the x-axis and which to plot to the y-axis?
- If you are unsure, web-search for the phrase “explanatory and response variables”
Positional Arguments
Begin with the following code
ggplot(mpg) +
geom_point(aes(x = displ, y = hwy, colour = factor(class)))

- Try removing
x = and y = from your geom_point call. Does everything still work?
- Try removing
colour = from your geom_point call. Does everything still work?
- Take the original plot and specify the aesthetics in a different order, say
y then colour then x. Does everything still work?
LS0tCnRpdGxlOiAiSW50byB0aGUgVGlkeXZlcnNlIgpzdWJ0aXRsZTogIlNlc3Npb24gT25lIEV4ZXJjaXNlcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKUmVtZW1iZXIsIGJlZm9yZSB5b3UgY2FuIHVzZSB0aGUgdGlkeXZlcnNlLCB5b3UgbmVlZCB0byBsb2FkIHRoZSBwYWNrYWdlLgoKYGBge3IgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyMgRmlyc3QgU3RlcHMKCiMjIyBNb3JlIHBsb3RzIHdpdGggdGhlIG1wZyBkYXRhc2V0CgooKipUYWtlbiBmb3JtIFI0RFMqKikKCjEuIFJ1biBgZ2dwbG90KGRhdGEgPSBtcGcpYC4gV2hhdCBkbyB5b3Ugc2VlPwoyLiBIb3cgbWFueSByb3dzIGFyZSBpbiBtcGc/IEhvdyBtYW55IGNvbHVtbnM/CjMuIFdoYXQgZG9lcyB0aGUgYGRydmAgdmFyaWFibGUgZGVzY3JpYmU/IFlvdSBtYXkgd2FudCB0byB1c2UgYD9tcGdgIHRvIGZpbmQgb3V0CjQuIE1ha2UgYSBzY2F0dGVyIHBsb3Qgb2YgYGh3eWAgdnMgYGN5bGAKNS4gV2hhdCBoYXBwZW5zIGlmIHlvdSBtYWtlIGEgc2NhdHRlciBwbG90IG9mIGBjbGFzc2AgdnMgYGRydmA/IFdoeSBpcyB0aGUgcGxvdCBub3QgdXNlZnVsPwoKIyMjIFBsb3RzIHdpdGggb3RoZXIgZGF0YXNldHMKCjEuIFRha2UgYSBsb29rIGF0IHRoZSBgaXJpc2AgZGF0YXNldC4gV2hhdCBhcmUgaXRzIGRpbWVuc2lvbnM/IFdoYXQgZG8gaXRzIGNvbHVtbnMgcmVwcmVzZW50PwoyLiBXaGF0IGFyZSB0aGUgcmFuZ2VzIG9mIGVhY2ggb2YgdGhlIG51bWVyaWMgY29sdW1ucy4gVGhlIGBzdW1tYXJ5KClgIGZ1bmN0aW9uIG1pZ2h0IGhlbHAgeW91IGhlcmUKMy4gTWFrZSBhIHBsb3Qgb2Ygc2VwYWwgd2lkdGggdnMgc2VwYWwgbGVuZ3RoLCBhbmQgc2V0IGFsbCBvZiB0aGUgcG9pbnRzIHRvIGJlIGdyZWVuCjQuIFJlcGVhdCB0aGUgcHJldmlvdXMgcGxvdCBidXQgY29sb3VyIGVhY2ggcG9pbnQgYnkgdGhlIHNwZWNpZXMgb2YgdGhlIGZsb3dlcgoKIyMjIFJlbWFraW5nIHBsb3RzCgoxLiBUYWtlIGEgbG9vayBhdCB0aGUgZmlyc3QgYW5kIGxhc3QgZmV3IHJvd3Mgb2YgdGhlIGBtdGNhcnNgIGRhdGFzZXQKMi4gQWNjZXNzIHRoZSBgY3lsYCBjb2x1bW4gb2YgdGhlIGRhdGFzZXQuIElzIHRoaXMgdmFyaWFibGUgY2F0ZWdvcmljYWwsIGRpc2NyZXRlLCBvciBjb250aW51b3VzPwozLiBXaGF0IHN0ZXBzIHdvdWxkIHlvdSBnbyBhYm91dCB0byByZW1ha2UgdGhlIGZvbGxvd2luZyBwbG90PwoKYGBge3IgZWNobz1GQUxTRX0KZ2dwbG90KG10Y2FycykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwLCB5ID0gaHAsIGNvbG91ciA9IGZhY3RvcihjeWwpKSkKYGBgCgojIyBNb3JlIEFlc3RoZXRpY3MgCgojIyMgU2l6ZSwgVHJhbnNwYXJlbmN5LCBhbmQgU2hhcGUKCjEuIFVzaW5nIHRoZSBgbXBnYCBkYXRhc2V0LCBtYWtlIGEgcGxvdCBvZiBjaXR5IG1pbGVhZ2UgdnMgaGlnaHdheSBtaWxlYWdlIHdoZXJlIHRoZSBzaXplIG9mIGVhY2ggcG9pbnQgaXMgZGV0ZXJtaW5lZCBieSBlbmdpbmUgc2l6ZSAoYGRpc3BsYCkKMi4gUGxvdCBzZXBhbCBsZW5ndGggdnMgc2VwYWwgd2lkdGggdXNpbmcgdGhlIGBpcmlzYCBkYXRhc2V0IGFuZCBjb250cm9sIHRoZSB0cmFuc3BhcmVuY3kgKGBhbHBoYWApIG9mIGVhY2ggcG9pbnQgdXNpbmcgdGhlIGBzcGVjaWVzYCB2YXJpYWJsZS4KMy4gSGF2ZSBhIHBsYXkgd2l0aCB0aGUgYE9yYW5nZWAgZGF0YSBzZXQgKG5vdGUgdGhlIGNhcGl0YWwgJ08nKS4gTWFrZSBhIHNjYXR0ZXIgcGxvdCBvZiBjaXJjdW1mZXJlbmNlIGFnYWluc3QgYWdlIHdoZXJlIHRoZSBzaGFwZSBvZiBlYWNoIHBvaW50IGlzIGRldGVybWluZWQgYnkgd2hpY2ggdHJlZSB0aGUgb2JzZXJ2YXRpb24gYmVsb25ncyB0bwo0LiBSZW1ha2UgdGhlIHN0YW5kYXJkIGBod3lgIHZzIGBkaXNwbGAgcGxvdCB1c2luZyB0aGUgYG1wZ2AgZGF0YSBzZXQgYnV0IG1ha2UgYWxsIG9mIHRoZSBwb2ludHMgaG9sbG93IGRpYW1vbmRzLiBIb3cgYWJvdXQgc29saWQgdHJpYW5nbGVzPwoKIyMjIENob29zaW5nIEFwcHJvcHJpYXRlIEFlc3RoZXRpY3MKCigqKlExLzIgZm9ybSBSNERTKiopCgoxLiBXaGljaCB2YXJpYWJsZXMgaW4gYG1wZ2AgYXJlIGNhdGVnb3JpY2FsPyBXaGljaCBhcmUgY29udGludW91cy9kaXNjcmV0ZT8gKFRoZSBkYXRhIHNldCBoZWxwIGZpbGUgbWF5IGJlIG9mIHVzZSkKMi4gTWFwIGEgY29udGludW91cyB2YXJpYWJsZSB0byBjb2xvdXIsIHNpemUsIGFuZCBzaGFwZS4gSG93IGRvZXMgdGhpcyBkaWZmZXIgZnJvbSB3aGVuIHlvdSBtYXAgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZT8KMy4gUGxvdCB0aGUgc3RhbmRhcmQgYGh3eWAgdnMgYGRpc3BsYCBncmFwaCB1c2luZyBgbXBnYCBhbmQgbWFwIHRoZSB2YXJpYWJsZSBgY2xhc3NgIHRvIHRoZSBgc2l6ZWAgYWVzdGhldGljLiBXYXMgdGhpcyBhIGdvb2QgaWRlYT8KNC4gSGF2ZSBhIGRpc2N1c3Npb24gd2l0aCBhIHBhcnRuZXIgb3IgdGhpbmsgZm9yIHlvdXJzZWxmOiBXaGljaCBvZiB0aGUgYWVzdGhldGljcyB5b3Uga25vdyBhcmUgdGhlIGNsZWFyZXN0IGZvciBkaXNwbGF5aW5nIGNhdGVnb3JpY2FsIGRhdGEgYW5kIHdoaWNoIGFyZSBiZXN0IGZvciBjb250aW51b3VzPyAKNS4gSW4geW91ciBvd24gb3Bpbmlvbiwgb3JkZXIgdGhlIGZvbGxvd2luZyBhZXN0aGV0aWNzIGJ5IGhvdyBjbGVhciB0aGV5IGFyZSBpbiByZXByZXNlbnRpbmcgYSBjb250aW51b3VzIHZhcmlhYmxlOiBzaXplLCBjb2xvdXIsIHRyYW5zcGFyZW5jeQoKIyMjIENvbW1vbiBQcm9ibGVtcwoKMS4gVXNpbmcgdGhlIGBtcGdgIGRhdGEgc2V0LCBtYWtlIGEgcGxvdCBvZiBjaXR5IG1pbGFnZSBhZ2FpbnN0IGVuZ2luZSBzaXplLiBNYXAgdGhlIHZhcmlhYmxlIGBjbGFzc2AgdG8gdGhlIGFlc3RoZXRpYyBgc2hhcGVgLiBJcyBldmVyeXRoaW5nIGFzIHlvdSB3b3VsZCBleHBlY3Q/CjIuIFR5cGUgdGhlIGZvbGxvd2luZyBjb2RlIGludG8gdGhlIGNvbnNvbGUuIFdoeSBkbyB5b3UgcmVjaWV2ZSBhbiBlcnJvciBtZXNzYWdlPwoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QoaXJpcykgKwogIGdlb21fcG9pbnQoeCA9IFNlcGFsLkxlbmd0aCwgeSA9IFBldGFsLkxlbmd0aCkKYGBgCgozLiBUYWtlIGEgbG9vayBhdCB0aGUgYGFpcnF1YWxpdHlgIGRhdGFzZXQuIFR5cGUgdGhlIGZvbGxvd2luZyBjb2RlIGludG8gdGhlIGNvbnNvbGUuIElzIHRoZSBwbG90IGFzIHlvdSBleHBlY3RlZD8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KGFpcnF1YWxpdHkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gV2luZCwgeSA9IFRlbXAsIGNvbCA9IE1vbnRoKSkKYGBgCgo0LiBXaHkgYXJlIHRoZSBwb2ludHMgaW4gdGhpcyBwbG90IG5vdCBibHVlPwoKYGBge3IgbWVzc2FnZSA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvdXIgPSAnYmx1ZScpKQpgYGAKCjUuIFdoYXQgaGFwcGVucyB3aGVuIHlvdSBtYXAgYSB2YXJpYWJsZSB0byBtdWx0aXBsZSBhZXN0aGV0aWNzIChzYXkgY29sb3VyIGFuZCBzaXplKT8gKEl0J3Mgb2theSB0byBhbnN3ZXIsICJub3RoaW5nIiwgdG8gdGhpcyBxdWVzdGlvbiBidXQgbWFrZSBzdXJlIHlvdSB2ZXJpZnkgdGhhdCBmaXJzdCEpCgojIyBGYWNldHRpbmcKCiMjIyBCYXNpYyBGYWNldGluZwoKKCoqVGFrZW4gZm9ybSBSNERTKiopCgoxLiBXaGF0IGhhcHBlbnMgd2hlbiB5b3UgZmFjZXQgYSBjb250aW51b3VzIHZhcmlhYmxlPwoyLiBXaGF0IGRvIHRoZSBlbXB0eSBjZWxscyBpbiBhIHBsb3Qgd2l0aCBgZmFjZXRfZ3JpZChkcnYgfiBjeWwpYCBtZWFuPyBIb3cgZG8gdGhleSByZWxhdGUgdG8gdGhpcyBwbG90PwoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRydiwgeSA9IGN5bCkpCmBgYAoKMy4gV2hhdCBwbG90cyBkb2VzIHRoZSBmb2xsb3dpbmcgY29kZSBtYWtlPyBXaGF0IGRvZXMgdGhlIGAuYCBkbz8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KG1wZykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsKICBmYWNldF9ncmlkKGRydiB+IC4pCgpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKwogIGZhY2V0X2dyaWQoLiB+IGN5bCkKYGBgCgo0LiBUYWtlIHRoZSBmaXJzdCBmYWNldGVkIHBsb3QgZnJvbSB0aGUgcHJlc2VudGF0aW9uOgoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKwogIGZhY2V0X3dyYXAofiBjbGFzcywgbnJvdyA9IDIpCmBgYAoKV2hhdCBhcmUgdGhlIGFkdmFudGFnZXMgb2YgZmFjZXRpbmcgaW5zdGVhZCBvZiB0aGUgY29sb3VyIGFlc3RoZXRpYz8gV2hhdCBhcmUgdGhlIGRpc2FkdmFudGFnZXM/IEhvdyBtaWdodCB0aGUgYmFsYW5jZSBjaGFuZ2UgaWYgeW91IGhhZCBhIGxhcmdlciBkYXRhIHNldD8KCjUuIFJlYWQgYD9mYWNldF93cmFwYC4gV2hhdCBkb2VzIGBucm93YCBkbz8gV2hhdCBkb2VzIGBuY29sYCBkbz8gV2hhdCBvdGhlciBvcHRpb25zIGNvbnRyb2wgdGhlIGxheW91dCBvZiB0aGUgaW5kaXZpZHVhbCBwYW5lbHM/IFdoeSBkb2Vzbid0IGBmYWNldF9ncmlkKClgIGhhdmUgYG5yb3dgIGFuZCBgbmNvbGAgcGFyYW1ldGVycz8KNi4gV2hlbiB1c2luZyBgZmFjZXRfZ3JpZCgpYCB5b3Ugc2hvdWxkIHVzdWFsbHkgcHV0IHRoZSB2YXJpYWJsZSB3aXRoIG1vcmUgdW5pcXVlIGxldmVscyBpbiB0aGUgY29sdW1ucy4gV2h5PwoKCiMjIyBDb21iaW5pbmcgRmFjZXRzIHdpdGggQWVzdGhldGljcwoKMS4gQ3JlYXRlIGEgc2NhdHRlciBwbG90IG9mIHBldGFsIGxlbmd0aCB2cyBwZXRhbCB3aWR0aCB1c2luZyB0aGUgYGlyaXNgIGRhdGFzZXQgYW5kIGZhY2V0IGJ5IHNwZWNpZXMKMi4gUmVwZWF0IHRoZSBhYm92ZSBwbG90IHdoaWxzdCBhbHNvIGNvbG91cmluZyB0aGUgc3BlY2llcy4gRG9uJ3QgZm9yZ2V0IHRvIGhpZGUgdGhlIGNvbG91ciBsZWdlbmQKMy4gVXNpbmcgdGhlIGBtcGdgIGRhdGFzZXQsIHBsb3QgYGh3eWAgdnMgYGN0eWAsIG1hcCBgZGlzcGxgIHRvIHRoZSBgc2l6ZWAgYWVzdGhldGljLCBtYXAgYGNsYXNzYCB0byBwb2ludCBjb2xvdXIsIGFuZCBmYWNldCBjb2x1bW5zIGJ5IGBjeWxgIGFuZCByb3dzIGJ5IGBkcnZgLiBUaGlzIHBsb3QgaXMgcmlkaWN1bG91cyBidXQgaXQgZG9lcyBkZW1vbnN0cmF0ZSB0aGUgZmxleGliaWx0eSBvZiBgZ2dwbG90MmAKCiMjIEdvaW5nIEJleW9uZAoKIyMjIExhYmVsbGluZwoKMS4gUnVuIHRoZSBmb2xsb3dpbmcgY29kZS4gV2hhdCBkb2VzIHRoZSBleHRyYSBgbGFicyguLi4pYCBsYXllciBkbz8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KG1wZykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwbCwgeSA9IGh3eSwgY29sb3VyID0gY2xhc3MpKSArCiAgbGFicyh4ID0gIkVuZ2luZSBEaXNwbGFjbWVudCAobGl0cmVzKSIsIHkgPSAiSGlnaHdheSBNaWxhZ2UgKG1pbGVzL2dhbGxvbikiLAogICAgICAgY29sb3VyID0gIkNhciBUeXBlIiwKICAgICAgIHRpdGxlID0gIkEgc2NhdHRlciBwbG90IG9mIGVuZ2luZSBkaXNwbGFjbWVudCB2cyBoaWdod2F5IG1pbGFnZSIsCiAgICAgICBzdWJ0aXRsZSA9ICJDb2xvdXJlZCBieSBjYXIgdHlwZSIsCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogRVBBIChodHRwOi8vZnVlbGVjb25vbXkuZ292KSIpCmBgYAoKMi4gVXNlIHRoaXMgdG8gdGFrZSB0aGUgcGxvdCBmcm9tIHRoZSAnUmVtYWtpbmcgcGxvdHMnIHNlY3Rpb24gYW5kIGJlYXV0aWZ5IGl0CjMuIFBpY2sgYW55IHBsb3Qgb2YgeW91ciBjaG9vc2luZyBhbiBnaXZlIGl0IGFwcHJvcHJpYXRlIGF4aXMgbGFiZWxzLCBhIHRpdGxlLCBhbmQgLSBpZiBwb3NzaWJsZSAtIGEgZGF0YSBzb3VyY2UKCiMjIyBEaWFtb25kcyBhbmQgT3ZlcnBsb3R0aW5nCgoxLiBIYXZlIGEgbG9vayBhdCB0aGUgYGRpYW1vbmRzYCBkYXRhc2V0CjIuIE1ha2UgYSBzY2F0dGVyIHBsb3Qgb2YgYHByaWNlYCBhZ2FpbnN0IGBjYXJldGAgKHRoaXMgbWF5IHRha2UgYSBsb25nIHRpbWUgdG8gcnVuKS4gSXMgdGhpcyBwbG90IGVhc3kgdG8gcmVhZD8KMy4gSG93IGNvdWxkIHlvdSBmaXggdGhpcyBwcm9ibGVtPyAocGVyaGFwcyB5b3UgY291bGQgbWFudWFsbHkgc2V0IGEgY2VydGFpbiBhZXN0aGV0aWMpCgojIyMgRXhwbGFuYXRvcnkgYW5kIFJlc3BvbnNlIHZhcmlhYmxlcwoKMS4gSG93IGRvIHlvdSBkZWNpZGUgd2hpY2ggdmFyaWFibGUgdG8gbWFwIHRvIHRoZSB4LWF4aXMgYW5kIHdoaWNoIHRvIHBsb3QgdG8gdGhlIHktYXhpcz8KMi4gSWYgeW91IGFyZSB1bnN1cmUsIHdlYi1zZWFyY2ggZm9yIHRoZSBwaHJhc2UgImV4cGxhbmF0b3J5IGFuZCByZXNwb25zZSB2YXJpYWJsZXMiCgojIyMgUG9zaXRpb25hbCBBcmd1bWVudHMKCkJlZ2luIHdpdGggdGhlIGZvbGxvd2luZyBjb2RlCgpgYGB7ciBldmFsIEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvdXIgPSBmYWN0b3IoY2xhc3MpKSkKYGBgCgoxLiBUcnkgcmVtb3ZpbmcgYHggPSBgIGFuZCBgeSA9IGAgZnJvbSB5b3VyIGBnZW9tX3BvaW50YCBjYWxsLiBEb2VzIGV2ZXJ5dGhpbmcgc3RpbGwgd29yaz8KMi4gVHJ5IHJlbW92aW5nIGBjb2xvdXIgPSBgIGZyb20geW91ciBgZ2VvbV9wb2ludGAgY2FsbC4gRG9lcyBldmVyeXRoaW5nIHN0aWxsIHdvcms/CjMuIFRha2UgdGhlIG9yaWdpbmFsIHBsb3QgYW5kIHNwZWNpZnkgdGhlIGFlc3RoZXRpY3MgaW4gYSBkaWZmZXJlbnQgb3JkZXIsIHNheSBgeWAgdGhlbiBgY29sb3VyYCB0aGVuIGB4YC4gRG9lcyBldmVyeXRoaW5nIHN0aWxsIHdvcms/Cg==