Question 1

The MNIST dataset is one of the most well-known datasets in the field of machine learning and is widely used for training various image processing systems. It contains images of handwritten digits, with each image being a 28x28 pixel grayscale image. Each pixel ranges from 0 (white) to 255 (black). The dataset is structured as follows:

  • Label: This variable denotes the class of the handwritten digit image. It represents the digit depicted in the image (0 through 9). In some variations of the MNIST dataset (though not standard), the label might represent letters if it’s modified and extended to alphabets.

  • Pix1, Pix2, …, Pix784: These variables represent the pixel values of the 28x28 pixel images. Each image is “flattened” into a single row with 784 columns (28 multiplied by 28), where each PixN corresponds to the grayscale value of a pixel. Each pixel value ranges from 0 to 255, where 0 corresponds to a completely white pixel and 255 corresponds to a completely black pixel.

Structure of the Data:

  • Rows: Each row in the dataset corresponds to a single image (a single handwritten digit) along with its label.
  • Columns: The first column is typically the Label and the remaining 784 columns are the pixel intensity values from the top-left to the bottom-right of the image.

Goal: The goal with MNIST is to build a model that can predict the Label from the 784 pixel values, effectively allowing a computer to recognize handwritten digits.

# Load necessary libraries
library(class)
install.packages("gmodels")
Installing package into 'C:/Users/jfern/AppData/Local/R/win-library/4.4'
(as 'lib' is unspecified)
Error in contrib.url(repos, "source"): trying to use CRAN without setting a mirror
library(gmodels)
Warning: package 'gmodels' was built under R version 4.4.3
# Load MNIST dataset
DataMnist <- readRDS("MN500.rds")
DataMnist$Label <- factor(DataMnist$Label)

# Create Training and Testing Data
set.seed(123)
index <- sample(1:nrow(DataMnist), 0.7 * nrow(DataMnist))
DataTrain <- DataMnist[index, ]
DataTest <- DataMnist[-index, ]

# Prepare the data for KNN (excluding the label column for training/testing dataset)
train_labels <- DataTrain$Label
test_labels <- DataTest$Label

# Remove the label column from the datasets for KNN
DataTrain <- DataTrain[, -1]
DataTest <- DataTest[, -1]

# Perform KNN for k = 5
predicted_labels <- knn(train = DataTrain, test = DataTest, cl = train_labels,  5)

# Create Confusion Matrix using CrossTable
CrossTable(x = test_labels, y = predicted_labels, prop.chisq = FALSE)

 
   Cell Contents
|-------------------------|
|                       N |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|

 
Total Observations in Table:  150 

 
             | predicted_labels 
 test_labels |         0 |         1 |         2 |         3 |         4 |         5 |         6 |         7 |         8 |         9 | Row Total | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           0 |        12 |         0 |         1 |         0 |         0 |         0 |         0 |         0 |         0 |         0 |        13 | 
             |     0.923 |     0.000 |     0.077 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.087 | 
             |     0.923 |     0.000 |     0.125 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |           | 
             |     0.080 |     0.000 |     0.007 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           1 |         0 |        23 |         0 |         0 |         0 |         0 |         0 |         0 |         0 |         0 |        23 | 
             |     0.000 |     1.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.153 | 
             |     0.000 |     0.742 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |           | 
             |     0.000 |     0.153 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           2 |         0 |         2 |         6 |         0 |         1 |         0 |         0 |         1 |         0 |         0 |        10 | 
             |     0.000 |     0.200 |     0.600 |     0.000 |     0.100 |     0.000 |     0.000 |     0.100 |     0.000 |     0.000 |     0.067 | 
             |     0.000 |     0.065 |     0.750 |     0.000 |     0.067 |     0.000 |     0.000 |     0.059 |     0.000 |     0.000 |           | 
             |     0.000 |     0.013 |     0.040 |     0.000 |     0.007 |     0.000 |     0.000 |     0.007 |     0.000 |     0.000 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           3 |         0 |         1 |         0 |         9 |         0 |         0 |         0 |         1 |         0 |         0 |        11 | 
             |     0.000 |     0.091 |     0.000 |     0.818 |     0.000 |     0.000 |     0.000 |     0.091 |     0.000 |     0.000 |     0.073 | 
             |     0.000 |     0.032 |     0.000 |     0.900 |     0.000 |     0.000 |     0.000 |     0.059 |     0.000 |     0.000 |           | 
             |     0.000 |     0.007 |     0.000 |     0.060 |     0.000 |     0.000 |     0.000 |     0.007 |     0.000 |     0.000 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           4 |         0 |         0 |         1 |         0 |        10 |         0 |         0 |         0 |         0 |         2 |        13 | 
             |     0.000 |     0.000 |     0.077 |     0.000 |     0.769 |     0.000 |     0.000 |     0.000 |     0.000 |     0.154 |     0.087 | 
             |     0.000 |     0.000 |     0.125 |     0.000 |     0.667 |     0.000 |     0.000 |     0.000 |     0.000 |     0.118 |           | 
             |     0.000 |     0.000 |     0.007 |     0.000 |     0.067 |     0.000 |     0.000 |     0.000 |     0.000 |     0.013 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           5 |         0 |         2 |         0 |         1 |         2 |        12 |         1 |         0 |         0 |         0 |        18 | 
             |     0.000 |     0.111 |     0.000 |     0.056 |     0.111 |     0.667 |     0.056 |     0.000 |     0.000 |     0.000 |     0.120 | 
             |     0.000 |     0.065 |     0.000 |     0.100 |     0.133 |     0.800 |     0.059 |     0.000 |     0.000 |     0.000 |           | 
             |     0.000 |     0.013 |     0.000 |     0.007 |     0.013 |     0.080 |     0.007 |     0.000 |     0.000 |     0.000 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           6 |         1 |         0 |         0 |         0 |         0 |         0 |        16 |         0 |         0 |         0 |        17 | 
             |     0.059 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.941 |     0.000 |     0.000 |     0.000 |     0.113 | 
             |     0.077 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.941 |     0.000 |     0.000 |     0.000 |           | 
             |     0.007 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.107 |     0.000 |     0.000 |     0.000 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           7 |         0 |         0 |         0 |         0 |         0 |         0 |         0 |        13 |         0 |         0 |        13 | 
             |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     1.000 |     0.000 |     0.000 |     0.087 | 
             |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.765 |     0.000 |     0.000 |           | 
             |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.000 |     0.087 |     0.000 |     0.000 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           8 |         0 |         2 |         0 |         0 |         1 |         3 |         0 |         0 |         6 |         1 |        13 | 
             |     0.000 |     0.154 |     0.000 |     0.000 |     0.077 |     0.231 |     0.000 |     0.000 |     0.462 |     0.077 |     0.087 | 
             |     0.000 |     0.065 |     0.000 |     0.000 |     0.067 |     0.200 |     0.000 |     0.000 |     0.857 |     0.059 |           | 
             |     0.000 |     0.013 |     0.000 |     0.000 |     0.007 |     0.020 |     0.000 |     0.000 |     0.040 |     0.007 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
           9 |         0 |         1 |         0 |         0 |         1 |         0 |         0 |         2 |         1 |        14 |        19 | 
             |     0.000 |     0.053 |     0.000 |     0.000 |     0.053 |     0.000 |     0.000 |     0.105 |     0.053 |     0.737 |     0.127 | 
             |     0.000 |     0.032 |     0.000 |     0.000 |     0.067 |     0.000 |     0.000 |     0.118 |     0.143 |     0.824 |           | 
             |     0.000 |     0.007 |     0.000 |     0.000 |     0.007 |     0.000 |     0.000 |     0.013 |     0.007 |     0.093 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
Column Total |        13 |        31 |         8 |        10 |        15 |        15 |        17 |        17 |         7 |        17 |       150 | 
             |     0.087 |     0.207 |     0.053 |     0.067 |     0.100 |     0.100 |     0.113 |     0.113 |     0.047 |     0.113 |           | 
-------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|

 
# Calculate accuracy
accuracy <- mean(predicted_labels == test_labels)
print(paste("Accuracy:", round(accuracy * 100, 2), "%"))
[1] "Accuracy: 80.67 %"

MODEL PERFORMS AT 80.67% ACCURACY

Question 2

The Titanic dataset is a classic dataset in data science and machine learning typically used for demonstrating classification tasks. This dataset is available in the file `Titanic.csv1. Here’s a general description of the Titanic dataset and its variables:

Description of the Titanic Dataset

The dataset contains data about the passengers who were onboard the ill-fated RMS Titanic. Your goal is to predict the survival of the passengers based on various features. Below are the variables you will use in this dataset:

Survived: Indicates if the passenger Survived (1) or did not survive (0).

Class: Passenger class, a proxy for socio-economic status (1 = 1st class, 2 = 2nd class, 3 = 3rd class).

Name: Full name of the passenger.

Sex: Gender of the passenger (male or female).

Age: Age of the passenger in years. Some entries may have missing ages.

SibSp: Number of siblings and spouses aboard the Titanic.

Parch: Number of parents and children aboard the Titanic.

Fare: Passenger fare.

# Load necessary libraries
library(rpart)
library(gmodels)

# Load the dataset; assuming the Titanic dataset
Titanic <- read.csv("Titanic.csv")

# Select relevant columns
Titanic <- Titanic[,c("Survived", "Sex", "Class", "Age", "Fare")]

# Factorize the Survived column
Titanic$Survived <- as.factor(Titanic$Survived)

# Set seed and split the data
set.seed(777)
train_indices <- sample(1:nrow(Titanic), 0.75 * nrow(Titanic))
DataTrain <- Titanic[train_indices, ]
DataTest <- Titanic[-train_indices, ]

# Train the decision tree model
ModelDesignDecTree <- rpart(Survived ~ ., data = DataTrain, method = "class", control = rpart.control(maxdepth = 3))

# Visualize the decision tree
library(rpart.plot)
Warning: package 'rpart.plot' was built under R version 4.4.3
rpart.plot(ModelDesignDecTree, yes.text = "YES", no.text = "NO", roundint = FALSE)

# Predict on the test set
predicted_labels <- predict(ModelDesignDecTree, DataTest, type = "class")

# Create confusion matrix using CrossTable
CrossTable(x = DataTest$Survived, y = predicted_labels, prop.chisq = FALSE)

 
   Cell Contents
|-------------------------|
|                       N |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|

 
Total Observations in Table:  222 

 
                  | predicted_labels 
DataTest$Survived |         0 |         1 | Row Total | 
------------------|-----------|-----------|-----------|
                0 |       115 |        12 |       127 | 
                  |     0.906 |     0.094 |     0.572 | 
                  |     0.846 |     0.140 |           | 
                  |     0.518 |     0.054 |           | 
------------------|-----------|-----------|-----------|
                1 |        21 |        74 |        95 | 
                  |     0.221 |     0.779 |     0.428 | 
                  |     0.154 |     0.860 |           | 
                  |     0.095 |     0.333 |           | 
------------------|-----------|-----------|-----------|
     Column Total |       136 |        86 |       222 | 
                  |     0.613 |     0.387 |           | 
------------------|-----------|-----------|-----------|

 
# Calculate accuracy
accuracy <- mean(predicted_labels == DataTest$Survived)
print(paste("Accuracy:", round(accuracy * 100, 2), "%"))
[1] "Accuracy: 85.14 %"

WITH A 85% ACCURACY THE TREE PREDICTS

  1. What is the survival rate for adult male passengers 13 years or older, regardless of the class they traveled in and the fare they paid?

Answer: 9% with 46% Data

  1. What is the survival rate for young male passengers (younger than 13 years), regardless of which class they traveled and the fare they paid?

Answer: 19% with 66% Data

  1. What is the survival rate for young male passengers (younger than 13 years) traveling in Third Class regardless of the fare they paid?

Answer: 79%

  1. What is the survival rate for female passengers, regardless of age and not considering the class they traveled in or the fare they paid?

Answer: 72% with 34% Data

  1. When considering the class female passengers traveled in, we can see female passengers, regardless of age, had a survival rate of 93% when they traveled in First or Second Class regardless of the fare they paid.
LS0tDQp0aXRsZTogIkJBTkwgMzIwMDogTWFjaGluZSBMZWFybmluZyAtLSBTdXBlcnZpc2VkIg0Kc3VidGl0bGU6ICJNaWR0ZXJtIg0KYXV0aG9yOiAiSm95c3RvbiBGZXJuYW5kZXMiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZSwgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdGhlbWU6IGZsYXRseQ0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIHRvY19kZXB0aDogMw0KICAgIG51bWJlcl9zZWN0aW9uczogVFJVRQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFLCBjYWNoZSA9IEZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGV2YWwgPSBUUlVFLCBlcnJvciA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZ3MgPSBGQUxTRSwgbWVzc2FnZXMgPSBGQUxTRSwgdGlkeSA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IEZBTFNFKQ0KIyBsb2FkIGxpYnJhcmllcw0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCg0KDQojIyMgUXVlc3Rpb24gMSB7LX0NCg0KVGhlIE1OSVNUIGRhdGFzZXQgaXMgb25lIG9mIHRoZSBtb3N0IHdlbGwta25vd24gZGF0YXNldHMgaW4gdGhlIGZpZWxkIG9mIG1hY2hpbmUgbGVhcm5pbmcgYW5kIGlzIHdpZGVseSB1c2VkIGZvciB0cmFpbmluZyB2YXJpb3VzIGltYWdlIHByb2Nlc3Npbmcgc3lzdGVtcy4gSXQgY29udGFpbnMgaW1hZ2VzIG9mIGhhbmR3cml0dGVuIGRpZ2l0cywgd2l0aCBlYWNoIGltYWdlIGJlaW5nIGEgMjh4MjggcGl4ZWwgZ3JheXNjYWxlIGltYWdlLiBFYWNoIHBpeGVsIHJhbmdlcyBmcm9tIDAgKHdoaXRlKSB0byAyNTUgKGJsYWNrKS4gVGhlIGRhdGFzZXQgaXMgc3RydWN0dXJlZCBhcyBmb2xsb3dzOg0KDQotICoqTGFiZWwqKjogVGhpcyB2YXJpYWJsZSBkZW5vdGVzIHRoZSBjbGFzcyBvZiB0aGUgaGFuZHdyaXR0ZW4gZGlnaXQgaW1hZ2UuIEl0IHJlcHJlc2VudHMgdGhlIGRpZ2l0IGRlcGljdGVkIGluIHRoZSBpbWFnZSAoMCB0aHJvdWdoIDkpLiBJbiBzb21lIHZhcmlhdGlvbnMgb2YgdGhlIE1OSVNUIGRhdGFzZXQgKHRob3VnaCBub3Qgc3RhbmRhcmQpLCB0aGUgbGFiZWwgbWlnaHQgcmVwcmVzZW50IGxldHRlcnMgaWYgaXTigJlzIG1vZGlmaWVkIGFuZCBleHRlbmRlZCB0byBhbHBoYWJldHMuICANCg0KLSAqKlBpeDEsIFBpeDIsIC4uLiwgUGl4Nzg0Kio6IFRoZXNlIHZhcmlhYmxlcyByZXByZXNlbnQgdGhlIHBpeGVsIHZhbHVlcyBvZiB0aGUgMjh4MjggcGl4ZWwgaW1hZ2VzLiBFYWNoIGltYWdlIGlzICJmbGF0dGVuZWQiIGludG8gYSBzaW5nbGUgcm93IHdpdGggNzg0IGNvbHVtbnMgKDI4IG11bHRpcGxpZWQgYnkgMjgpLCB3aGVyZSBlYWNoIGBQaXhOYCBjb3JyZXNwb25kcyB0byB0aGUgZ3JheXNjYWxlIHZhbHVlIG9mIGEgcGl4ZWwuIEVhY2ggcGl4ZWwgdmFsdWUgcmFuZ2VzIGZyb20gMCB0byAyNTUsIHdoZXJlIDAgY29ycmVzcG9uZHMgdG8gYSBjb21wbGV0ZWx5IHdoaXRlIHBpeGVsIGFuZCAyNTUgY29ycmVzcG9uZHMgdG8gYSBjb21wbGV0ZWx5IGJsYWNrIHBpeGVsLg0KDQoqKlN0cnVjdHVyZSBvZiB0aGUgRGF0YToqKg0KDQotICoqUm93cyoqOiBFYWNoIHJvdyBpbiB0aGUgZGF0YXNldCBjb3JyZXNwb25kcyB0byBhIHNpbmdsZSBpbWFnZSAoYSBzaW5nbGUgaGFuZHdyaXR0ZW4gZGlnaXQpIGFsb25nIHdpdGggaXRzIGxhYmVsLiAgDQotICoqQ29sdW1ucyoqOiBUaGUgZmlyc3QgY29sdW1uIGlzIHR5cGljYWxseSB0aGUgYExhYmVsYCBhbmQgdGhlIHJlbWFpbmluZyA3ODQgY29sdW1ucyBhcmUgdGhlIHBpeGVsIGludGVuc2l0eSB2YWx1ZXMgZnJvbSB0aGUgdG9wLWxlZnQgdG8gdGhlIGJvdHRvbS1yaWdodCBvZiB0aGUgaW1hZ2UuDQoNCioqKkdvYWw6KioqIA0KVGhlIGdvYWwgd2l0aCBNTklTVCBpcyB0byBidWlsZCBhIG1vZGVsIHRoYXQgY2FuIHByZWRpY3QgdGhlIGBMYWJlbGAgZnJvbSB0aGUgNzg0IHBpeGVsIHZhbHVlcywgZWZmZWN0aXZlbHkgYWxsb3dpbmcgYSBjb21wdXRlciB0byByZWNvZ25pemUgaGFuZHdyaXR0ZW4gZGlnaXRzLg0KDQoNCmBgYHtyIFExfQ0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMNCmxpYnJhcnkoY2xhc3MpDQppbnN0YWxsLnBhY2thZ2VzKCJnbW9kZWxzIikNCmxpYnJhcnkoZ21vZGVscykNCg0KIyBMb2FkIE1OSVNUIGRhdGFzZXQNCkRhdGFNbmlzdCA8LSByZWFkUkRTKCJNTjUwMC5yZHMiKQ0KRGF0YU1uaXN0JExhYmVsIDwtIGZhY3RvcihEYXRhTW5pc3QkTGFiZWwpDQoNCiMgQ3JlYXRlIFRyYWluaW5nIGFuZCBUZXN0aW5nIERhdGENCnNldC5zZWVkKDEyMykNCmluZGV4IDwtIHNhbXBsZSgxOm5yb3coRGF0YU1uaXN0KSwgMC43ICogbnJvdyhEYXRhTW5pc3QpKQ0KRGF0YVRyYWluIDwtIERhdGFNbmlzdFtpbmRleCwgXQ0KRGF0YVRlc3QgPC0gRGF0YU1uaXN0Wy1pbmRleCwgXQ0KDQojIFByZXBhcmUgdGhlIGRhdGEgZm9yIEtOTiAoZXhjbHVkaW5nIHRoZSBsYWJlbCBjb2x1bW4gZm9yIHRyYWluaW5nL3Rlc3RpbmcgZGF0YXNldCkNCnRyYWluX2xhYmVscyA8LSBEYXRhVHJhaW4kTGFiZWwNCnRlc3RfbGFiZWxzIDwtIERhdGFUZXN0JExhYmVsDQoNCiMgUmVtb3ZlIHRoZSBsYWJlbCBjb2x1bW4gZnJvbSB0aGUgZGF0YXNldHMgZm9yIEtOTg0KRGF0YVRyYWluIDwtIERhdGFUcmFpblssIC0xXQ0KRGF0YVRlc3QgPC0gRGF0YVRlc3RbLCAtMV0NCg0KIyBQZXJmb3JtIEtOTiBmb3IgayA9IDUNCnByZWRpY3RlZF9sYWJlbHMgPC0ga25uKHRyYWluID0gRGF0YVRyYWluLCB0ZXN0ID0gRGF0YVRlc3QsIGNsID0gdHJhaW5fbGFiZWxzLCAgNSkNCg0KIyBDcmVhdGUgQ29uZnVzaW9uIE1hdHJpeCB1c2luZyBDcm9zc1RhYmxlDQpDcm9zc1RhYmxlKHggPSB0ZXN0X2xhYmVscywgeSA9IHByZWRpY3RlZF9sYWJlbHMsIHByb3AuY2hpc3EgPSBGQUxTRSkNCg0KIyBDYWxjdWxhdGUgYWNjdXJhY3kNCmFjY3VyYWN5IDwtIG1lYW4ocHJlZGljdGVkX2xhYmVscyA9PSB0ZXN0X2xhYmVscykNCnByaW50KHBhc3RlKCJBY2N1cmFjeToiLCByb3VuZChhY2N1cmFjeSAqIDEwMCwgMiksICIlIikpDQpgYGANCg0KKipNT0RFTCBQRVJGT1JNUyBBVCA4MC42NyUgQUNDVVJBQ1kqKg0KDQojIyMgUXVlc3Rpb24gMiB7LX0NCg0KVGhlIFRpdGFuaWMgZGF0YXNldCBpcyBhIGNsYXNzaWMgZGF0YXNldCBpbiBkYXRhIHNjaWVuY2UgYW5kIG1hY2hpbmUgbGVhcm5pbmcgdHlwaWNhbGx5IHVzZWQgZm9yIGRlbW9uc3RyYXRpbmcgY2xhc3NpZmljYXRpb24gdGFza3MuIFRoaXMgZGF0YXNldCBpcyBhdmFpbGFibGUgaW4gdGhlIGZpbGUgYFRpdGFuaWMuY3N2MS4gSGVyZSdzIGEgZ2VuZXJhbCBkZXNjcmlwdGlvbiBvZiB0aGUgVGl0YW5pYyBkYXRhc2V0IGFuZCBpdHMgdmFyaWFibGVzOg0KDQojIyMgRGVzY3JpcHRpb24gb2YgdGhlIFRpdGFuaWMgRGF0YXNldCB7LX0NCg0KVGhlIGRhdGFzZXQgY29udGFpbnMgZGF0YSBhYm91dCB0aGUgcGFzc2VuZ2VycyB3aG8gd2VyZSBvbmJvYXJkIHRoZSBpbGwtZmF0ZWQgUk1TIFRpdGFuaWMuIFlvdXIgZ29hbCBpcyB0byBwcmVkaWN0IHRoZSBzdXJ2aXZhbCBvZiB0aGUgcGFzc2VuZ2VycyBiYXNlZCBvbiB2YXJpb3VzIGZlYXR1cmVzLiBCZWxvdyBhcmUgdGhlIHZhcmlhYmxlcyB5b3Ugd2lsbCB1c2UgaW4gdGhpcyBkYXRhc2V0Og0KDQoqKlN1cnZpdmVkKio6IEluZGljYXRlcyBpZiB0aGUgcGFzc2VuZ2VyIFN1cnZpdmVkICgxKSBvciBkaWQgbm90IHN1cnZpdmUgKDApLg0KDQoqKkNsYXNzKio6IFBhc3NlbmdlciBjbGFzcywgYSBwcm94eSBmb3Igc29jaW8tZWNvbm9taWMgc3RhdHVzICgxID0gMXN0IGNsYXNzLCAyID0gMm5kIGNsYXNzLCAzID0gM3JkIGNsYXNzKS4NCg0KKipOYW1lKio6IEZ1bGwgbmFtZSBvZiB0aGUgcGFzc2VuZ2VyLg0KDQoqKlNleCoqOiBHZW5kZXIgb2YgdGhlIHBhc3NlbmdlciAobWFsZSBvciBmZW1hbGUpLg0KDQoqKkFnZSoqOiBBZ2Ugb2YgdGhlIHBhc3NlbmdlciBpbiB5ZWFycy4gU29tZSBlbnRyaWVzIG1heSBoYXZlIG1pc3NpbmcgYWdlcy4NCg0KKipTaWJTcCoqOiBOdW1iZXIgb2Ygc2libGluZ3MgYW5kIHNwb3VzZXMgYWJvYXJkIHRoZSBUaXRhbmljLg0KDQoqKlBhcmNoKio6IE51bWJlciBvZiBwYXJlbnRzIGFuZCBjaGlsZHJlbiBhYm9hcmQgdGhlIFRpdGFuaWMuDQoNCioqRmFyZSoqOiBQYXNzZW5nZXIgZmFyZS4NCg0KDQpgYGB7ciBRMn0NCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzDQpsaWJyYXJ5KHJwYXJ0KQ0KbGlicmFyeShnbW9kZWxzKQ0KDQojIExvYWQgdGhlIGRhdGFzZXQ7IGFzc3VtaW5nIHRoZSBUaXRhbmljIGRhdGFzZXQNClRpdGFuaWMgPC0gcmVhZC5jc3YoIlRpdGFuaWMuY3N2IikNCg0KIyBTZWxlY3QgcmVsZXZhbnQgY29sdW1ucw0KVGl0YW5pYyA8LSBUaXRhbmljWyxjKCJTdXJ2aXZlZCIsICJTZXgiLCAiQ2xhc3MiLCAiQWdlIiwgIkZhcmUiKV0NCg0KIyBGYWN0b3JpemUgdGhlIFN1cnZpdmVkIGNvbHVtbg0KVGl0YW5pYyRTdXJ2aXZlZCA8LSBhcy5mYWN0b3IoVGl0YW5pYyRTdXJ2aXZlZCkNCg0KIyBTZXQgc2VlZCBhbmQgc3BsaXQgdGhlIGRhdGENCnNldC5zZWVkKDc3NykNCnRyYWluX2luZGljZXMgPC0gc2FtcGxlKDE6bnJvdyhUaXRhbmljKSwgMC43NSAqIG5yb3coVGl0YW5pYykpDQpEYXRhVHJhaW4gPC0gVGl0YW5pY1t0cmFpbl9pbmRpY2VzLCBdDQpEYXRhVGVzdCA8LSBUaXRhbmljWy10cmFpbl9pbmRpY2VzLCBdDQoNCiMgVHJhaW4gdGhlIGRlY2lzaW9uIHRyZWUgbW9kZWwNCk1vZGVsRGVzaWduRGVjVHJlZSA8LSBycGFydChTdXJ2aXZlZCB+IC4sIGRhdGEgPSBEYXRhVHJhaW4sIG1ldGhvZCA9ICJjbGFzcyIsIGNvbnRyb2wgPSBycGFydC5jb250cm9sKG1heGRlcHRoID0gMykpDQoNCiMgVmlzdWFsaXplIHRoZSBkZWNpc2lvbiB0cmVlDQpsaWJyYXJ5KHJwYXJ0LnBsb3QpDQpycGFydC5wbG90KE1vZGVsRGVzaWduRGVjVHJlZSwgeWVzLnRleHQgPSAiWUVTIiwgbm8udGV4dCA9ICJOTyIsIHJvdW5kaW50ID0gRkFMU0UpDQoNCiMgUHJlZGljdCBvbiB0aGUgdGVzdCBzZXQNCnByZWRpY3RlZF9sYWJlbHMgPC0gcHJlZGljdChNb2RlbERlc2lnbkRlY1RyZWUsIERhdGFUZXN0LCB0eXBlID0gImNsYXNzIikNCg0KIyBDcmVhdGUgY29uZnVzaW9uIG1hdHJpeCB1c2luZyBDcm9zc1RhYmxlDQpDcm9zc1RhYmxlKHggPSBEYXRhVGVzdCRTdXJ2aXZlZCwgeSA9IHByZWRpY3RlZF9sYWJlbHMsIHByb3AuY2hpc3EgPSBGQUxTRSkNCg0KIyBDYWxjdWxhdGUgYWNjdXJhY3kNCmFjY3VyYWN5IDwtIG1lYW4ocHJlZGljdGVkX2xhYmVscyA9PSBEYXRhVGVzdCRTdXJ2aXZlZCkNCnByaW50KHBhc3RlKCJBY2N1cmFjeToiLCByb3VuZChhY2N1cmFjeSAqIDEwMCwgMiksICIlIikpDQpgYGANCg0KKipXSVRIIEEgODUlIEFDQ1VSQUNZIFRIRSBUUkVFIFBSRURJQ1RTKioNCg0KMS4gV2hhdCBpcyB0aGUgc3Vydml2YWwgcmF0ZSBmb3IgYWR1bHQgbWFsZSBwYXNzZW5nZXJzIDEzIHllYXJzIG9yIG9sZGVyLCByZWdhcmRsZXNzIG9mIHRoZSBjbGFzcyB0aGV5IHRyYXZlbGVkIGluIGFuZCB0aGUgZmFyZSB0aGV5IHBhaWQ/DQoNCkFuc3dlcjogKio5JSB3aXRoIDQ2JSBEYXRhKioNCg0KMi4gV2hhdCBpcyB0aGUgc3Vydml2YWwgcmF0ZSBmb3IgeW91bmcgbWFsZSBwYXNzZW5nZXJzICh5b3VuZ2VyIHRoYW4gMTMgeWVhcnMpLCByZWdhcmRsZXNzIG9mIHdoaWNoIGNsYXNzIHRoZXkgdHJhdmVsZWQgYW5kIHRoZSBmYXJlIHRoZXkgcGFpZD8NCg0KQW5zd2VyOiAqKjE5JSB3aXRoIDY2JSBEYXRhKioNCg0KMy4gV2hhdCBpcyB0aGUgc3Vydml2YWwgcmF0ZSBmb3IgeW91bmcgbWFsZSBwYXNzZW5nZXJzICh5b3VuZ2VyIHRoYW4gMTMgeWVhcnMpIHRyYXZlbGluZyBpbiBUaGlyZCBDbGFzcyByZWdhcmRsZXNzIG9mIHRoZSBmYXJlIHRoZXkgcGFpZD8NCg0KQW5zd2VyOiAqKjc5JSoqDQoNCjQuIFdoYXQgaXMgdGhlIHN1cnZpdmFsIHJhdGUgZm9yIGZlbWFsZSBwYXNzZW5nZXJzLCByZWdhcmRsZXNzIG9mIGFnZSBhbmQgbm90IGNvbnNpZGVyaW5nIHRoZSBjbGFzcyB0aGV5IHRyYXZlbGVkIGluIG9yIHRoZSBmYXJlIHRoZXkgcGFpZD8NCg0KQW5zd2VyOiAqKjcyJSB3aXRoIDM0JSBEYXRhKioNCg0KNS4gV2hlbiBjb25zaWRlcmluZyB0aGUgY2xhc3MgZmVtYWxlIHBhc3NlbmdlcnMgdHJhdmVsZWQgaW4sIHdlIGNhbiBzZWUgZmVtYWxlIHBhc3NlbmdlcnMsIHJlZ2FyZGxlc3Mgb2YgYWdlLCBoYWQgYSBzdXJ2aXZhbCByYXRlIG9mICoqOTMlKiogd2hlbiB0aGV5IHRyYXZlbGVkIGluIEZpcnN0IG9yIFNlY29uZCBDbGFzcyByZWdhcmRsZXNzIG9mIHRoZSBmYXJlIHRoZXkgcGFpZC4NCg0KDQoNCg0K