Introduction
Overview
This homework is designed to evaluate your understanding of R
programming, focusing on your ability to write functions, manipulate
data, and apply various programming concepts. The exercises are
structured to present different levels of difficulty, beginning with
basic tasks and progressing to more complex challenges. This progression
will allow you to apply foundational skills while also pushing you to
tackle more advanced problems.
Expectations
Clarity and Correctness
- Each function should be clearly named and precisely perform the task
described in the exercise.
- Ensure that your code is correct by producing the expected output
for a variety of test cases, including edge cases.
Code Efficiency
- While correctness is crucial, you should also consider the
efficiency of your code.
- Avoid unnecessary computations or memory usage where possible.
Documentation and Readability
- Include comments in your code to explain what each part of your
function does, especially for more complex functions.
- Use meaningful variable names that make it clear what each variable
represents, enhancing the readability of your code.
Handling Edge Cases
- For exercises involving numeric inputs, consider how your function
should behave with different types of numbers (e.g., zero, negative
numbers, non-integers).
- For data-related exercises, ensure that your function can handle
scenarios like empty data frames or missing values gracefully.
Testing
- Test your functions with a variety of inputs to ensure they work as
expected. Include some of these tests in your submission to demonstrate
that your code has been thoroughly checked.
- Where applicable, provide an explanation of how you tested the
function and why you believe it is correct.
Use of Built-in Functions
- You are encouraged to use R’s built-in functions and packages where
appropriate, but ensure you understand how they work and can explain
their usage if needed.
Submission Guidelines
- Submit your code in a single R script file (.R).
- Ensure that your code runs without errors. If there are any known
issues, document them in comments within your script.
- If you collaborated with others or consulted external resources,
please acknowledge them in comments.
- Include a brief write-up (as comments at the top of your script)
summarizing how you approached the homework and any challenges you
encountered.
Exercises
Exercise 1: Simple Functions
- Greeting Function:
- Create a function called
greet
that takes a character
string name
as input and returns a greeting message in the
format "Hello, <name>!"
. For example,
greet("Alice")
should return
"Hello, Alice!"
.
- Basic Arithmetic Operations:
- Write a function
basic_ops(a, b)
that takes two numbers
a
and b
as input and returns their sum,
difference, product, and quotient in a named list.
- Summing Even Numbers:
- Create a function
even_sum(n)
that takes a positive
integer n
and returns the sum of all even numbers from 1 to
n
.
- Prime Number Checker:
- Write a function
is_prime(n)
that takes an integer
n
as input and returns TRUE
if n
is a prime number, and FALSE
otherwise.
Exercise 2: Conditional Statements
- Age Classification:
- Write a function
classify_age
that takes an integer
age
as input and returns a character string indicating
whether the person is "young"
(under 18),
"adult"
(18-64), or "senior"
(65 or
older).
Exercise 3: String Manipulation
- Extracting Initials:
- Write a function
extract_initials
that takes a
character string full_name
as input and returns the
initials of the name (e.g., "John Smith"
->
"JS"
).
Exercise 4: Simple Variable Manipulation
- Assigning Values:
- Create three variables:
a
, b
, and
c
. Assign them the values 5, 10, and 15, respectively.
- Swapping Values:
- Write code to swap the values of
a
and
c
.
- Printing Variables:
- Print the new values of
a
, b
, and
c
.
Exercise 5: Vector Operations
- Creating Vectors:
- Create a vector
v1
containing the numbers 1 through
10.
- Concatenating Vectors:
- Create a vector
v2
containing the numbers 11 through
20. Write code to concatenate v1
and v2
into a
new vector v3
.
- Statistical Analysis:
- Calculate the sum, mean, and standard deviation of
v3
.
Exercise 6: Matrix Operations
- Creating Matrices:
- Create a 3x3 matrix
m1
with random integer values
between 1 and 50.
- Matrix Addition:
- Create a 3x3 matrix
m2
with random integer values
between 1 and 50. Write code to add m1
and m2
and store the result in m3
.
- Determinant Calculation:
- Calculate the determinant of
m3
.
Exercise 7: Data Frame Manipulation
- Loading Data:
- Download the
"mtcars"
dataset and store it in a
variable called df
.
- Filtering Data:
- Write code to select all rows where the car has more than 100
horsepower.
- Creating Subsets:
- Create a new data frame
df_subset
that contains only
the mpg
, cyl
, and hp
columns.
- Sorting Data:
- Sort
df_subset
in descending order by
hp
.
Exercise 8: Data Visualization
- Creating a Scatterplot:
- Use the
ggplot2
library to create a scatterplot of the
mtcars
dataset, plotting mpg
on the y-axis and
hp
on the x-axis.
- Adding a Trend Line:
- Add a trend line to the scatterplot using a linear regression
model.
- Customizing the Plot:
- Customize the plot by adding a title, axis labels, and applying a
theme.
Exercise 9: Estimating π with the Monte Carlo Method
Objective
In this exercise, you will write a function that estimates the value
of π using a Monte Carlo simulation. The Monte Carlo method relies on
random sampling to obtain numerical results, making it a powerful tool
for estimating values that are difficult to calculate directly.
Problem Statement
- Function Name:
monte_carlo_pi
- Input: A single integer
iterations
,
representing the number of random points to generate.
- Output: A numeric value representing the estimated
value of π.
Methodology
The Monte Carlo method can be used to estimate π by simulating random
points within a unit square and determining the proportion that fall
within a quarter circle inscribed within the square.
- Generate Random Points:
- The unit square is defined with both x and y coordinates ranging
from 0 to 1.
- For each iteration, generate a random point
(x, y)
where both x and y are uniformly distributed between 0 and 1.
- Determine if the Point is Inside the Quarter
Circle:
- A point
(x, y)
lies inside the quarter circle if it
satisfies the equation \(x^2 + y^2 \leq
1\).
- Count how many points fall inside the quarter circle.
- Estimate π:
- The ratio of points inside the quarter circle to the total number of
points, multiplied by 4, gives an estimate of π: \[
\text{Estimated } \pi = \frac{\text{Number of points inside the
circle}}{\text{Total number of points}} \times 4
\]
Implementation
monte_carlo_pi <- function(iterations) {
...
return(estimated_pi)
}
Testing Your Function
To verify that your function works correctly, test it with a range of
values for iterations:
set.seed(123)
print(monte_carlo_pi(100)) # Small number of iterations
print(monte_carlo_pi(10000)) # Larger number of iterations
print(monte_carlo_pi(1000000)) # Even larger number of iterations
Expected Outcomes
- Understanding Random Sampling: This exercise will
help you grasp how random sampling can be used to estimate complex
values.
- Algorithm Design: You’ll practice designing an
algorithm that repeatedly tests a condition and accumulates
results.
- Numerical Estimation: You’ll gain insight into how
large-scale simulations can approximate mathematical constants.
LS0tCnRpdGxlOiAiSG9tZXdvcmsgMSIKYXV0aG9yOiAiRHIuIE5heWVsIEJldHRhY2hlIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIEludHJvZHVjdGlvbgoKIyMjIE92ZXJ2aWV3CgpUaGlzIGhvbWV3b3JrIGlzIGRlc2lnbmVkIHRvIGV2YWx1YXRlIHlvdXIgdW5kZXJzdGFuZGluZyBvZiBSIHByb2dyYW1taW5nLCBmb2N1c2luZyBvbiB5b3VyIGFiaWxpdHkgdG8gd3JpdGUgZnVuY3Rpb25zLCBtYW5pcHVsYXRlIGRhdGEsIGFuZCBhcHBseSB2YXJpb3VzIHByb2dyYW1taW5nIGNvbmNlcHRzLiBUaGUgZXhlcmNpc2VzIGFyZSBzdHJ1Y3R1cmVkIHRvIHByZXNlbnQgZGlmZmVyZW50IGxldmVscyBvZiBkaWZmaWN1bHR5LCBiZWdpbm5pbmcgd2l0aCBiYXNpYyB0YXNrcyBhbmQgcHJvZ3Jlc3NpbmcgdG8gbW9yZSBjb21wbGV4IGNoYWxsZW5nZXMuIFRoaXMgcHJvZ3Jlc3Npb24gd2lsbCBhbGxvdyB5b3UgdG8gYXBwbHkgZm91bmRhdGlvbmFsIHNraWxscyB3aGlsZSBhbHNvIHB1c2hpbmcgeW91IHRvIHRhY2tsZSBtb3JlIGFkdmFuY2VkIHByb2JsZW1zLgoKIyMjIEV4cGVjdGF0aW9ucwoKIyMjIyBDbGFyaXR5IGFuZCBDb3JyZWN0bmVzcwoKLSBFYWNoIGZ1bmN0aW9uIHNob3VsZCBiZSBjbGVhcmx5IG5hbWVkIGFuZCBwcmVjaXNlbHkgcGVyZm9ybSB0aGUgdGFzayBkZXNjcmliZWQgaW4gdGhlIGV4ZXJjaXNlLgotIEVuc3VyZSB0aGF0IHlvdXIgY29kZSBpcyBjb3JyZWN0IGJ5IHByb2R1Y2luZyB0aGUgZXhwZWN0ZWQgb3V0cHV0IGZvciBhIHZhcmlldHkgb2YgdGVzdCBjYXNlcywgaW5jbHVkaW5nIGVkZ2UgY2FzZXMuCgojIyMjIENvZGUgRWZmaWNpZW5jeQoKLSBXaGlsZSBjb3JyZWN0bmVzcyBpcyBjcnVjaWFsLCB5b3Ugc2hvdWxkIGFsc28gY29uc2lkZXIgdGhlIGVmZmljaWVuY3kgb2YgeW91ciBjb2RlLgotIEF2b2lkIHVubmVjZXNzYXJ5IGNvbXB1dGF0aW9ucyBvciBtZW1vcnkgdXNhZ2Ugd2hlcmUgcG9zc2libGUuCgojIyMjIERvY3VtZW50YXRpb24gYW5kIFJlYWRhYmlsaXR5CgotIEluY2x1ZGUgY29tbWVudHMgaW4geW91ciBjb2RlIHRvIGV4cGxhaW4gd2hhdCBlYWNoIHBhcnQgb2YgeW91ciBmdW5jdGlvbiBkb2VzLCBlc3BlY2lhbGx5IGZvciBtb3JlIGNvbXBsZXggZnVuY3Rpb25zLgotIFVzZSBtZWFuaW5nZnVsIHZhcmlhYmxlIG5hbWVzIHRoYXQgbWFrZSBpdCBjbGVhciB3aGF0IGVhY2ggdmFyaWFibGUgcmVwcmVzZW50cywgZW5oYW5jaW5nIHRoZSByZWFkYWJpbGl0eSBvZiB5b3VyIGNvZGUuCgojIyMjIEhhbmRsaW5nIEVkZ2UgQ2FzZXMKCi0gRm9yIGV4ZXJjaXNlcyBpbnZvbHZpbmcgbnVtZXJpYyBpbnB1dHMsIGNvbnNpZGVyIGhvdyB5b3VyIGZ1bmN0aW9uIHNob3VsZCBiZWhhdmUgd2l0aCBkaWZmZXJlbnQgdHlwZXMgb2YgbnVtYmVycyAoZS5nLiwgemVybywgbmVnYXRpdmUgbnVtYmVycywgbm9uLWludGVnZXJzKS4KLSBGb3IgZGF0YS1yZWxhdGVkIGV4ZXJjaXNlcywgZW5zdXJlIHRoYXQgeW91ciBmdW5jdGlvbiBjYW4gaGFuZGxlIHNjZW5hcmlvcyBsaWtlIGVtcHR5IGRhdGEgZnJhbWVzIG9yIG1pc3NpbmcgdmFsdWVzIGdyYWNlZnVsbHkuCgojIyMjIFRlc3RpbmcKCi0gVGVzdCB5b3VyIGZ1bmN0aW9ucyB3aXRoIGEgdmFyaWV0eSBvZiBpbnB1dHMgdG8gZW5zdXJlIHRoZXkgd29yayBhcyBleHBlY3RlZC4gSW5jbHVkZSBzb21lIG9mIHRoZXNlIHRlc3RzIGluIHlvdXIgc3VibWlzc2lvbiB0byBkZW1vbnN0cmF0ZSB0aGF0IHlvdXIgY29kZSBoYXMgYmVlbiB0aG9yb3VnaGx5IGNoZWNrZWQuCi0gV2hlcmUgYXBwbGljYWJsZSwgcHJvdmlkZSBhbiBleHBsYW5hdGlvbiBvZiBob3cgeW91IHRlc3RlZCB0aGUgZnVuY3Rpb24gYW5kIHdoeSB5b3UgYmVsaWV2ZSBpdCBpcyBjb3JyZWN0LgoKIyMjIyBVc2Ugb2YgQnVpbHQtaW4gRnVuY3Rpb25zCgotIFlvdSBhcmUgZW5jb3VyYWdlZCB0byB1c2UgUuKAmXMgYnVpbHQtaW4gZnVuY3Rpb25zIGFuZCBwYWNrYWdlcyB3aGVyZSBhcHByb3ByaWF0ZSwgYnV0IGVuc3VyZSB5b3UgdW5kZXJzdGFuZCBob3cgdGhleSB3b3JrIGFuZCBjYW4gZXhwbGFpbiB0aGVpciB1c2FnZSBpZiBuZWVkZWQuCgojIyMgU3VibWlzc2lvbiBHdWlkZWxpbmVzCgotIFN1Ym1pdCB5b3VyIGNvZGUgaW4gYSBzaW5nbGUgUiBzY3JpcHQgZmlsZSAoLlIpLgotIEVuc3VyZSB0aGF0IHlvdXIgY29kZSBydW5zIHdpdGhvdXQgZXJyb3JzLiBJZiB0aGVyZSBhcmUgYW55IGtub3duIGlzc3VlcywgZG9jdW1lbnQgdGhlbSBpbiBjb21tZW50cyB3aXRoaW4geW91ciBzY3JpcHQuCi0gSWYgeW91IGNvbGxhYm9yYXRlZCB3aXRoIG90aGVycyBvciBjb25zdWx0ZWQgZXh0ZXJuYWwgcmVzb3VyY2VzLCBwbGVhc2UgYWNrbm93bGVkZ2UgdGhlbSBpbiBjb21tZW50cy4KLSBJbmNsdWRlIGEgYnJpZWYgd3JpdGUtdXAgKGFzIGNvbW1lbnRzIGF0IHRoZSB0b3Agb2YgeW91ciBzY3JpcHQpIHN1bW1hcml6aW5nIGhvdyB5b3UgYXBwcm9hY2hlZCB0aGUgaG9tZXdvcmsgYW5kIGFueSBjaGFsbGVuZ2VzIHlvdSBlbmNvdW50ZXJlZC4KCi0tLQoKIyBFeGVyY2lzZXMKCiMjIyBFeGVyY2lzZSAxOiBTaW1wbGUgRnVuY3Rpb25zCgoxLiAqKkdyZWV0aW5nIEZ1bmN0aW9uOioqCiAgIC0gQ3JlYXRlIGEgZnVuY3Rpb24gY2FsbGVkIGBncmVldGAgdGhhdCB0YWtlcyBhIGNoYXJhY3RlciBzdHJpbmcgYG5hbWVgIGFzIGlucHV0IGFuZCByZXR1cm5zIGEgZ3JlZXRpbmcgbWVzc2FnZSBpbiB0aGUgZm9ybWF0IGAiSGVsbG8sIDxuYW1lPiEiYC4gRm9yIGV4YW1wbGUsIGBncmVldCgiQWxpY2UiKWAgc2hvdWxkIHJldHVybiBgIkhlbGxvLCBBbGljZSEiYC4KICAgCjIuICoqQmFzaWMgQXJpdGhtZXRpYyBPcGVyYXRpb25zOioqCiAgIC0gV3JpdGUgYSBmdW5jdGlvbiBgYmFzaWNfb3BzKGEsIGIpYCB0aGF0IHRha2VzIHR3byBudW1iZXJzIGBhYCBhbmQgYGJgIGFzIGlucHV0IGFuZCByZXR1cm5zIHRoZWlyIHN1bSwgZGlmZmVyZW5jZSwgcHJvZHVjdCwgYW5kIHF1b3RpZW50IGluIGEgbmFtZWQgbGlzdC4KICAgCjMuICoqU3VtbWluZyBFdmVuIE51bWJlcnM6KioKICAgLSBDcmVhdGUgYSBmdW5jdGlvbiBgZXZlbl9zdW0obilgIHRoYXQgdGFrZXMgYSBwb3NpdGl2ZSBpbnRlZ2VyIGBuYCBhbmQgcmV0dXJucyB0aGUgc3VtIG9mIGFsbCBldmVuIG51bWJlcnMgZnJvbSAxIHRvIGBuYC4KICAgCjQuICoqUHJpbWUgTnVtYmVyIENoZWNrZXI6KioKICAgLSBXcml0ZSBhIGZ1bmN0aW9uIGBpc19wcmltZShuKWAgdGhhdCB0YWtlcyBhbiBpbnRlZ2VyIGBuYCBhcyBpbnB1dCBhbmQgcmV0dXJucyBgVFJVRWAgaWYgYG5gIGlzIGEgcHJpbWUgbnVtYmVyLCBhbmQgYEZBTFNFYCBvdGhlcndpc2UuCgojIyMgRXhlcmNpc2UgMjogQ29uZGl0aW9uYWwgU3RhdGVtZW50cwoKLSAqKkFnZSBDbGFzc2lmaWNhdGlvbjoqKgogIC0gV3JpdGUgYSBmdW5jdGlvbiBgY2xhc3NpZnlfYWdlYCB0aGF0IHRha2VzIGFuIGludGVnZXIgYGFnZWAgYXMgaW5wdXQgYW5kIHJldHVybnMgYSBjaGFyYWN0ZXIgc3RyaW5nIGluZGljYXRpbmcgd2hldGhlciB0aGUgcGVyc29uIGlzIGAieW91bmciYCAodW5kZXIgMTgpLCBgImFkdWx0ImAgKDE4LTY0KSwgb3IgYCJzZW5pb3IiYCAoNjUgb3Igb2xkZXIpLgoKIyMjIEV4ZXJjaXNlIDM6IFN0cmluZyBNYW5pcHVsYXRpb24KCi0gKipFeHRyYWN0aW5nIEluaXRpYWxzOioqCiAgLSBXcml0ZSBhIGZ1bmN0aW9uIGBleHRyYWN0X2luaXRpYWxzYCB0aGF0IHRha2VzIGEgY2hhcmFjdGVyIHN0cmluZyBgZnVsbF9uYW1lYCBhcyBpbnB1dCBhbmQgcmV0dXJucyB0aGUgaW5pdGlhbHMgb2YgdGhlIG5hbWUgKGUuZy4sIGAiSm9obiBTbWl0aCJgIC0+IGAiSlMiYCkuCgojIyMgRXhlcmNpc2UgNDogU2ltcGxlIFZhcmlhYmxlIE1hbmlwdWxhdGlvbgoKMS4gKipBc3NpZ25pbmcgVmFsdWVzOioqCiAgIC0gQ3JlYXRlIHRocmVlIHZhcmlhYmxlczogYGFgLCBgYmAsIGFuZCBgY2AuIEFzc2lnbiB0aGVtIHRoZSB2YWx1ZXMgNSwgMTAsIGFuZCAxNSwgcmVzcGVjdGl2ZWx5LgogICAKMi4gKipTd2FwcGluZyBWYWx1ZXM6KioKICAgLSBXcml0ZSBjb2RlIHRvIHN3YXAgdGhlIHZhbHVlcyBvZiBgYWAgYW5kIGBjYC4KICAgCjMuICoqUHJpbnRpbmcgVmFyaWFibGVzOioqCiAgIC0gUHJpbnQgdGhlIG5ldyB2YWx1ZXMgb2YgYGFgLCBgYmAsIGFuZCBgY2AuCgojIyMgRXhlcmNpc2UgNTogVmVjdG9yIE9wZXJhdGlvbnMKCjEuICoqQ3JlYXRpbmcgVmVjdG9yczoqKgogICAtIENyZWF0ZSBhIHZlY3RvciBgdjFgIGNvbnRhaW5pbmcgdGhlIG51bWJlcnMgMSB0aHJvdWdoIDEwLgogICAKMi4gKipDb25jYXRlbmF0aW5nIFZlY3RvcnM6KioKICAgLSBDcmVhdGUgYSB2ZWN0b3IgYHYyYCBjb250YWluaW5nIHRoZSBudW1iZXJzIDExIHRocm91Z2ggMjAuIFdyaXRlIGNvZGUgdG8gY29uY2F0ZW5hdGUgYHYxYCBhbmQgYHYyYCBpbnRvIGEgbmV3IHZlY3RvciBgdjNgLgogICAKMy4gKipTdGF0aXN0aWNhbCBBbmFseXNpczoqKgogICAtIENhbGN1bGF0ZSB0aGUgc3VtLCBtZWFuLCBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGB2M2AuCgojIyMgRXhlcmNpc2UgNjogTWF0cml4IE9wZXJhdGlvbnMKCjEuICoqQ3JlYXRpbmcgTWF0cmljZXM6KioKICAgLSBDcmVhdGUgYSAzeDMgbWF0cml4IGBtMWAgd2l0aCByYW5kb20gaW50ZWdlciB2YWx1ZXMgYmV0d2VlbiAxIGFuZCA1MC4KICAgCjIuICoqTWF0cml4IEFkZGl0aW9uOioqCiAgIC0gQ3JlYXRlIGEgM3gzIG1hdHJpeCBgbTJgIHdpdGggcmFuZG9tIGludGVnZXIgdmFsdWVzIGJldHdlZW4gMSBhbmQgNTAuIFdyaXRlIGNvZGUgdG8gYWRkIGBtMWAgYW5kIGBtMmAgYW5kIHN0b3JlIHRoZSByZXN1bHQgaW4gYG0zYC4KICAgCjMuICoqRGV0ZXJtaW5hbnQgQ2FsY3VsYXRpb246KioKICAgLSBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50IG9mIGBtM2AuCgojIyMgRXhlcmNpc2UgNzogRGF0YSBGcmFtZSBNYW5pcHVsYXRpb24KCjEuICoqTG9hZGluZyBEYXRhOioqCiAgIC0gRG93bmxvYWQgdGhlIGAibXRjYXJzImAgZGF0YXNldCBhbmQgc3RvcmUgaXQgaW4gYSB2YXJpYWJsZSBjYWxsZWQgYGRmYC4KICAgCjIuICoqRmlsdGVyaW5nIERhdGE6KioKICAgLSBXcml0ZSBjb2RlIHRvIHNlbGVjdCBhbGwgcm93cyB3aGVyZSB0aGUgY2FyIGhhcyBtb3JlIHRoYW4gMTAwIGhvcnNlcG93ZXIuCiAgIAozLiAqKkNyZWF0aW5nIFN1YnNldHM6KioKICAgLSBDcmVhdGUgYSBuZXcgZGF0YSBmcmFtZSBgZGZfc3Vic2V0YCB0aGF0IGNvbnRhaW5zIG9ubHkgdGhlIGBtcGdgLCBgY3lsYCwgYW5kIGBocGAgY29sdW1ucy4KICAgCjQuICoqU29ydGluZyBEYXRhOioqCiAgIC0gU29ydCBgZGZfc3Vic2V0YCBpbiBkZXNjZW5kaW5nIG9yZGVyIGJ5IGBocGAuCgojIyMgRXhlcmNpc2UgODogRGF0YSBWaXN1YWxpemF0aW9uCgoxLiAqKkNyZWF0aW5nIGEgU2NhdHRlcnBsb3Q6KioKICAgLSBVc2UgdGhlIGBnZ3Bsb3QyYCBsaWJyYXJ5IHRvIGNyZWF0ZSBhIHNjYXR0ZXJwbG90IG9mIHRoZSBgbXRjYXJzYCBkYXRhc2V0LCBwbG90dGluZyBgbXBnYCBvbiB0aGUgeS1heGlzIGFuZCBgaHBgIG9uIHRoZSB4LWF4aXMuCiAgIAoyLiAqKkFkZGluZyBhIFRyZW5kIExpbmU6KioKICAgLSBBZGQgYSB0cmVuZCBsaW5lIHRvIHRoZSBzY2F0dGVycGxvdCB1c2luZyBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLgogICAKMy4gKipDdXN0b21pemluZyB0aGUgUGxvdDoqKgogICAtIEN1c3RvbWl6ZSB0aGUgcGxvdCBieSBhZGRpbmcgYSB0aXRsZSwgYXhpcyBsYWJlbHMsIGFuZCBhcHBseWluZyBhIHRoZW1lLgogICAKIyMjIEV4ZXJjaXNlIDk6IEVzdGltYXRpbmcgz4Agd2l0aCB0aGUgTW9udGUgQ2FybG8gTWV0aG9kCgojIyMjIyBPYmplY3RpdmUKCkluIHRoaXMgZXhlcmNpc2UsIHlvdSB3aWxsIHdyaXRlIGEgZnVuY3Rpb24gdGhhdCBlc3RpbWF0ZXMgdGhlIHZhbHVlIG9mIM+AIHVzaW5nIGEgTW9udGUgQ2FybG8gc2ltdWxhdGlvbi4gVGhlIE1vbnRlIENhcmxvIG1ldGhvZCByZWxpZXMgb24gcmFuZG9tIHNhbXBsaW5nIHRvIG9idGFpbiBudW1lcmljYWwgcmVzdWx0cywgbWFraW5nIGl0IGEgcG93ZXJmdWwgdG9vbCBmb3IgZXN0aW1hdGluZyB2YWx1ZXMgdGhhdCBhcmUgZGlmZmljdWx0IHRvIGNhbGN1bGF0ZSBkaXJlY3RseS4KCiMjIyMjIFByb2JsZW0gU3RhdGVtZW50CgotICoqRnVuY3Rpb24gTmFtZToqKiBgbW9udGVfY2FybG9fcGlgCi0gKipJbnB1dDoqKiBBIHNpbmdsZSBpbnRlZ2VyIGBpdGVyYXRpb25zYCwgcmVwcmVzZW50aW5nIHRoZSBudW1iZXIgb2YgcmFuZG9tIHBvaW50cyB0byBnZW5lcmF0ZS4KLSAqKk91dHB1dDoqKiBBIG51bWVyaWMgdmFsdWUgcmVwcmVzZW50aW5nIHRoZSBlc3RpbWF0ZWQgdmFsdWUgb2Ygz4AuCgojIyMjIyBNZXRob2RvbG9neQoKVGhlIE1vbnRlIENhcmxvIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBlc3RpbWF0ZSDPgCBieSBzaW11bGF0aW5nIHJhbmRvbSBwb2ludHMgd2l0aGluIGEgdW5pdCBzcXVhcmUgYW5kIGRldGVybWluaW5nIHRoZSBwcm9wb3J0aW9uIHRoYXQgZmFsbCB3aXRoaW4gYSBxdWFydGVyIGNpcmNsZSBpbnNjcmliZWQgd2l0aGluIHRoZSBzcXVhcmUuCgoxLiAqKkdlbmVyYXRlIFJhbmRvbSBQb2ludHM6KioKICAgLSBUaGUgdW5pdCBzcXVhcmUgaXMgZGVmaW5lZCB3aXRoIGJvdGggeCBhbmQgeSBjb29yZGluYXRlcyByYW5naW5nIGZyb20gMCB0byAxLgogICAtIEZvciBlYWNoIGl0ZXJhdGlvbiwgZ2VuZXJhdGUgYSByYW5kb20gcG9pbnQgYCh4LCB5KWAgd2hlcmUgYm90aCB4IGFuZCB5IGFyZSB1bmlmb3JtbHkgZGlzdHJpYnV0ZWQgYmV0d2VlbiAwIGFuZCAxLgoKMi4gKipEZXRlcm1pbmUgaWYgdGhlIFBvaW50IGlzIEluc2lkZSB0aGUgUXVhcnRlciBDaXJjbGU6KioKICAgLSBBIHBvaW50IGAoeCwgeSlgIGxpZXMgaW5zaWRlIHRoZSBxdWFydGVyIGNpcmNsZSBpZiBpdCBzYXRpc2ZpZXMgdGhlIGVxdWF0aW9uIFwoeF4yICsgeV4yIFxsZXEgMVwpLgogICAtIENvdW50IGhvdyBtYW55IHBvaW50cyBmYWxsIGluc2lkZSB0aGUgcXVhcnRlciBjaXJjbGUuCgozLiAqKkVzdGltYXRlIM+AOioqCiAgIC0gVGhlIHJhdGlvIG9mIHBvaW50cyBpbnNpZGUgdGhlIHF1YXJ0ZXIgY2lyY2xlIHRvIHRoZSB0b3RhbCBudW1iZXIgb2YgcG9pbnRzLCBtdWx0aXBsaWVkIGJ5IDQsIGdpdmVzIGFuIGVzdGltYXRlIG9mIM+AOgogICAgIFxbCiAgICAgXHRleHR7RXN0aW1hdGVkIH0gXHBpID0gXGZyYWN7XHRleHR7TnVtYmVyIG9mIHBvaW50cyBpbnNpZGUgdGhlIGNpcmNsZX19e1x0ZXh0e1RvdGFsIG51bWJlciBvZiBwb2ludHN9fSBcdGltZXMgNAogICAgIFxdCgojIyMjIyBJbXBsZW1lbnRhdGlvbgoKYGBgcgptb250ZV9jYXJsb19waSA8LSBmdW5jdGlvbihpdGVyYXRpb25zKSB7CiAgICAuLi4KICAgIHJldHVybihlc3RpbWF0ZWRfcGkpCn0KYGBgCgojIyMjIyBUZXN0aW5nIFlvdXIgRnVuY3Rpb24KClRvIHZlcmlmeSB0aGF0IHlvdXIgZnVuY3Rpb24gd29ya3MgY29ycmVjdGx5LCB0ZXN0IGl0IHdpdGggYSByYW5nZSBvZiB2YWx1ZXMgZm9yIGl0ZXJhdGlvbnM6CgpgYGB7cn0Kc2V0LnNlZWQoMTIzKQpwcmludChtb250ZV9jYXJsb19waSgxMDApKSAgICAgICMgU21hbGwgbnVtYmVyIG9mIGl0ZXJhdGlvbnMKcHJpbnQobW9udGVfY2FybG9fcGkoMTAwMDApKSAgICAjIExhcmdlciBudW1iZXIgb2YgaXRlcmF0aW9ucwpwcmludChtb250ZV9jYXJsb19waSgxMDAwMDAwKSkgICMgRXZlbiBsYXJnZXIgbnVtYmVyIG9mIGl0ZXJhdGlvbnMKCmBgYAoKIyMjIyMgRXhwZWN0ZWQgT3V0Y29tZXMKLSAqKlVuZGVyc3RhbmRpbmcgUmFuZG9tIFNhbXBsaW5nKio6IFRoaXMgZXhlcmNpc2Ugd2lsbCBoZWxwIHlvdSBncmFzcCBob3cgcmFuZG9tIHNhbXBsaW5nIGNhbiBiZSB1c2VkIHRvIGVzdGltYXRlIGNvbXBsZXggdmFsdWVzLgotICoqQWxnb3JpdGhtIERlc2lnbioqOiBZb3XigJlsbCBwcmFjdGljZSBkZXNpZ25pbmcgYW4gYWxnb3JpdGhtIHRoYXQgcmVwZWF0ZWRseSB0ZXN0cyBhIGNvbmRpdGlvbiBhbmQgYWNjdW11bGF0ZXMgcmVzdWx0cy4KLSAqKk51bWVyaWNhbCBFc3RpbWF0aW9uKio6IFlvdeKAmWxsIGdhaW4gaW5zaWdodCBpbnRvIGhvdyBsYXJnZS1zY2FsZSBzaW11bGF0aW9ucyBjYW4gYXBwcm94aW1hdGUgbWF0aGVtYXRpY2FsIGNvbnN0YW50cy4KCg==