Introduction

Functions are an important programming construct. They help in structuring large programs and minimize duplication of code. Additionally, they make code easier to read and debug. R, just like all other modern programming language supports functions.

A quick note on terminology: a function returns a value while a procedure does not. R, like many other languages, does not support procedures in a direct way, although one can define a function that does not return a value which would then be a procedure. This is similar to functions returning void in C/C++ and Java.

R is a procedural language similar to C. It is not object-oriented and does not support objects, classes, inheritance, or polymorphism. It has little support for data encapsulation or abstraction, so no equivalent for class or struct in C/C++ or Java.

All functions are free methods and are not bound to an object or a class like in Java or C++. It’s the same way as in Python or C.

All functions in R can return a value, although they do not have to. So, R does not distinguish between functions and procedures and there is no void return type as in C, C++, and Java.

Programs is R are scripts. There is no “main function” or similar. R programs execute with the first statement at the beginning of the program script, so functions must be defined before they can be called. Functions can be placed into packages for reuse and inclusion by other programs, but that is beyond the scope of this lesson.

Defining a Function

The generic template for defining a function is:

function_name <- function(arg_1, arg_2, ...) {
   Function body 
}

Simple Program with Function

The program below is complete and defines a function that is then called. The function must be defined before it can be called.

# Full R Program 

addNums <- function(n1, n2) 
{
  if (is.numeric(n1) && is.numeric(n2))
  {
    r <- n1 + n2
  
    return(r)
  } else {
    n1 <- as.numeric(n1)
    n2 <- as.numeric(n2)
    
    if (is.na(n1) || is.na(n2)) {
      return(NA)
    } else {
      return(addNums(n1,n2))
    }
  }
}

a <- 10
b <- 20

c <- addNums(a,b)
print(c)
## [1] 30
d <- addNums(a,50)
print(d)
## [1] 60
e <- addNums(a*10,b*45)
print(e)
## [1] 1000
f <- addNums('1', "20.3")
print(f)
## [1] 21.3
# Full R Program 

addVecNums <- function(v) 
{
  if (!is.vector(v) || length(v) < 1)
    return(NA)
  
  s <- 0
  for (i in 1:length(v))
  {
    n <- as.numeric(v[i])
    if (!is.na(n))
      s <- s + n
  }
  
  return(s)
}


vec.nums <- c(23,55,34,87,65,'x',11,98)

e <- addVecNums(vec.nums)
## Warning in addVecNums(vec.nums): NAs introduced by coercion
print(e)
## [1] 373

Example Function

The example below defines a function called findSmallest() which takes a vector of positive integers as an argument and returns the smallest element in the vector. While it can be solved in several ways, we will show a design that uses loops and should be familiar to programmers of most other languages.

Note that we are using the predefined value Inf with is the largest representable integer. There is also -Inf that is the smallest representable integer.

findSmallest = function(v)
{
  s = Inf
  for (i in 1:length(v))
  {
    if (v[i] < s) {
      s = v[i]
    }
  }
  return (s)
}

While you can use = to define a function, you should really get used to using the more common <- syntax. So, let’s try again:

findSmallest <- function(v)
{
  s = Inf
  for (i in 1:length(v))
  {
    if (v[i] < s) {
      s = v[i]
    }
  }
  return (s)
}

Just to be clear, in practice you would use the min() function to find the smallest element rather writing it yourself.

While there are several ways to return a value from a function, the way that is most congruent with other languages is the use of the return statement.

Note that the type of return value and the type of arguments are not declared. R uses a lazy evaluation mechanism and no type checking is performed until run-time.

Calling a Function

To call a function, you would invoke it with its name and its required arguments.

x = c(3,1,9,7,3,6)

w = findSmallest(x)
print(w)
## [1] 1

Function Parameters

If a function takes several arguments you generally pass them in the order declared; the approach that is used by all other languages. However, in R you can pass the arguments in any order as long as you specify the name of the argument.

Argument matching is a bit different in R compared to other languages. Firstly, R does all argument checking at run-time. Secondly, while arguments can be matched positionally like in other languages, arguments can also be matched by parameter name – a syntax not supported by most other languages.

For example, the built-in function seq generates a sequence of numbers and returns those numbers in a vector. The definition of the function is as follows: seq(to, from, by, length.out, along.with).

Here are examples of using it. Note that by, length.out, and along.with have default values and are therefore optional.

v = seq(1, 10, 2)    # integers from 1 to 10 in increments of 2
w = seq(1, 5)        # integers from 1 to 5 (by default in increments of 1)

# pass arguments in a different order but specify by name
w = seq(from = 5, by = -0.5, to = 1)

R also supports variable numbers of arguments but that is beyond the scope of this tutorial.

Default Arguments

R functions can have default values for arguments which are then optional when the function is called. When the argument is missing, then the default value is passed. In the example below, the start argument is the position at which the search for the smallest element will start.

findSmallest <- function(v, start = 1)
{
  s = Inf
  for (i in start:length(v))
  {
    if (v[i] < s) {
      s = v[i]
    }
  }
  return (s)
}
x = c(3,1,9,7,3,6)

w = findSmallest(x, 3)
print(w)
## [1] 3
w = findSmallest(x)
print(w)
## [1] 1

Local Variables

As in most other programming languages, R functions can define local variables that are not known outside the scope of the function. The scope boundaries in R are like other languages: a block enclosed in curly braces.

In the example below, local.var is local to the function and thus is not visible outside of the function. The code below produces the error: “Error in print(local.var) : object ‘local.var’ not found”.

findSmallest <- function(v, start = 1)
{
  local.var = Inf
  for (i in start:length(v))
  {
    if (v[i] < local.var) {
      local.var = v[i]
    }
  }
  return (local.var)
}

x = c(3,1,9,7,3,6)

w = findSmallest(x, 3)

# we cannot echo or access the local variable "s"
print(local.var)

Recursion

R functions can be called recursively. The example below calculates factorial using recursion rather than a loop.

fac <- function(x)
{
  if (x == 1) 
    return (1)
  else 
    return (x * fac(x-1))
}

print(fac(8))
## [1] 40320

If it hasn’t been obvious yet, just like in other languages, the placement of curly braces makes no difference. For single statement blocks, the curly braces can be omitted.

The parenthesis around the value for return are required.

As an exercise, try writing the above function to calculate factorial using a loop.

Conclusion

Functions are an important code structuring mechanism and any R program with more than a few lines of code can benefit from functions. Functions are first-class objects in R and can be passed to functions as parameters.


Files & Resources

All Files for Lesson 6.121

References

No references.

Errata

None collected yet. Let us know.

LS0tCnRpdGxlOiAiV3JpdGluZyBGdW5jdGlvbnMgaW4gUiIKcGFyYW1zOgogIGNhdGVnb3J5OiA2CiAgbnVtYmVyOiAxMjEKICB0aW1lOiA2MAogIGxldmVsOiBiZWdpbm5lcgogIHRhZ3M6ICJyLHByaW1lcixsb29wcyIKICBkZXNjcmlwdGlvbjogIkV4cGxhaW5zIHRoZSBjb25jZXB0IG9mIGZ1bmN0aW9ucyBhbmQgdGhlaXIgaW1wbGVtZW50YXRpb24KICAgICAgICAgICAgICAgIGluIFIuIERlbW9uc3RyYXRlcyBzb21lIG9mIHRoZSB1bmlxdWUgbWVjaGFuaXNtcyBmb3IKICAgICAgICAgICAgICAgIHdyaXRpbmcgYW5kIGNhbGxpbmcgZnVuY3Rpb25zIGluIFIuIgpkYXRlOiAiPHNtYWxsPmByIFN5cy5EYXRlKClgPC9zbWFsbD4iCmF1dGhvcjogIjxzbWFsbD5NYXJ0aW4gU2NoZWRsYmF1ZXI8L3NtYWxsPiIKZW1haWw6ICJtLnNjaGVkbGJhdWVyQG5ldS5lZHUiCmFmZmlsaXRhdGlvbjogIk5vcnRoZWFzdGVybiBVbml2ZXJzaXR5IgpvdXRwdXQ6IAogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0aGVtZTogc3BhY2VsYWIKICAgIGhpZ2hsaWdodDogdGFuZ28KLS0tCgotLS0KdGl0bGU6ICI8c21hbGw+YHIgcGFyYW1zJGNhdGVnb3J5YC5gciBwYXJhbXMkbnVtYmVyYDwvc21hbGw+PGJyLz48c3BhbiBzdHlsZT0nY29sb3I6ICMyRTQwNTM7IGZvbnQtc2l6ZTogMC45ZW0nPmByIHJtYXJrZG93bjo6bWV0YWRhdGEkdGl0bGVgPC9zcGFuPiIKLS0tCgpgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9faW5zZXJ0MkRCLlInKSksIGluY2x1ZGUgPSBGQUxTRX0KYGBgCgojIyBQcmVyZXF1aXNpdGVzCgotICAgWzYuMTAwIOKUhiBCZWdpbm5pbmcgUl0oaHR0cDovL2FydGlmaWNpdW0udXMvbGVzc29ucy8wNi5yL2wtNi0xMDAtYmVnaW5uaW5nLXIvbC02LTEwMC5odG1sKQotICAgWzYuMTA0IOKUhiBRdWljayBHdWlkZSB0byBSIEZvciBQcm9ncmFtbWVyc10oaHR0cDovL2FydGlmaWNpdW0udXMvbGVzc29ucy8wNi5yL2wtNi0xMDQtcjRwcm9ncy9sLTYtMTA0Lmh0bWwpCgojIyBJbnRyb2R1Y3Rpb24KCkZ1bmN0aW9ucyBhcmUgYW4gaW1wb3J0YW50IHByb2dyYW1taW5nIGNvbnN0cnVjdC4gVGhleSBoZWxwIGluIHN0cnVjdHVyaW5nIGxhcmdlIHByb2dyYW1zIGFuZCBtaW5pbWl6ZSBkdXBsaWNhdGlvbiBvZiBjb2RlLiBBZGRpdGlvbmFsbHksIHRoZXkgbWFrZSBjb2RlIGVhc2llciB0byByZWFkIGFuZCBkZWJ1Zy4gUiwganVzdCBsaWtlIGFsbCBvdGhlciBtb2Rlcm4gcHJvZ3JhbW1pbmcgbGFuZ3VhZ2Ugc3VwcG9ydHMgZnVuY3Rpb25zLgoKQSBxdWljayBub3RlIG9uIHRlcm1pbm9sb2d5OiBhIGZ1bmN0aW9uIHJldHVybnMgYSB2YWx1ZSB3aGlsZSBhIHByb2NlZHVyZSBkb2VzIG5vdC4gUiwgbGlrZSBtYW55IG90aGVyIGxhbmd1YWdlcywgZG9lcyBub3Qgc3VwcG9ydCBwcm9jZWR1cmVzIGluIGEgZGlyZWN0IHdheSwgYWx0aG91Z2ggb25lIGNhbiBkZWZpbmUgYSBmdW5jdGlvbiB0aGF0IGRvZXMgbm90IHJldHVybiBhIHZhbHVlIHdoaWNoIHdvdWxkIHRoZW4gYmUgYSBwcm9jZWR1cmUuIFRoaXMgaXMgc2ltaWxhciB0byBmdW5jdGlvbnMgcmV0dXJuaW5nICp2b2lkKiBpbiBDL0MrKyBhbmQgSmF2YS4KClIgaXMgYSBwcm9jZWR1cmFsIGxhbmd1YWdlIHNpbWlsYXIgdG8gQy4gSXQgaXMgbm90IG9iamVjdC1vcmllbnRlZCBhbmQgZG9lcyBub3Qgc3VwcG9ydCBvYmplY3RzLCBjbGFzc2VzLCBpbmhlcml0YW5jZSwgb3IgcG9seW1vcnBoaXNtLiBJdCBoYXMgbGl0dGxlIHN1cHBvcnQgZm9yIGRhdGEgZW5jYXBzdWxhdGlvbiBvciBhYnN0cmFjdGlvbiwgc28gbm8gZXF1aXZhbGVudCBmb3IgKmNsYXNzKiBvciAqc3RydWN0KiBpbiBDL0MrKyBvciBKYXZhLgoKQWxsIGZ1bmN0aW9ucyBhcmUgZnJlZSBtZXRob2RzIGFuZCBhcmUgbm90IGJvdW5kIHRvIGFuIG9iamVjdCBvciBhIGNsYXNzIGxpa2UgaW4gSmF2YSBvciBDKysuIEl0J3MgdGhlIHNhbWUgd2F5IGFzIGluIFB5dGhvbiBvciBDLgoKQWxsIGZ1bmN0aW9ucyBpbiBSIGNhbiByZXR1cm4gYSB2YWx1ZSwgYWx0aG91Z2ggdGhleSBkbyBub3QgaGF2ZSB0by4gU28sIFIgZG9lcyBub3QgZGlzdGluZ3Vpc2ggYmV0d2VlbiBmdW5jdGlvbnMgYW5kIHByb2NlZHVyZXMgYW5kIHRoZXJlIGlzIG5vICp2b2lkKiByZXR1cm4gdHlwZSBhcyBpbiBDLCBDKyssIGFuZCBKYXZhLgoKUHJvZ3JhbXMgaXMgUiBhcmUgc2NyaXB0cy4gVGhlcmUgaXMgbm8gIm1haW4gZnVuY3Rpb24iIG9yIHNpbWlsYXIuIFIgcHJvZ3JhbXMgZXhlY3V0ZSB3aXRoIHRoZSBmaXJzdCBzdGF0ZW1lbnQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgcHJvZ3JhbSBzY3JpcHQsIHNvIGZ1bmN0aW9ucyBtdXN0IGJlIGRlZmluZWQgYmVmb3JlIHRoZXkgY2FuIGJlIGNhbGxlZC4gRnVuY3Rpb25zIGNhbiBiZSBwbGFjZWQgaW50byBwYWNrYWdlcyBmb3IgcmV1c2UgYW5kIGluY2x1c2lvbiBieSBvdGhlciBwcm9ncmFtcywgYnV0IHRoYXQgaXMgYmV5b25kIHRoZSBzY29wZSBvZiB0aGlzIGxlc3Nvbi4KCiMjIERlZmluaW5nIGEgRnVuY3Rpb24KClRoZSBnZW5lcmljIHRlbXBsYXRlIGZvciBkZWZpbmluZyBhIGZ1bmN0aW9uIGlzOgoKYGBge3IgZXZhbD1GQUxTRX0KZnVuY3Rpb25fbmFtZSA8LSBmdW5jdGlvbihhcmdfMSwgYXJnXzIsIC4uLikgewogICBGdW5jdGlvbiBib2R5IAp9CmBgYAoKIyMjIFNpbXBsZSBQcm9ncmFtIHdpdGggRnVuY3Rpb24KClRoZSBwcm9ncmFtIGJlbG93IGlzIGNvbXBsZXRlIGFuZCBkZWZpbmVzIGEgZnVuY3Rpb24gdGhhdCBpcyB0aGVuIGNhbGxlZC4gVGhlIGZ1bmN0aW9uIG11c3QgYmUgZGVmaW5lZCAqYmVmb3JlKiBpdCBjYW4gYmUgY2FsbGVkLgoKYGBge3Igc2ltcGxlRnVuY0luUHJvZ30KIyBGdWxsIFIgUHJvZ3JhbSAKCmFkZE51bXMgPC0gZnVuY3Rpb24objEsIG4yKSAKewogIGlmIChpcy5udW1lcmljKG4xKSAmJiBpcy5udW1lcmljKG4yKSkKICB7CiAgICByIDwtIG4xICsgbjIKICAKICAgIHJldHVybihyKQogIH0gZWxzZSB7CiAgICBuMSA8LSBhcy5udW1lcmljKG4xKQogICAgbjIgPC0gYXMubnVtZXJpYyhuMikKICAgIAogICAgaWYgKGlzLm5hKG4xKSB8fCBpcy5uYShuMikpIHsKICAgICAgcmV0dXJuKE5BKQogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuKGFkZE51bXMobjEsbjIpKQogICAgfQogIH0KfQoKYSA8LSAxMApiIDwtIDIwCgpjIDwtIGFkZE51bXMoYSxiKQpwcmludChjKQoKZCA8LSBhZGROdW1zKGEsNTApCnByaW50KGQpCgplIDwtIGFkZE51bXMoYSoxMCxiKjQ1KQpwcmludChlKQoKZiA8LSBhZGROdW1zKCcxJywgIjIwLjMiKQpwcmludChmKQpgYGAKCmBgYHtyIHNpbXBsZVZlY3RvckZ1bmNJblByb2d9CiMgRnVsbCBSIFByb2dyYW0gCgphZGRWZWNOdW1zIDwtIGZ1bmN0aW9uKHYpIAp7CiAgaWYgKCFpcy52ZWN0b3IodikgfHwgbGVuZ3RoKHYpIDwgMSkKICAgIHJldHVybihOQSkKICAKICBzIDwtIDAKICBmb3IgKGkgaW4gMTpsZW5ndGgodikpCiAgewogICAgbiA8LSBhcy5udW1lcmljKHZbaV0pCiAgICBpZiAoIWlzLm5hKG4pKQogICAgICBzIDwtIHMgKyBuCiAgfQogIAogIHJldHVybihzKQp9CgoKdmVjLm51bXMgPC0gYygyMyw1NSwzNCw4Nyw2NSwneCcsMTEsOTgpCgplIDwtIGFkZFZlY051bXModmVjLm51bXMpCnByaW50KGUpCmBgYAoKIyMjIEV4YW1wbGUgRnVuY3Rpb24KClRoZSBleGFtcGxlIGJlbG93IGRlZmluZXMgYSBmdW5jdGlvbiBjYWxsZWQgKmZpbmRTbWFsbGVzdCgpKiB3aGljaCB0YWtlcyBhIHZlY3RvciBvZiBwb3NpdGl2ZSBpbnRlZ2VycyBhcyBhbiBhcmd1bWVudCBhbmQgcmV0dXJucyB0aGUgc21hbGxlc3QgZWxlbWVudCBpbiB0aGUgdmVjdG9yLiBXaGlsZSBpdCBjYW4gYmUgc29sdmVkIGluIHNldmVyYWwgd2F5cywgd2Ugd2lsbCBzaG93IGEgZGVzaWduIHRoYXQgdXNlcyBsb29wcyBhbmQgc2hvdWxkIGJlIGZhbWlsaWFyIHRvIHByb2dyYW1tZXJzIG9mIG1vc3Qgb3RoZXIgbGFuZ3VhZ2VzLgoKTm90ZSB0aGF0IHdlIGFyZSB1c2luZyB0aGUgcHJlZGVmaW5lZCB2YWx1ZSAqSW5mKiB3aXRoIGlzIHRoZSBsYXJnZXN0IHJlcHJlc2VudGFibGUgaW50ZWdlci4gVGhlcmUgaXMgYWxzbyAqLUluZiogdGhhdCBpcyB0aGUgc21hbGxlc3QgcmVwcmVzZW50YWJsZSBpbnRlZ2VyLgoKYGBge3IgZnVuY3Rpb25EZWZ9CmZpbmRTbWFsbGVzdCA9IGZ1bmN0aW9uKHYpCnsKICBzID0gSW5mCiAgZm9yIChpIGluIDE6bGVuZ3RoKHYpKQogIHsKICAgIGlmICh2W2ldIDwgcykgewogICAgICBzID0gdltpXQogICAgfQogIH0KICByZXR1cm4gKHMpCn0KYGBgCgpXaGlsZSB5b3UgY2FuIHVzZSAqPSogdG8gZGVmaW5lIGEgZnVuY3Rpb24sIHlvdSBzaG91bGQgcmVhbGx5IGdldCB1c2VkIHRvIHVzaW5nIHRoZSBtb3JlIGNvbW1vbiAqXDwtKiBzeW50YXguIFNvLCBsZXQncyB0cnkgYWdhaW46CgpgYGB7ciBmdW5jdGlvbkRlZkJldHRlcn0KZmluZFNtYWxsZXN0IDwtIGZ1bmN0aW9uKHYpCnsKICBzID0gSW5mCiAgZm9yIChpIGluIDE6bGVuZ3RoKHYpKQogIHsKICAgIGlmICh2W2ldIDwgcykgewogICAgICBzID0gdltpXQogICAgfQogIH0KICByZXR1cm4gKHMpCn0KYGBgCgpKdXN0IHRvIGJlIGNsZWFyLCBpbiBwcmFjdGljZSB5b3Ugd291bGQgdXNlIHRoZSA8Y29kZT5taW4oKTwvY29kZT4gZnVuY3Rpb24gdG8gZmluZCB0aGUgc21hbGxlc3QgZWxlbWVudCByYXRoZXIgd3JpdGluZyBpdCB5b3Vyc2VsZi4KCldoaWxlIHRoZXJlIGFyZSBzZXZlcmFsIHdheXMgdG8gcmV0dXJuIGEgdmFsdWUgZnJvbSBhIGZ1bmN0aW9uLCB0aGUgd2F5IHRoYXQgaXMgbW9zdCBjb25ncnVlbnQgd2l0aCBvdGhlciBsYW5ndWFnZXMgaXMgdGhlIHVzZSBvZiB0aGUgKnJldHVybiogc3RhdGVtZW50LgoKTm90ZSB0aGF0IHRoZSB0eXBlIG9mIHJldHVybiB2YWx1ZSBhbmQgdGhlIHR5cGUgb2YgYXJndW1lbnRzIGFyZSBub3QgZGVjbGFyZWQuIFIgdXNlcyBhIGxhenkgZXZhbHVhdGlvbiBtZWNoYW5pc20gYW5kIG5vIHR5cGUgY2hlY2tpbmcgaXMgcGVyZm9ybWVkIHVudGlsIHJ1bi10aW1lLgoKIyMjIENhbGxpbmcgYSBGdW5jdGlvbgoKVG8gY2FsbCBhIGZ1bmN0aW9uLCB5b3Ugd291bGQgaW52b2tlIGl0IHdpdGggaXRzIG5hbWUgYW5kIGl0cyByZXF1aXJlZCBhcmd1bWVudHMuCgpgYGB7ciBjYWxsRnVuY30KeCA9IGMoMywxLDksNywzLDYpCgp3ID0gZmluZFNtYWxsZXN0KHgpCnByaW50KHcpCmBgYAoKIyMjIEZ1bmN0aW9uIFBhcmFtZXRlcnMKCklmIGEgZnVuY3Rpb24gdGFrZXMgc2V2ZXJhbCBhcmd1bWVudHMgeW91IGdlbmVyYWxseSBwYXNzIHRoZW0gaW4gdGhlIG9yZGVyIGRlY2xhcmVkOyB0aGUgYXBwcm9hY2ggdGhhdCBpcyB1c2VkIGJ5IGFsbCBvdGhlciBsYW5ndWFnZXMuIEhvd2V2ZXIsIGluIFIgeW91IGNhbiBwYXNzIHRoZSBhcmd1bWVudHMgaW4gYW55IG9yZGVyIGFzIGxvbmcgYXMgeW91IHNwZWNpZnkgdGhlIG5hbWUgb2YgdGhlIGFyZ3VtZW50LgoKQXJndW1lbnQgbWF0Y2hpbmcgaXMgYSBiaXQgZGlmZmVyZW50IGluIFIgY29tcGFyZWQgdG8gb3RoZXIgbGFuZ3VhZ2VzLiBGaXJzdGx5LCBSIGRvZXMgYWxsIGFyZ3VtZW50IGNoZWNraW5nIGF0IHJ1bi10aW1lLiBTZWNvbmRseSwgd2hpbGUgYXJndW1lbnRzIGNhbiBiZSBtYXRjaGVkIHBvc2l0aW9uYWxseSBsaWtlIGluIG90aGVyIGxhbmd1YWdlcywgYXJndW1lbnRzIGNhbiBhbHNvIGJlIG1hdGNoZWQgYnkgcGFyYW1ldGVyIG5hbWUgLS0gYSBzeW50YXggbm90IHN1cHBvcnRlZCBieSBtb3N0IG90aGVyIGxhbmd1YWdlcy4KCkZvciBleGFtcGxlLCB0aGUgYnVpbHQtaW4gZnVuY3Rpb24gPGNvZGU+c2VxPC9jb2RlPiBnZW5lcmF0ZXMgYSBzZXF1ZW5jZSBvZiBudW1iZXJzIGFuZCByZXR1cm5zIHRob3NlIG51bWJlcnMgaW4gYSB2ZWN0b3IuIFRoZSBkZWZpbml0aW9uIG9mIHRoZSBmdW5jdGlvbiBpcyBhcyBmb2xsb3dzOiA8Y29kZT5zZXEodG8sIGZyb20sIGJ5LCBsZW5ndGgub3V0LCBhbG9uZy53aXRoKTwvY29kZT4uCgpIZXJlIGFyZSBleGFtcGxlcyBvZiB1c2luZyBpdC4gTm90ZSB0aGF0ICpieSosICpsZW5ndGgub3V0KiwgYW5kICphbG9uZy53aXRoKiBoYXZlIGRlZmF1bHQgdmFsdWVzIGFuZCBhcmUgdGhlcmVmb3JlIG9wdGlvbmFsLgoKYGBge3Igc2VxUGFybVBhc3Npbmd9CnYgPSBzZXEoMSwgMTAsIDIpICAgICMgaW50ZWdlcnMgZnJvbSAxIHRvIDEwIGluIGluY3JlbWVudHMgb2YgMgp3ID0gc2VxKDEsIDUpICAgICAgICAjIGludGVnZXJzIGZyb20gMSB0byA1IChieSBkZWZhdWx0IGluIGluY3JlbWVudHMgb2YgMSkKCiMgcGFzcyBhcmd1bWVudHMgaW4gYSBkaWZmZXJlbnQgb3JkZXIgYnV0IHNwZWNpZnkgYnkgbmFtZQp3ID0gc2VxKGZyb20gPSA1LCBieSA9IC0wLjUsIHRvID0gMSkKYGBgCgpSIGFsc28gc3VwcG9ydHMgdmFyaWFibGUgbnVtYmVycyBvZiBhcmd1bWVudHMgYnV0IHRoYXQgaXMgYmV5b25kIHRoZSBzY29wZSBvZiB0aGlzIHR1dG9yaWFsLgoKIyMjIERlZmF1bHQgQXJndW1lbnRzCgpSIGZ1bmN0aW9ucyBjYW4gaGF2ZSBkZWZhdWx0IHZhbHVlcyBmb3IgYXJndW1lbnRzIHdoaWNoIGFyZSB0aGVuIG9wdGlvbmFsIHdoZW4gdGhlIGZ1bmN0aW9uIGlzIGNhbGxlZC4gV2hlbiB0aGUgYXJndW1lbnQgaXMgbWlzc2luZywgdGhlbiB0aGUgZGVmYXVsdCB2YWx1ZSBpcyBwYXNzZWQuIEluIHRoZSBleGFtcGxlIGJlbG93LCB0aGUgKnN0YXJ0KiBhcmd1bWVudCBpcyB0aGUgcG9zaXRpb24gYXQgd2hpY2ggdGhlIHNlYXJjaCBmb3IgdGhlIHNtYWxsZXN0IGVsZW1lbnQgd2lsbCBzdGFydC4KCmBgYHtyIGZ1bmN0aW9uRGVmQXJnfQpmaW5kU21hbGxlc3QgPC0gZnVuY3Rpb24odiwgc3RhcnQgPSAxKQp7CiAgcyA9IEluZgogIGZvciAoaSBpbiBzdGFydDpsZW5ndGgodikpCiAgewogICAgaWYgKHZbaV0gPCBzKSB7CiAgICAgIHMgPSB2W2ldCiAgICB9CiAgfQogIHJldHVybiAocykKfQpgYGAKCmBgYHtyfQp4ID0gYygzLDEsOSw3LDMsNikKCncgPSBmaW5kU21hbGxlc3QoeCwgMykKcHJpbnQodykKCncgPSBmaW5kU21hbGxlc3QoeCkKcHJpbnQodykKYGBgCgojIyMgTG9jYWwgVmFyaWFibGVzCgpBcyBpbiBtb3N0IG90aGVyIHByb2dyYW1taW5nIGxhbmd1YWdlcywgUiBmdW5jdGlvbnMgY2FuIGRlZmluZSBsb2NhbCB2YXJpYWJsZXMgdGhhdCBhcmUgbm90IGtub3duIG91dHNpZGUgdGhlIHNjb3BlIG9mIHRoZSBmdW5jdGlvbi4gVGhlIHNjb3BlIGJvdW5kYXJpZXMgaW4gUiBhcmUgbGlrZSBvdGhlciBsYW5ndWFnZXM6IGEgYmxvY2sgZW5jbG9zZWQgaW4gY3VybHkgYnJhY2VzLgoKSW4gdGhlIGV4YW1wbGUgYmVsb3csICpsb2NhbC52YXIqIGlzIGxvY2FsIHRvIHRoZSBmdW5jdGlvbiBhbmQgdGh1cyBpcyBub3QgdmlzaWJsZSBvdXRzaWRlIG9mIHRoZSBmdW5jdGlvbi4gVGhlIGNvZGUgYmVsb3cgcHJvZHVjZXMgdGhlIGVycm9yOiAiRXJyb3IgaW4gcHJpbnQobG9jYWwudmFyKSA6IG9iamVjdCAnbG9jYWwudmFyJyBub3QgZm91bmQiLgoKYGBge3IgbG9jYVZhcnMsIGVjaG89VFJVRSwgZXZhbD1GQUxTRX0KZmluZFNtYWxsZXN0IDwtIGZ1bmN0aW9uKHYsIHN0YXJ0ID0gMSkKewogIGxvY2FsLnZhciA9IEluZgogIGZvciAoaSBpbiBzdGFydDpsZW5ndGgodikpCiAgewogICAgaWYgKHZbaV0gPCBsb2NhbC52YXIpIHsKICAgICAgbG9jYWwudmFyID0gdltpXQogICAgfQogIH0KICByZXR1cm4gKGxvY2FsLnZhcikKfQoKeCA9IGMoMywxLDksNywzLDYpCgp3ID0gZmluZFNtYWxsZXN0KHgsIDMpCgojIHdlIGNhbm5vdCBlY2hvIG9yIGFjY2VzcyB0aGUgbG9jYWwgdmFyaWFibGUgInMiCnByaW50KGxvY2FsLnZhcikKYGBgCgojIyMgUmVjdXJzaW9uCgpSIGZ1bmN0aW9ucyBjYW4gYmUgY2FsbGVkIHJlY3Vyc2l2ZWx5LiBUaGUgZXhhbXBsZSBiZWxvdyBjYWxjdWxhdGVzIGZhY3RvcmlhbCB1c2luZyByZWN1cnNpb24gcmF0aGVyIHRoYW4gYSBsb29wLgoKYGBge3IgcmVjdXJzaXZlRnVuY3N9CmZhYyA8LSBmdW5jdGlvbih4KQp7CiAgaWYgKHggPT0gMSkgCiAgICByZXR1cm4gKDEpCiAgZWxzZSAKICAgIHJldHVybiAoeCAqIGZhYyh4LTEpKQp9CgpwcmludChmYWMoOCkpCmBgYAoKPiBJZiBpdCBoYXNuJ3QgYmVlbiBvYnZpb3VzIHlldCwganVzdCBsaWtlIGluIG90aGVyIGxhbmd1YWdlcywgdGhlIHBsYWNlbWVudCBvZiBjdXJseSBicmFjZXMgbWFrZXMgbm8gZGlmZmVyZW5jZS4gRm9yIHNpbmdsZSBzdGF0ZW1lbnQgYmxvY2tzLCB0aGUgY3VybHkgYnJhY2VzIGNhbiBiZSBvbWl0dGVkLgoKPiBUaGUgcGFyZW50aGVzaXMgYXJvdW5kIHRoZSB2YWx1ZSBmb3IgKnJldHVybiogYXJlIHJlcXVpcmVkLgoKQXMgYW4gZXhlcmNpc2UsIHRyeSB3cml0aW5nIHRoZSBhYm92ZSBmdW5jdGlvbiB0byBjYWxjdWxhdGUgZmFjdG9yaWFsIHVzaW5nIGEgbG9vcC4KCiMjIENvbmNsdXNpb24KCkZ1bmN0aW9ucyBhcmUgYW4gaW1wb3J0YW50IGNvZGUgc3RydWN0dXJpbmcgbWVjaGFuaXNtIGFuZCBhbnkgUiBwcm9ncmFtIHdpdGggbW9yZSB0aGFuIGEgZmV3IGxpbmVzIG9mIGNvZGUgY2FuIGJlbmVmaXQgZnJvbSBmdW5jdGlvbnMuIEZ1bmN0aW9ucyBhcmUgZmlyc3QtY2xhc3Mgb2JqZWN0cyBpbiBSIGFuZCBjYW4gYmUgcGFzc2VkIHRvIGZ1bmN0aW9ucyBhcyBwYXJhbWV0ZXJzLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBGaWxlcyAmIFJlc291cmNlcwoKYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9CnppcE5hbWUgPSBzcHJpbnRmKCJMZXNzb25GaWxlcy0lcy0lcy56aXAiLCAKICAgICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikKCnRleHRBTGluayA9IHBhc3RlMCgiQWxsIEZpbGVzIGZvciBMZXNzb24gIiwgCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikKCiMgZG93bmxvYWRGaWxlc0xpbmsoKSBpcyBpbmNsdWRlZCBmcm9tIF9pbnNlcnQyREIuUgprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgUmVmZXJlbmNlcwoKTm8gcmVmZXJlbmNlcy4KCiMjIEVycmF0YQoKTm9uZSBjb2xsZWN0ZWQgeWV0LiBMZXQgdXMga25vdy4KCmBgYHs9aHRtbH0KPHNjcmlwdCBzcmM9Imh0dHBzOi8vZm9ybS5qb3Rmb3JtLmNvbS9zdGF0aWMvZmVlZGJhY2syLmpzIiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgogIG5ldyBKb3Rmb3JtRmVlZGJhY2soewogICAgZm9ybUlkOiAiMjEyMTg3MDcyNzg0MTU3IiwKICAgIGJ1dHRvblRleHQ6ICJGZWVkYmFjayIsCiAgICBiYXNlOiAiaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tLyIsCiAgICBiYWNrZ3JvdW5kOiAiI0Y1OTIwMiIsCiAgICBmb250Q29sb3I6ICIjRkZGRkZGIiwKICAgIGJ1dHRvblNpZGU6ICJsZWZ0IiwKICAgIGJ1dHRvbkFsaWduOiAiY2VudGVyIiwKICAgIHR5cGU6IGZhbHNlLAogICAgd2lkdGg6IDcwMCwKICAgIGhlaWdodDogNTAwLAogICAgaXNDYXJkRm9ybTogZmFsc2UKICB9KTsKPC9zY3JpcHQ+CmBgYApgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9fZGVwbG95S25pdC5SJykpLCBpbmNsdWRlID0gRkFMU0V9CmBgYAo=