In this class, you will learn how to:
- Save new types of data, like character strings and logical
values
- Save a data set as a vector, matrix, array, list, or data frame
- Load and save your own data sets with R
- Extract individual values from a data set
- Change individual values within a data set
Atomic Vectors
We create and atomic vector die that stores 5 elements.
die <- c(1, 2, 3, 4, 5, 6)
die
[1] 1 2 3 4 5 6
## 1 2 3 4 5 6
Is it a vector?
is.vector(die)
[1] TRUE
Yes, it is a vector
We create an atomic vector that stores 5 (one element).
five <- 5
five
[1] 5
Is object five a vector?
is.vector(five)
[1] TRUE
Yes, five is a vector with just one element.
Function length gets or sets the length of vectors (including lists)
and factors, and of any other R object for which a method has been
defined. In simple terms, length returns the length of an atomic
vector.
length(five)
[1] 1
length(die)
[1] 6
Vector five has one element while vector die has 6 elements.
Each atomic vector stores its values as a one-dimensional vector, and
each atomic vector can only store one type of data. R recognizes six
basic types of atomic vectors: doubles, integers, characters, logicals,
complex, and raw.
int <- 1L
text <- "ace"
do_uble <- 30 #64 bits to store
logic <- TRUE
Floating-point errors arise due to each double accuracy to about 16
significant digits. This introduces a little bit of error. In most
cases, this rounding error will go unnoticed. However, in some
situations, the rounding error can cause surprising results. For
example, you may expect the result of the expression below to be zero,
but it is not:
sqrt(2)^2 - 2
[1] 4.440892e-16
Problem here is that program compute square root of 2. The result of
this operation is rounded so it is computing an error. Then, the number
which is elevated to 2, is an approximation of the square root of 2
value, is going to be an approximation to 2.
Other types
comp <- c(1 + 1i, 1 + 2i, 1 + 3i)
comp
[1] 1+1i 1+2i 1+3i
r_raw <- raw(3)
raw
function (length = 0L)
.Internal(vector("raw", length))
<bytecode: 0x000001b025c3cea0>
<environment: namespace:base>
## 00 00 00
Attributes
The most common attributes to give an atomic vector are names,
dimensions (dim), and classes. Notice how object die has no names after
we created the object.
names(die)
NULL
We assign names to the elemements.
names(die) <- c("one", "two", "three", "four", "five", "six")
names(die)
[1] "one" "two" "three" "four" "five" "six"
Let’s recheck the attributes function.
attributes(die)
$names
[1] "one" "two" "three" "four" "five" "six"
Names do not affect the values.
names(die) <- c("uno", "dos", "tres", "quatro", "cinco", "seis")
die
uno dos tres quatro cinco seis
1 2 3 4 5 6
We can also remove names.
names(die) <- NULL
Creating n dimensional Structures
A vector is a one-dimensional array. A matrix is a two-dimensional
array; therefore is the same thing as a matrix. Modifying the dim
attribute of an atomic vector into either a matrix or an array with more
than three dimensions.
For example you can reorganize die into a 2 × 3 matrix.
dim(die) <- c(2, 3)
die
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
R will always use the first value in dim for the number of rows and
the second value for the number of columns. In general, rows always come
first in R operations that deal with both rows and columns.
dim(die) <- c(3, 2)
die
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
Notice how by default R fills up each matrix by columns.
#hypercube
dim(die) <- c(1, 2, 3)
class(die)
[1] "array"
If you’d like more control over how the data is stored, you can use
one of R’s helper functions, matrix or array. They do the same thing as
changing the dim attribute, but they provide extra arguments to
customize the process. # Matrix Function
m <- matrix(die, nrow = 2)
m
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
specifying byrow=TRUE, values follows the rows order
m <- matrix(die, nrow = 2, byrow = TRUE)
m
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
Array Function
The array function creates an n-dimensional array.
ar <- array(c(11:14, 21:24, 31:34), dim = c(2, 2, 3))
ar
, , 1
[,1] [,2]
[1,] 11 13
[2,] 12 14
, , 2
[,1] [,2]
[1,] 21 23
[2,] 22 24
, , 3
[,1] [,2]
[1,] 31 33
[2,] 32 34
Notice that changing the dimensions of your object will not change
the type of the object, but it will change the object’s class
attribute:
dim(die) <- c(2, 3)
typeof(die)
[1] "double"
class(die)
[1] "matrix" "array"
Note that an object’s class attribute will not always appear when you
run attributes; you may need to specifically search for it with class:
attributes(die)
attributes(die)
$dim
[1] 2 3
You can apply class to objects that do not have a class attribute.
class will return a value based on the object’s atomic type. Notice that
the “class” of a double is “numeric,” an odd deviation, but one I am
thankful for. I think that the most important property of a double
vector is that it contains numbers, a property that “numeric” makes
obvious:
class("Hello")
[1] "character"
class(5)
[1] "numeric"
now <- Sys.time()
now
[1] "2022-11-30 20:05:18 EST"
typeof(now)
[1] "double"
class(now)
[1] "POSIXct" "POSIXt"
POSIXct is a framework for representing dates and times. Time is
represented by the number of seconds that have passed between now
and12:00 AM January 1st 1970 (in the Universal Time Coordinated (UTC)
zone). You can see this number by removing the class attribute of now,
or by using the un class function, which does the same thing:
unclass(now)
[1] 1669856718
R then gives the double vector a class attribute that contains two
classes, “POSIXct” and “POSIXt”. This attribute alerts R functions that
they are dealing with a POSIXct time, so they can treat it in a special
way. For example, R functions will use the POSIXct standard to convert
the time into a user-friendly character string before displaying it. You
can take advantage of this system by giving the POSIXct class to random
R objects. For example, have you ever wondered what day it was a million
seconds after 12:00 a.m. Jan. 1, 1970?
mil <- 1000000
mil
[1] 1e+06
class(mil) <- c("POSIXct", "POSIXt")
mil
[1] "1970-01-12 08:46:40 EST"
Factors
As could be seen below there are two different values that are
repeated male and female Gender is a factor with 2 different levels.
gender <- factor(c("male", "female", "female", "male"))
typeof(gender)
[1] "integer"
attributes(gender)
$levels
[1] "female" "male"
$class
[1] "factor"
unclass(gender)
[1] 2 1 1 2
attr(,"levels")
[1] "female" "male"
attributes(gender)
$levels
[1] "female" "male"
$class
[1] "factor"
The 2 levels male and female keep
gender
[1] male female female male
Levels: female male
Shows gender as characters instead of as a factor.
gender2 <- as.character(gender)
gender2
[1] "male" "female" "female" "male"
Coercion
Taking TRUE as 1 and FALSE as 0
sum(c(TRUE, TRUE, FALSE, FALSE))
[1] 2
#will become:
sum(c(1, 1, 0, 0))
[1] 2
Number 1 as a character is “1” as logical is TRUE. Number “0” as
logical is FALSE and FALSE as numeric is 0.
as.character(1)
[1] "1"
## "1"
as.logical(1)
[1] TRUE
## TRUE
as.numeric(FALSE)
[1] 0
## 0
Lists
Lists do not group together individual values; lists group together R
objects, they are used as building blocks to create many more
spohisticated types of R objects.
list1 <- list(100:130, "R", list(TRUE, FALSE))
list1
[[1]]
[1] 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
[[2]]
[1] "R"
[[3]]
[[3]][[1]]
[1] TRUE
[[3]][[2]]
[1] FALSE
Data Frames
Data frames are the two-dimensional version of a list. They are far
and away the most useful storage structure for data analysis, and they
provide an ideal way to store an entire deck of cards. You can think of
a data frame as R’s equivalent to the Excel spreadsheet because it
stores data in a similar format.
df <- data.frame(face = c("ace", "two", "six"),
suit = c("clubs", "clubs", "clubs"), value = c(1, 2, 3))
df
Data frames cannot combine columns of different lengths.
df <- data.frame(face = c("ace", "two", "six"),
suit = c("clubs", "clubs", "clubs"), value = c(1, 2, 3),
stringsAsFactors = FALSE)
typeof(df)
[1] "list"
class(df)
[1] "data.frame"
str(df)
'data.frame': 3 obs. of 3 variables:
$ face : chr "ace" "two" "six"
$ suit : chr "clubs" "clubs" "clubs"
$ value: num 1 2 3
df <- data.frame(face = c("ace", "two", "six"),
suit = c("clubs", "clubs", "clubs"), value = c(1, 2, 3),
stringsAsFactors = TRUE)
df
LS0tDQp0aXRsZTogIldlZWsgMiBQYXJ0MSAoT2JqZWN0IFR5cGVzKSINCmF1dGhvcjogIlJhdWwgUm9jZXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpJbiB0aGlzIGNsYXNzLCB5b3Ugd2lsbCBsZWFybiBob3cgdG86DQoNCiogU2F2ZSBuZXcgdHlwZXMgb2YgZGF0YSwgbGlrZSBjaGFyYWN0ZXIgc3RyaW5ncyBhbmQgbG9naWNhbCB2YWx1ZXMNCiogU2F2ZSBhIGRhdGEgc2V0IGFzIGEgdmVjdG9yLCBtYXRyaXgsIGFycmF5LCBsaXN0LCBvciBkYXRhIGZyYW1lDQoqIExvYWQgYW5kIHNhdmUgeW91ciBvd24gZGF0YSBzZXRzIHdpdGggUg0KKiBFeHRyYWN0IGluZGl2aWR1YWwgdmFsdWVzIGZyb20gYSBkYXRhIHNldA0KKiBDaGFuZ2UgaW5kaXZpZHVhbCB2YWx1ZXMgd2l0aGluIGEgZGF0YSBzZXQNCg0KIyBBdG9taWMgVmVjdG9ycw0KV2UgY3JlYXRlIGFuZCBhdG9taWMgdmVjdG9yIGRpZSB0aGF0IHN0b3JlcyA1IGVsZW1lbnRzLg0KYGBge3J9DQpkaWUgPC0gYygxLCAyLCAzLCA0LCA1LCA2KQ0KZGllDQojIyAxIDIgMyA0IDUgNg0KDQpgYGANCg0KDQpJcyBpdCBhIHZlY3Rvcj8NCmBgYHtyfQ0KaXMudmVjdG9yKGRpZSkNCmBgYA0KWWVzLCBpdCBpcyBhIHZlY3Rvcg0KDQpXZSBjcmVhdGUgYW4gYXRvbWljIHZlY3RvciB0aGF0IHN0b3JlcyA1IChvbmUgZWxlbWVudCkuDQpgYGB7cn0NCmZpdmUgPC0gNQ0KZml2ZQ0KYGBgDQoNCg0KSXMgb2JqZWN0IGZpdmUgYSB2ZWN0b3I/DQpgYGB7cn0NCmlzLnZlY3RvcihmaXZlKQ0KYGBgDQpZZXMsIGZpdmUgaXMgYSB2ZWN0b3Igd2l0aCBqdXN0IG9uZSBlbGVtZW50Lg0KDQpGdW5jdGlvbiBsZW5ndGggZ2V0cyBvciBzZXRzIHRoZSBsZW5ndGggb2YgdmVjdG9ycyAoaW5jbHVkaW5nIGxpc3RzKSBhbmQgZmFjdG9ycywgYW5kIG9mIGFueSBvdGhlciBSIG9iamVjdCBmb3Igd2hpY2ggYSBtZXRob2QgaGFzIGJlZW4gZGVmaW5lZC4gSW4gc2ltcGxlIHRlcm1zLCBsZW5ndGggcmV0dXJucyB0aGUgbGVuZ3RoIG9mIGFuIGF0b21pYyB2ZWN0b3IuDQpgYGB7cn0NCmxlbmd0aChmaXZlKQ0KbGVuZ3RoKGRpZSkNCmBgYA0KVmVjdG9yIGZpdmUgaGFzIG9uZSBlbGVtZW50IHdoaWxlIHZlY3RvciBkaWUgaGFzIDYgZWxlbWVudHMuDQoNCkVhY2ggYXRvbWljIHZlY3RvciBzdG9yZXMgaXRzIHZhbHVlcyBhcyBhIG9uZS1kaW1lbnNpb25hbCB2ZWN0b3IsIGFuZCBlYWNoIGF0b21pYyB2ZWN0b3IgY2FuIG9ubHkgc3RvcmUgb25lIHR5cGUgb2YgZGF0YS4gUiByZWNvZ25pemVzIHNpeCBiYXNpYyB0eXBlcyBvZiBhdG9taWMgdmVjdG9yczogZG91YmxlcywgaW50ZWdlcnMsIGNoYXJhY3RlcnMsIGxvZ2ljYWxzLCBjb21wbGV4LCBhbmQgcmF3Lg0KYGBge3J9DQppbnQgPC0gMUwNCnRleHQgPC0gImFjZSINCmRvX3VibGUgPC0gMzAgIzY0IGJpdHMgdG8gc3RvcmUNCmxvZ2ljIDwtIFRSVUUNCmBgYA0KDQoNCkZsb2F0aW5nLXBvaW50IGVycm9ycyBhcmlzZSBkdWUgdG8gZWFjaCBkb3VibGUgYWNjdXJhY3kgdG8gYWJvdXQgMTYgc2lnbmlmaWNhbnQgZGlnaXRzLiBUaGlzIGludHJvZHVjZXMgYSBsaXR0bGUgYml0IG9mIGVycm9yLiBJbiBtb3N0IGNhc2VzLCB0aGlzIHJvdW5kaW5nIGVycm9yIHdpbGwgZ28gdW5ub3RpY2VkLiBIb3dldmVyLCBpbiBzb21lDQpzaXR1YXRpb25zLCB0aGUgcm91bmRpbmcgZXJyb3IgY2FuIGNhdXNlIHN1cnByaXNpbmcgcmVzdWx0cy4gRm9yIGV4YW1wbGUsIHlvdSBtYXkgZXhwZWN0DQp0aGUgcmVzdWx0IG9mIHRoZSBleHByZXNzaW9uIGJlbG93IHRvIGJlIHplcm8sIGJ1dCBpdCBpcyBub3Q6DQpgYGB7cn0NCnNxcnQoMileMiAtIDINCmBgYA0KUHJvYmxlbSBoZXJlIGlzIHRoYXQgcHJvZ3JhbSBjb21wdXRlIHNxdWFyZSByb290IG9mIDIuIFRoZSByZXN1bHQgb2YgdGhpcyBvcGVyYXRpb24gaXMgcm91bmRlZCBzbyBpdCBpcyBjb21wdXRpbmcgYW4gZXJyb3IuIFRoZW4sIHRoZSBudW1iZXIgd2hpY2ggaXMgZWxldmF0ZWQgdG8gMiwgaXMgYW4gYXBwcm94aW1hdGlvbiBvZiB0aGUgc3F1YXJlIHJvb3Qgb2YgMiB2YWx1ZSwgaXMgZ29pbmcgdG8gYmUgYW4gYXBwcm94aW1hdGlvbiB0byAyLg0KDQpPdGhlciB0eXBlcw0KYGBge3J9DQpjb21wIDwtIGMoMSArIDFpLCAxICsgMmksIDEgKyAzaSkNCmNvbXANCnJfcmF3IDwtIHJhdygzKQ0KcmF3DQojIyAwMCAwMCAwMA0KYGBgDQoNCg0KIyBBdHRyaWJ1dGVzDQpUaGUgbW9zdCBjb21tb24gYXR0cmlidXRlcyB0byBnaXZlIGFuIGF0b21pYyB2ZWN0b3IgYXJlIG5hbWVzLCBkaW1lbnNpb25zIChkaW0pLA0KYW5kIGNsYXNzZXMuIE5vdGljZSBob3cgb2JqZWN0IGRpZSBoYXMgbm8gbmFtZXMgYWZ0ZXIgd2UgY3JlYXRlZCB0aGUgb2JqZWN0Lg0KYGBge3J9DQpuYW1lcyhkaWUpDQpgYGANCg0KDQpXZSBhc3NpZ24gbmFtZXMgdG8gdGhlIGVsZW1lbWVudHMuDQpgYGB7cn0NCm5hbWVzKGRpZSkgPC0gYygib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IikNCm5hbWVzKGRpZSkNCmBgYA0KDQoNCkxldCdzIHJlY2hlY2sgdGhlIGF0dHJpYnV0ZXMgZnVuY3Rpb24uDQpgYGB7cn0NCmF0dHJpYnV0ZXMoZGllKQ0KYGBgDQoNCg0KTmFtZXMgZG8gbm90IGFmZmVjdCB0aGUgdmFsdWVzLg0KYGBge3J9DQpuYW1lcyhkaWUpIDwtIGMoInVubyIsICJkb3MiLCAidHJlcyIsICJxdWF0cm8iLCAiY2luY28iLCAic2VpcyIpDQpkaWUNCmBgYA0KV2UgY2FuIGFsc28gcmVtb3ZlIG5hbWVzLg0KDQpgYGB7cn0NCm5hbWVzKGRpZSkgPC0gTlVMTA0KYGBgDQojIENyZWF0aW5nIG4gZGltZW5zaW9uYWwgU3RydWN0dXJlcw0KDQoNCkEgdmVjdG9yIGlzIGEgb25lLWRpbWVuc2lvbmFsIGFycmF5LiBBIG1hdHJpeCBpcyBhIHR3by1kaW1lbnNpb25hbCBhcnJheTsgdGhlcmVmb3JlIGlzIHRoZSBzYW1lIHRoaW5nIGFzIGEgbWF0cml4Lg0KTW9kaWZ5aW5nIHRoZSBkaW0gYXR0cmlidXRlIG9mIGFuIGF0b21pYyB2ZWN0b3IgaW50byBlaXRoZXIgYSBtYXRyaXggb3IgYW4gYXJyYXkgd2l0aCBtb3JlIHRoYW4gdGhyZWUgZGltZW5zaW9ucy4gDQoNCg0KRm9yIGV4YW1wbGUgeW91IGNhbiByZW9yZ2FuaXplIGRpZSBpbnRvIGEgMiDDlyAzIG1hdHJpeC4NCmBgYHtyfQ0KZGltKGRpZSkgPC0gYygyLCAzKQ0KZGllDQpgYGANCg0KDQpSIHdpbGwgYWx3YXlzIHVzZSB0aGUgZmlyc3QgdmFsdWUgaW4gZGltIGZvciB0aGUgbnVtYmVyIG9mIHJvd3MgYW5kIHRoZSBzZWNvbmQgdmFsdWUgZm9yDQp0aGUgbnVtYmVyIG9mIGNvbHVtbnMuIEluIGdlbmVyYWwsIHJvd3MgYWx3YXlzIGNvbWUgZmlyc3QgaW4gUiBvcGVyYXRpb25zIHRoYXQgZGVhbA0Kd2l0aCBib3RoIHJvd3MgYW5kIGNvbHVtbnMuDQpgYGB7cn0NCmRpbShkaWUpIDwtIGMoMywgMikNCmRpZQ0KYGBgDQoNCg0KTm90aWNlIGhvdyBieSBkZWZhdWx0IFIgZmlsbHMgdXAgZWFjaCBtYXRyaXggYnkgY29sdW1ucy4gDQpgYGB7cn0NCiNoeXBlcmN1YmUNCmRpbShkaWUpIDwtIGMoMSwgMiwgMykNCmNsYXNzKGRpZSkNCg0KYGBgDQoNCg0KSWYgeW914oCZZCBsaWtlIG1vcmUgY29udHJvbCBvdmVyIGhvdyB0aGUgZGF0YSBpcyBzdG9yZWQsIHlvdSBjYW4gdXNlIG9uZSBvZiBSJ3MgaGVscGVyIGZ1bmN0aW9ucywgbWF0cml4IG9yIGFycmF5Lg0KVGhleSBkbyB0aGUgc2FtZSB0aGluZyBhcyBjaGFuZ2luZyB0aGUgZGltIGF0dHJpYnV0ZSwgYnV0IHRoZXkgcHJvdmlkZSBleHRyYSBhcmd1bWVudHMgdG8gY3VzdG9taXplIHRoZSBwcm9jZXNzLg0KIyBNYXRyaXggRnVuY3Rpb24NCmBgYHtyfQ0KbSA8LSBtYXRyaXgoZGllLCBucm93ID0gMikNCm0NCmBgYA0KDQpzcGVjaWZ5aW5nIGJ5cm93PVRSVUUsIHZhbHVlcyBmb2xsb3dzIHRoZSByb3dzIG9yZGVyDQpgYGB7cn0NCm0gPC0gbWF0cml4KGRpZSwgbnJvdyA9IDIsIGJ5cm93ID0gVFJVRSkNCm0NCmBgYA0KDQoNCiMgQXJyYXkgRnVuY3Rpb24NClRoZSBhcnJheSBmdW5jdGlvbiBjcmVhdGVzIGFuIG4tZGltZW5zaW9uYWwgYXJyYXkuDQpgYGB7cn0NCmFyIDwtIGFycmF5KGMoMTE6MTQsIDIxOjI0LCAzMTozNCksIGRpbSA9IGMoMiwgMiwgMykpDQphcg0KYGBgDQoNCk5vdGljZSB0aGF0IGNoYW5naW5nIHRoZSBkaW1lbnNpb25zIG9mIHlvdXIgb2JqZWN0IHdpbGwgbm90IGNoYW5nZSB0aGUgdHlwZSBvZiB0aGUgb2JqZWN0LA0KYnV0IGl0IHdpbGwgY2hhbmdlIHRoZSBvYmplY3TigJlzIGNsYXNzIGF0dHJpYnV0ZToNCmBgYHtyfQ0KZGltKGRpZSkgPC0gYygyLCAzKQ0KdHlwZW9mKGRpZSkNCmNsYXNzKGRpZSkNCmBgYA0KDQpOb3RlIHRoYXQgYW4gb2JqZWN04oCZcyBjbGFzcyBhdHRyaWJ1dGUgd2lsbCBub3QgYWx3YXlzIGFwcGVhciB3aGVuIHlvdSBydW4gYXR0cmlidXRlczsNCnlvdSBtYXkgbmVlZCB0byBzcGVjaWZpY2FsbHkgc2VhcmNoIGZvciBpdCB3aXRoIGNsYXNzOg0KYXR0cmlidXRlcyhkaWUpDQpgYGB7cn0NCmF0dHJpYnV0ZXMoZGllKQ0KYGBgDQoNCllvdSBjYW4gYXBwbHkgY2xhc3MgdG8gb2JqZWN0cyB0aGF0IGRvIG5vdCBoYXZlIGEgY2xhc3MgYXR0cmlidXRlLiBjbGFzcyB3aWxsIHJldHVybiBhDQp2YWx1ZSBiYXNlZCBvbiB0aGUgb2JqZWN04oCZcyBhdG9taWMgdHlwZS4gTm90aWNlIHRoYXQgdGhlIOKAnGNsYXNz4oCdIG9mIGEgZG91YmxlIGlzIOKAnG51bWVyaWMs4oCdDQphbiBvZGQgZGV2aWF0aW9uLCBidXQgb25lIEkgYW0gdGhhbmtmdWwgZm9yLiBJIHRoaW5rIHRoYXQgdGhlIG1vc3QgaW1wb3J0YW50IHByb3BlcnR5DQpvZiBhIGRvdWJsZSB2ZWN0b3IgaXMgdGhhdCBpdCBjb250YWlucyBudW1iZXJzLCBhIHByb3BlcnR5IHRoYXQg4oCcbnVtZXJpY+KAnSBtYWtlcyBvYnZpb3VzOg0KYGBge3J9DQpjbGFzcygiSGVsbG8iKQ0KY2xhc3MoNSkNCmBgYA0KDQpgYGB7cn0NCm5vdyA8LSBTeXMudGltZSgpDQpub3cNCnR5cGVvZihub3cpDQpjbGFzcyhub3cpDQpgYGANClBPU0lYY3QgaXMgYSBmcmFtZXdvcmsgZm9yIHJlcHJlc2VudGluZyBkYXRlcyBhbmQgdGltZXMuIFRpbWUgaXMgcmVwcmVzZW50ZWQgYnkgdGhlIG51bWJlciBvZiBzZWNvbmRzIHRoYXQgaGF2ZSBwYXNzZWQgYmV0d2VlbiBub3cgYW5kMTI6MDAgQU0gSmFudWFyeSAxc3QgMTk3MCAoaW4gdGhlIFVuaXZlcnNhbCBUaW1lIENvb3JkaW5hdGVkIChVVEMpDQp6b25lKS4gWW91IGNhbiBzZWUgdGhpcyBudW1iZXIgYnkgcmVtb3ZpbmcgdGhlIGNsYXNzIGF0dHJpYnV0ZSBvZiBub3csIG9yIGJ5IHVzaW5nIHRoZSB1bg0KY2xhc3MgZnVuY3Rpb24sIHdoaWNoIGRvZXMgdGhlIHNhbWUgdGhpbmc6DQpgYGB7cn0NCnVuY2xhc3Mobm93KQ0KYGBgDQpSIHRoZW4gZ2l2ZXMgdGhlIGRvdWJsZSB2ZWN0b3IgYSBjbGFzcyBhdHRyaWJ1dGUgdGhhdCBjb250YWlucyB0d28gY2xhc3NlcywgIlBPU0lYY3QiDQphbmQgIlBPU0lYdCIuIFRoaXMgYXR0cmlidXRlIGFsZXJ0cyBSIGZ1bmN0aW9ucyB0aGF0IHRoZXkgYXJlIGRlYWxpbmcgd2l0aCBhIFBPU0lYY3QNCnRpbWUsIHNvIHRoZXkgY2FuIHRyZWF0IGl0IGluIGEgc3BlY2lhbCB3YXkuIEZvciBleGFtcGxlLCBSIGZ1bmN0aW9ucyB3aWxsIHVzZSB0aGUgUE9TSVhjdA0Kc3RhbmRhcmQgdG8gY29udmVydCB0aGUgdGltZSBpbnRvIGEgdXNlci1mcmllbmRseSBjaGFyYWN0ZXIgc3RyaW5nIGJlZm9yZSBkaXNwbGF5aW5nIGl0Lg0KWW91IGNhbiB0YWtlIGFkdmFudGFnZSBvZiB0aGlzIHN5c3RlbSBieSBnaXZpbmcgdGhlIFBPU0lYY3QgY2xhc3MgdG8gcmFuZG9tIFIgb2JqZWN0cy4NCkZvciBleGFtcGxlLCBoYXZlIHlvdSBldmVyIHdvbmRlcmVkIHdoYXQgZGF5IGl0IHdhcyBhIG1pbGxpb24gc2Vjb25kcyBhZnRlciAxMjowMCBhLm0uDQpKYW4uIDEsIDE5NzA/DQpgYGB7cn0NCm1pbCA8LSAxMDAwMDAwDQptaWwNCmNsYXNzKG1pbCkgPC0gYygiUE9TSVhjdCIsICJQT1NJWHQiKQ0KbWlsDQpgYGANCg0KIyBGYWN0b3JzDQpBcyBjb3VsZCBiZSBzZWVuIGJlbG93IHRoZXJlIGFyZSB0d28gZGlmZmVyZW50IHZhbHVlcyB0aGF0IGFyZSByZXBlYXRlZCBtYWxlIGFuZCBmZW1hbGUgR2VuZGVyIGlzIGEgZmFjdG9yIHdpdGggMiBkaWZmZXJlbnQgbGV2ZWxzLg0KYGBge3J9DQpnZW5kZXIgPC0gZmFjdG9yKGMoIm1hbGUiLCAiZmVtYWxlIiwgImZlbWFsZSIsICJtYWxlIikpDQp0eXBlb2YoZ2VuZGVyKQ0KYXR0cmlidXRlcyhnZW5kZXIpDQpgYGANCg0KDQpgYGB7cn0NCnVuY2xhc3MoZ2VuZGVyKQ0KYGBgDQpUaGUgMiBsZXZlbHMgbWFsZSBhbmQgZmVtYWxlIGtlZXANCmBgYHtyfQ0KZ2VuZGVyDQpgYGANCg0KU2hvd3MgZ2VuZGVyIGFzIGNoYXJhY3RlcnMgaW5zdGVhZCBvZiBhcyBhIGZhY3Rvci4NCmBgYHtyfQ0KZ2VuZGVyMiA8LSBhcy5jaGFyYWN0ZXIoZ2VuZGVyKQ0KZ2VuZGVyMg0KDQpgYGANCg0KDQojIENvZXJjaW9uDQpUYWtpbmcgVFJVRSBhcyAxIGFuZCBGQUxTRSBhcyAwDQpgYGB7cn0NCnN1bShjKFRSVUUsIFRSVUUsIEZBTFNFLCBGQUxTRSkpDQojd2lsbCBiZWNvbWU6DQpzdW0oYygxLCAxLCAwLCAwKSkNCmBgYA0KDQoNCk51bWJlciAxIGFzIGEgY2hhcmFjdGVyIGlzICIxIiBhcyBsb2dpY2FsIGlzIFRSVUUuIE51bWJlciAiMCIgYXMgbG9naWNhbCBpcyBGQUxTRSBhbmQgRkFMU0UgYXMgbnVtZXJpYyBpcyAwLg0KYGBge3J9DQphcy5jaGFyYWN0ZXIoMSkNCiMjICIxIg0KYXMubG9naWNhbCgxKQ0KIyMgVFJVRQ0KYXMubnVtZXJpYyhGQUxTRSkNCiMjIDANCmBgYA0KDQojIExpc3RzDQpMaXN0cyBkbyBub3QgZ3JvdXAgdG9nZXRoZXIgaW5kaXZpZHVhbCB2YWx1ZXM7IGxpc3RzIGdyb3VwIHRvZ2V0aGVyIFIgb2JqZWN0cywgdGhleSBhcmUgdXNlZCBhcyBidWlsZGluZyBibG9ja3MgdG8gY3JlYXRlIG1hbnkgbW9yZSBzcG9oaXN0aWNhdGVkIHR5cGVzIG9mIFIgb2JqZWN0cy4NCmBgYHtyfQ0KbGlzdDEgPC0gbGlzdCgxMDA6MTMwLCAiUiIsIGxpc3QoVFJVRSwgRkFMU0UpKQ0KbGlzdDENCmBgYA0KDQojIERhdGEgRnJhbWVzDQpEYXRhIGZyYW1lcyBhcmUgdGhlIHR3by1kaW1lbnNpb25hbCB2ZXJzaW9uIG9mIGEgbGlzdC4gVGhleSBhcmUgZmFyIGFuZCBhd2F5IHRoZSBtb3N0DQp1c2VmdWwgc3RvcmFnZSBzdHJ1Y3R1cmUgZm9yIGRhdGEgYW5hbHlzaXMsIGFuZCB0aGV5IHByb3ZpZGUgYW4gaWRlYWwgd2F5IHRvIHN0b3JlIGFuIGVudGlyZQ0KZGVjayBvZiBjYXJkcy4gWW91IGNhbiB0aGluayBvZiBhIGRhdGEgZnJhbWUgYXMgUuKAmXMgZXF1aXZhbGVudCB0byB0aGUgRXhjZWwgc3ByZWFkc2hlZXQNCmJlY2F1c2UgaXQgc3RvcmVzIGRhdGEgaW4gYSBzaW1pbGFyIGZvcm1hdC4NCmBgYHtyfQ0KZGYgPC0gZGF0YS5mcmFtZShmYWNlID0gYygiYWNlIiwgInR3byIsICJzaXgiKSwNCnN1aXQgPSBjKCJjbHVicyIsICJjbHVicyIsICJjbHVicyIpLCB2YWx1ZSA9IGMoMSwgMiwgMykpDQpkZg0KYGBgDQpEYXRhIGZyYW1lcyBjYW5ub3QgY29tYmluZSBjb2x1bW5zIG9mIGRpZmZlcmVudCBsZW5ndGhzLg0KYGBge3J9DQpkZiA8LSBkYXRhLmZyYW1lKGZhY2UgPSBjKCJhY2UiLCAidHdvIiwgInNpeCIpLA0Kc3VpdCA9IGMoImNsdWJzIiwgImNsdWJzIiwgImNsdWJzIiksIHZhbHVlID0gYygxLCAyLCAzKSwNCnN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCmBgYA0KDQoNCmBgYHtyfQ0KdHlwZW9mKGRmKQ0KY2xhc3MoZGYpDQpzdHIoZGYpDQpgYGANCg0KDQoNCmBgYHtyfQ0KZGYgPC0gZGF0YS5mcmFtZShmYWNlID0gYygiYWNlIiwgInR3byIsICJzaXgiKSwNCnN1aXQgPSBjKCJjbHVicyIsICJjbHVicyIsICJjbHVicyIpLCB2YWx1ZSA9IGMoMSwgMiwgMyksDQpzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpkZg0KYGBg