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

  1. 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!".
  2. 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.
  3. 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.
  4. 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

  1. Assigning Values:
    • Create three variables: a, b, and c. Assign them the values 5, 10, and 15, respectively.
  2. Swapping Values:
    • Write code to swap the values of a and c.
  3. Printing Variables:
    • Print the new values of a, b, and c.

Exercise 5: Vector Operations

  1. Creating Vectors:
    • Create a vector v1 containing the numbers 1 through 10.
  2. Concatenating Vectors:
    • Create a vector v2 containing the numbers 11 through 20. Write code to concatenate v1 and v2 into a new vector v3.
  3. Statistical Analysis:
    • Calculate the sum, mean, and standard deviation of v3.

Exercise 6: Matrix Operations

  1. Creating Matrices:
    • Create a 3x3 matrix m1 with random integer values between 1 and 50.
  2. 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.
  3. Determinant Calculation:
    • Calculate the determinant of m3.

Exercise 7: Data Frame Manipulation

  1. Loading Data:
    • Download the "mtcars" dataset and store it in a variable called df.
  2. Filtering Data:
    • Write code to select all rows where the car has more than 100 horsepower.
  3. Creating Subsets:
    • Create a new data frame df_subset that contains only the mpg, cyl, and hp columns.
  4. Sorting Data:
    • Sort df_subset in descending order by hp.

Exercise 8: Data Visualization

  1. 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.
  2. Adding a Trend Line:
    • Add a trend line to the scatterplot using a linear regression model.
  3. 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.

  1. 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.
  2. 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.
  3. 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==