Median Function

med_val <- function(x){
  n <- length(x)
  y <- sort(x)
  if (n%%2==1){
    med <- y[(n+1)/2]
  }
  else{
    med <- mean(c(y[n/2], y[(n/2)+1]))
  }
  med
}
med_val(c(10,20,30,40,50,20,2222222,13,342))
[1] 30

Mode Function

my_mode<-function(x){
  unique_x<-unique(x)
  tabulate_x<-tabulate(match(x,unique_x))
  unique_x[tabulate_x==max(tabulate_x)]
}
my_mode(c(10,20,30,40,50,20,2222222,13,342))
[1] 20

Correlation coefficient Function

cor.coeff<-function(x,y){
  avg_x<-mean(x)
  avg_y<-mean(y)
  nom<-sum((x-avg_x)*(y-avg_y))
  ssx<-sum((x-avg_x)^2)
  ssy<-sum((y-avg_y)^2)
  denom<-sqrt(ssx*ssy)
  r<-nom/denom
  r
}

cor.coeff(c(1,2,3,4,5,6,7,8,9), c(10,20,30,40,50,20,2222222,13,342))
[1] 0.273945

Custom (Range of a vector) Function

own.range <- function(x){
  n<-length(x)
  for (i in 1:n){
    for (j in 1:(n-1)){
      if (x[j] > x[j+1]){
        temp <- x[j]
        x[j] <- x[j+1]
        x[j+1] <- temp
      }
    }
  }
  range <- x[n]-x[1]
  range
}

own.range(c(10,20,30,40,50,20,2222222,13,342))
[1] 2222212

Suppose a box contains 10 identical items and the probability of having a defective item is 0.2.Then

i)Prob. of having no defective item ii)Find the number of defective items in 1000 such boxes iii)Estimate the probability of containing exactly 1 defective item iv)Estimate the probability of containing at most 1 defective item

# Given
n <- 10        # items per box
p <- 0.2       # probability of defect

# i) Probability of no defective item
prob_0 <- dbinom(0, size = n, prob = p)
prob_0
[1] 0.1073742
# ii) Expected number of defective items in 1000 boxes
expected_defects <- 1000 * (n * p)
expected_defects
[1] 2000
# iii) Probability of exactly 1 defective item
prob_1 <- dbinom(1, size = n, prob = p)
prob_1
[1] 0.2684355
# iv) Probability of at most 1 defective item
prob_at_most_1 <- pbinom(1, size = n, prob = p)
prob_at_most_1
[1] 0.3758096

Plotting PMF and CDF of X~binomial(5,0.6)

x<-0:5
y<-dbinom(x,5,0.6)
z<-pbinom(x,5,0.6)
plot(x,y,type="h",xlab="x",ylab="f(x)",
     main="PMF of X")

plot(x,z,type="s",xlab="x",ylab="F(x)",
     main="CDF of X")

Log Likelihood of Bernoulli Distribution

LL.Ber<-function(x,p){
  sum(x)*log(p)+(length(x)-sum(x))*log(1-p)
}

sample <- rbinom(10, size = 1, prob = 0.3)
LL.Ber(x = sample, p)
[1] -6.390319

Sum function

sum_value<-function(x){
  n<-length(x)
  s<-0
  for(i in 1:n){
    s<-s+x[i]
  }
  s
}

sum_value(c(10,20,30,40,50,20,2222222,13,342))
[1] 2222747

Factorial function

own.factorial<-function(n){
x<-1:n
L<-length(x)
prod<-1
for(i in 1:L){
prod<-prod*x[i]
}
prod
}

own.factorial(5)
[1] 120

Write a function that finds absolute value of a vector

bs_value<-function(x){
  ifelse(x<0,-x,x)}
abs_value(c(10,20,30,40,50,20,-2222222,13,-342))
[1]      10      20      30      40      50
[6]      20 2222222      13     342

Ascending(sort) function

asc.sort <- function(x){
  n<-length(x)
  for (i in 1:n){
    for (j in 1:(n-1)){
      if (x[j] > x[j+1]){
        temp <- x[j]
        x[j] <- x[j+1]
        x[j+1] <- temp
      }
    }
  }
  x
}

asc.sort(c(10,20,30,40,50,20,-2222222,13,-342))
[1] -2222222     -342       10       13
[5]       20       20       30       40
[9]       50

Descending(sort)function

des.sort <- function(x){
  n<-length(x)
  for (i in 1:n){
    for (j in 1:(n-1)){
      if (x[j] < x[j+1]){
        temp <- x[j]
        x[j] <- x[j+1]
        x[j+1] <- temp
      }
    }
  }
  x
}

des.sort(c(10,20,30,40,50,20,-2222222,13,-342))
[1]       50       40       30       20
[5]       20       13       10     -342
[9] -2222222

Write a function to find maximum value of a function

max_value<-function(x){
  n<-length(x)
  for(i in 2:n){
    if(x[1]<x[i]){
      x[1]<-x[i]
    }
  }
  x[1]
}

max_value(c(10,20,30,40,50,20,-2222222,13,-342))
[1] 50

Write a function that counts length without missing value

non.na.count<-function(x){
  i=1
  count=0
  n<- length(x)
  while (i<=n){
    if (!is.na(x[i])){
      count<-count+1
    }
    i=i+1
  }
  count 
}

non.na.count(c(NA,20,30,40,50,NA,20,-2222222,13,-342))
[1] 8

Let X1,…,Xn be a sequence of n random integers between 1 and 10 and let Yn=ΣXi.Find n so that max(Yn)<100

max100<- function(x){
  set.seed(209)
  sum=0
  i=1
  n=length(x)
  while (sum<100){
    sum<-sum+x[i]
    i<-i+1
  }
  cat("n =",i,"\n")
  cat("Sum =",sum)
}

max100(sample(1:10, 100, replace=TRUE))
n = 19 
Sum = 100

Create a user-defined function to compute the mean of numeric variables only and apply it to the birthwt dataset.

data.mean<-function(x){
  if(is.numeric(x)==T){
    mean(x)}
  else{
    NA
  }
}
library(MASS)
head(birthwt)
attach(birthwt)
birthwt$low<-as.factor(birthwt$low)
birthwt$race<-as.factor(birthwt$race)
birthwt$smoke<-as.factor(birthwt$smoke)
birthwt$ui<-as.factor(birthwt$ui)
birthwt$ht<-as.factor(birthwt$ht)
sapply(birthwt,data.mean)
         low          age          lwt 
          NA   23.2380952  129.8148148 
        race        smoke          ptl 
          NA           NA    0.1957672 
          ht           ui          ftv 
          NA           NA    0.7936508 
         bwt 
2944.5873016 

INC_2024-1

Part-1

"(a)"
[1] "(a)"
x <- seq(3, 6, by = 0.1)
v <- exp(x) * cos(x^2)
sum_v <- sum(v)
sum_v
[1] -339.2342
"(b)"
[1] "(b)"
# y<-rnorm(15, 0, 1)
n <- length(y)
avg_y <- mean(y)
for (i in 1:n){
  v <- sqrt(abs(y - avg_y))
}
print(v)
 [1] 1.1653621 0.8584013 0.9961283 0.9553444
 [5] 0.5351151 1.0487096 1.1013675 0.5778597
 [9] 0.4415788 1.2865604 0.6413056 0.7041377
[13] 1.0721042 0.8403968 0.4679993
avg_v <- mean(v)
print(avg_v)
[1] 0.8461581
"(c)"
[1] "(c)"
# v <- c(5.2, 7.0, 9.1, 3.8, 7.5, 5.9, 6.5)
picked <- v[v < 6]
indices <- which(v > 6 & v < 8)
print(picked)
 [1] 1.1653621 0.8584013 0.9961283 0.9553444
 [5] 0.5351151 1.0487096 1.1013675 0.5778597
 [9] 0.4415788 1.2865604 0.6413056 0.7041377
[13] 1.0721042 0.8403968 0.4679993
print(indices)
integer(0)
"(d)"
[1] "(d)"
int.v <- round(v)
sum(int.v %% 3 == 0)
[1] 2
"(e)"
[1] "(e)"
my.means <- function(x){
  am <- mean(x)
  gm <- exp(mean(log(x[x>0])))   # GM requires positive values
  hm <- length(x) / sum(1/x[x!=0])
  c(AM = am, GM = gm, HM = hm)
}

"(f)"
[1] "(f)"
my.means(v)
       AM        GM        HM 
0.8461581 0.8023689 0.7569923 

Part-2

# (a)
set.seed(75)
x <- sample(1:100, 60, replace = TRUE)
M <- matrix(x, nrow = 6, ncol = 10, byrow = TRUE)
rowtotals <- rowSums(M)
rowtotals
[1] 565 623 392 506 539 542
# (b)
count.over <- function(vec, k) {
  sum(vec > k)
}

# (c)
apply(M, MARGIN = 1, count.over, k = 4) # 1 means by row, 2 means by column
[1] 10 10 10 10  9  9

Part-3

# -----------------------------
# Simulate sample (given)
# -----------------------------
"(a)"
[1] "(a)"
set.seed(123)
Y <- rbinom(2000, size = 15, prob = 0.25)

# (i) Estimated P(2 < Y < 10)
est_prob <- mean(Y > 2 & Y < 10)
est_prob
[1] 0.7665
# (ii)
quantile(Y, 0.75)
75% 
  5 
"(b)"
[1] "(b)"
# (i) Actual P(2 < Y < 10)
actual_prob <- pbinom(9, 15, 0.25) - pbinom(2, 15, 0.25)
actual_prob
[1] 0.7631172
# (ii) Actual Q3 from the exact distribution
actual_Q3 <- qbinom(0.75, 15, 0.25)
actual_Q3
[1] 5

INC_2023-1

Part 1

  1. Create a vector x that stores the sequence {1.1, 1.5, 1.9, …, 111.1}
x <- seq(1.1,111.1, by=0.4)
  1. Create a vector y where y=logx
y <- log(x)
  1. Find the number of observations in y
n <- length(y)
n
[1] 276
  1. Create vector y12 with every 12th element
y12 <- y[seq(12, length(y), by = 12)]
  1. Display the positions (indices) of the elements in vector Y that lie between 0.5 and 2.
indices <- which((y > 0.5) & (y < 2))
print(indices)
 [1]  3  4  5  6  7  8  9 10 11 12 13 14 15
[14] 16
  1. Sum of elements in y that are below 3
sum_below_3 <- sum(y[y < 3])
sum_below_3
[1] 103.0407

Part 2 (regression context)

'(a)'
[1] "(a)"
# Set seed for reproducibility
set.seed(123)

# Generate data
n <- 1000

# X ~ N(0, 4) (variance = 4, so sd = 2)
X <- rnorm(n, mean = 0, sd = sqrt(4))

# ε ~ N(10, 2) (variance = 2, so sd = sqrt(2))
# Note: This error term with mean 10 seems unusual for regression
e <- rnorm(n, mean = 0, sd = sqrt(2))

# Generate Y = 0.5 + 0.8*X + e
Y <- 0.5 + 0.8 * X + e

# Store the values of X as x and Y as y, as requested
x <- X
y <- Y
'(b)'
[1] "(b)"
# 1. Create matrix D:
# First column: constant 1 (1000 rows)
# Second column: vector x from part (a)
D <- matrix(c(rep(1, n), x), ncol = 2)

# 2. Create column matrix M using vector y from part (a)
M <- matrix(y, ncol = 1)
'(C)'
[1] "(C)"
# 1. Calculate b = (D^T D)^{-1} D^T M
D_transpose <- t(D)
D_transpose_D <- D_transpose %*% D
D_transpose_M <- D_transpose %*% M

# Calculate inverse and b
D_transpose_D_inv <- solve(D_transpose_D)
b <- D_transpose_D_inv %*% D_transpose_M
print(b)
          [,1]
[1,] 0.5580467
[2,] 0.8622588
# 2. True parameter vector B from part (a)
B <- c(0.5, 0.8)
print(B)
[1] 0.5 0.8
# 3. Calculate absolute differences |b - B|
abs_difference <- abs(b-B)

cat("Absolute differences:\n")
Absolute differences:
print(abs_difference)
           [,1]
[1,] 0.05804673
[2,] 0.06225884
LS0tDQp0aXRsZTogIjJEZWMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMjIE1lZGlhbiBGdW5jdGlvbg0KYGBge3J9DQptZWRfdmFsIDwtIGZ1bmN0aW9uKHgpew0KICBuIDwtIGxlbmd0aCh4KQ0KICB5IDwtIHNvcnQoeCkNCiAgaWYgKG4lJTI9PTEpew0KICAgIG1lZCA8LSB5WyhuKzEpLzJdDQogIH0NCiAgZWxzZXsNCiAgICBtZWQgPC0gbWVhbihjKHlbbi8yXSwgeVsobi8yKSsxXSkpDQogIH0NCiAgbWVkDQp9DQpgYGANCg0KYGBge3J9DQptZWRfdmFsKGMoMTAsMjAsMzAsNDAsNTAsMjAsMjIyMjIyMiwxMywzNDIpKQ0KYGBgDQojIyMgTW9kZSBGdW5jdGlvbg0KYGBge3J9DQpteV9tb2RlPC1mdW5jdGlvbih4KXsNCiAgdW5pcXVlX3g8LXVuaXF1ZSh4KQ0KICB0YWJ1bGF0ZV94PC10YWJ1bGF0ZShtYXRjaCh4LHVuaXF1ZV94KSkNCiAgdW5pcXVlX3hbdGFidWxhdGVfeD09bWF4KHRhYnVsYXRlX3gpXQ0KfQ0KbXlfbW9kZShjKDEwLDIwLDMwLDQwLDUwLDIwLDIyMjIyMjIsMTMsMzQyKSkNCmBgYA0KIyMjIENvcnJlbGF0aW9uIGNvZWZmaWNpZW50IEZ1bmN0aW9uDQpgYGB7cn0NCmNvci5jb2VmZjwtZnVuY3Rpb24oeCx5KXsNCiAgYXZnX3g8LW1lYW4oeCkNCiAgYXZnX3k8LW1lYW4oeSkNCiAgbm9tPC1zdW0oKHgtYXZnX3gpKih5LWF2Z195KSkNCiAgc3N4PC1zdW0oKHgtYXZnX3gpXjIpDQogIHNzeTwtc3VtKCh5LWF2Z195KV4yKQ0KICBkZW5vbTwtc3FydChzc3gqc3N5KQ0KICByPC1ub20vZGVub20NCiAgcg0KfQ0KDQpjb3IuY29lZmYoYygxLDIsMyw0LDUsNiw3LDgsOSksIGMoMTAsMjAsMzAsNDAsNTAsMjAsMjIyMjIyMiwxMywzNDIpKQ0KYGBgDQojIyMgQ3VzdG9tIChSYW5nZSBvZiBhIHZlY3RvcikgRnVuY3Rpb24NCmBgYHtyfQ0Kb3duLnJhbmdlIDwtIGZ1bmN0aW9uKHgpew0KICBuPC1sZW5ndGgoeCkNCiAgZm9yIChpIGluIDE6bil7DQogICAgZm9yIChqIGluIDE6KG4tMSkpew0KICAgICAgaWYgKHhbal0gPiB4W2orMV0pew0KICAgICAgICB0ZW1wIDwtIHhbal0NCiAgICAgICAgeFtqXSA8LSB4W2orMV0NCiAgICAgICAgeFtqKzFdIDwtIHRlbXANCiAgICAgIH0NCiAgICB9DQogIH0NCiAgcmFuZ2UgPC0geFtuXS14WzFdDQogIHJhbmdlDQp9DQoNCm93bi5yYW5nZShjKDEwLDIwLDMwLDQwLDUwLDIwLDIyMjIyMjIsMTMsMzQyKSkNCmBgYA0KU3VwcG9zZSBhIGJveCBjb250YWlucyAxMCBpZGVudGljYWwNCml0ZW1zIGFuZCB0aGUgcHJvYmFiaWxpdHkgb2YgaGF2aW5nIGENCmRlZmVjdGl2ZSBpdGVtIGlzIDAuMi5UaGVuDQoNCmkpUHJvYi4gb2YgaGF2aW5nIG5vIGRlZmVjdGl2ZSBpdGVtDQppaSlGaW5kIHRoZSBudW1iZXIgb2YgZGVmZWN0aXZlIGl0ZW1zDQppbiAxMDAwIHN1Y2ggYm94ZXMNCmlpaSlFc3RpbWF0ZSB0aGUgcHJvYmFiaWxpdHkgb2YNCmNvbnRhaW5pbmcgZXhhY3RseSAxIGRlZmVjdGl2ZSBpdGVtDQppdilFc3RpbWF0ZSB0aGUgcHJvYmFiaWxpdHkgb2YNCmNvbnRhaW5pbmcgYXQgbW9zdCAxIGRlZmVjdGl2ZSBpdGVtDQpgYGB7cn0NCiMgR2l2ZW4NCm4gPC0gMTAgICAgICAgICMgaXRlbXMgcGVyIGJveA0KcCA8LSAwLjIgICAgICAgIyBwcm9iYWJpbGl0eSBvZiBkZWZlY3QNCg0KIyBpKSBQcm9iYWJpbGl0eSBvZiBubyBkZWZlY3RpdmUgaXRlbQ0KcHJvYl8wIDwtIGRiaW5vbSgwLCBzaXplID0gbiwgcHJvYiA9IHApDQpwcm9iXzANCg0KIyBpaSkgRXhwZWN0ZWQgbnVtYmVyIG9mIGRlZmVjdGl2ZSBpdGVtcyBpbiAxMDAwIGJveGVzDQpleHBlY3RlZF9kZWZlY3RzIDwtIDEwMDAgKiAobiAqIHApDQpleHBlY3RlZF9kZWZlY3RzDQoNCiMgaWlpKSBQcm9iYWJpbGl0eSBvZiBleGFjdGx5IDEgZGVmZWN0aXZlIGl0ZW0NCnByb2JfMSA8LSBkYmlub20oMSwgc2l6ZSA9IG4sIHByb2IgPSBwKQ0KcHJvYl8xDQoNCiMgaXYpIFByb2JhYmlsaXR5IG9mIGF0IG1vc3QgMSBkZWZlY3RpdmUgaXRlbQ0KcHJvYl9hdF9tb3N0XzEgPC0gcGJpbm9tKDEsIHNpemUgPSBuLCBwcm9iID0gcCkNCnByb2JfYXRfbW9zdF8xDQoNCmBgYA0KIyMjIFBsb3R0aW5nIFBNRiBhbmQgQ0RGIG9mIFh+Ymlub21pYWwoNSwwLjYpDQpgYGB7cn0NCng8LTA6NQ0KeTwtZGJpbm9tKHgsNSwwLjYpDQp6PC1wYmlub20oeCw1LDAuNikNCnBsb3QoeCx5LHR5cGU9ImgiLHhsYWI9IngiLHlsYWI9ImYoeCkiLA0KICAgICBtYWluPSJQTUYgb2YgWCIpDQpwbG90KHgseix0eXBlPSJzIix4bGFiPSJ4Iix5bGFiPSJGKHgpIiwNCiAgICAgbWFpbj0iQ0RGIG9mIFgiKQ0KYGBgDQojIyMgTG9nIExpa2VsaWhvb2Qgb2YgQmVybm91bGxpIERpc3RyaWJ1dGlvbg0KYGBge3J9DQpMTC5CZXI8LWZ1bmN0aW9uKHgscCl7DQogIHN1bSh4KSpsb2cocCkrKGxlbmd0aCh4KS1zdW0oeCkpKmxvZygxLXApDQp9DQoNCnNhbXBsZSA8LSByYmlub20oMTAsIHNpemUgPSAxLCBwcm9iID0gMC4zKQ0KTEwuQmVyKHggPSBzYW1wbGUsIHApDQpgYGANCiMjIyBTdW0gZnVuY3Rpb24NCmBgYHtyfQ0Kc3VtX3ZhbHVlPC1mdW5jdGlvbih4KXsNCiAgbjwtbGVuZ3RoKHgpDQogIHM8LTANCiAgZm9yKGkgaW4gMTpuKXsNCiAgICBzPC1zK3hbaV0NCiAgfQ0KICBzDQp9DQoNCnN1bV92YWx1ZShjKDEwLDIwLDMwLDQwLDUwLDIwLDIyMjIyMjIsMTMsMzQyKSkNCmBgYA0KIyMjIEZhY3RvcmlhbCBmdW5jdGlvbg0KYGBge3J9DQpvd24uZmFjdG9yaWFsPC1mdW5jdGlvbihuKXsNCng8LTE6bg0KTDwtbGVuZ3RoKHgpDQpwcm9kPC0xDQpmb3IoaSBpbiAxOkwpew0KcHJvZDwtcHJvZCp4W2ldDQp9DQpwcm9kDQp9DQoNCm93bi5mYWN0b3JpYWwoNSkNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdGhhdCBmaW5kcyBhYnNvbHV0ZSB2YWx1ZSBvZiBhIHZlY3Rvcg0KYGBge3J9DQpic192YWx1ZTwtZnVuY3Rpb24oeCl7DQogIGlmZWxzZSh4PDAsLXgseCl9DQphYnNfdmFsdWUoYygxMCwyMCwzMCw0MCw1MCwyMCwtMjIyMjIyMiwxMywtMzQyKSkNCmBgYA0KIyMjIEFzY2VuZGluZyhzb3J0KSBmdW5jdGlvbg0KYGBge3J9DQphc2Muc29ydCA8LSBmdW5jdGlvbih4KXsNCiAgbjwtbGVuZ3RoKHgpDQogIGZvciAoaSBpbiAxOm4pew0KICAgIGZvciAoaiBpbiAxOihuLTEpKXsNCiAgICAgIGlmICh4W2pdID4geFtqKzFdKXsNCiAgICAgICAgdGVtcCA8LSB4W2pdDQogICAgICAgIHhbal0gPC0geFtqKzFdDQogICAgICAgIHhbaisxXSA8LSB0ZW1wDQogICAgICB9DQogICAgfQ0KICB9DQogIHgNCn0NCg0KYXNjLnNvcnQoYygxMCwyMCwzMCw0MCw1MCwyMCwtMjIyMjIyMiwxMywtMzQyKSkNCmBgYA0KIyMjIERlc2NlbmRpbmcoc29ydClmdW5jdGlvbg0KYGBge3J9DQpkZXMuc29ydCA8LSBmdW5jdGlvbih4KXsNCiAgbjwtbGVuZ3RoKHgpDQogIGZvciAoaSBpbiAxOm4pew0KICAgIGZvciAoaiBpbiAxOihuLTEpKXsNCiAgICAgIGlmICh4W2pdIDwgeFtqKzFdKXsNCiAgICAgICAgdGVtcCA8LSB4W2pdDQogICAgICAgIHhbal0gPC0geFtqKzFdDQogICAgICAgIHhbaisxXSA8LSB0ZW1wDQogICAgICB9DQogICAgfQ0KICB9DQogIHgNCn0NCg0KZGVzLnNvcnQoYygxMCwyMCwzMCw0MCw1MCwyMCwtMjIyMjIyMiwxMywtMzQyKSkNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gZmluZCBtYXhpbXVtIHZhbHVlIG9mIGEgZnVuY3Rpb24NCmBgYHtyfQ0KbWF4X3ZhbHVlPC1mdW5jdGlvbih4KXsNCiAgbjwtbGVuZ3RoKHgpDQogIGZvcihpIGluIDI6bil7DQogICAgaWYoeFsxXTx4W2ldKXsNCiAgICAgIHhbMV08LXhbaV0NCiAgICB9DQogIH0NCiAgeFsxXQ0KfQ0KDQptYXhfdmFsdWUoYygxMCwyMCwzMCw0MCw1MCwyMCwtMjIyMjIyMiwxMywtMzQyKSkNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdGhhdCBjb3VudHMgbGVuZ3RoIHdpdGhvdXQgbWlzc2luZyB2YWx1ZQ0KYGBge3J9DQpub24ubmEuY291bnQ8LWZ1bmN0aW9uKHgpew0KICBpPTENCiAgY291bnQ9MA0KICBuPC0gbGVuZ3RoKHgpDQogIHdoaWxlIChpPD1uKXsNCiAgICBpZiAoIWlzLm5hKHhbaV0pKXsNCiAgICAgIGNvdW50PC1jb3VudCsxDQogICAgfQ0KICAgIGk9aSsxDQogIH0NCiAgY291bnQgDQp9DQoNCm5vbi5uYS5jb3VudChjKE5BLDIwLDMwLDQwLDUwLE5BLDIwLC0yMjIyMjIyLDEzLC0zNDIpKQ0KYGBgDQpMZXQgWDEsLi4uLFhuIGJlIGEgc2VxdWVuY2Ugb2YgbiByYW5kb20NCmludGVnZXJzIGJldHdlZW4gMSBhbmQgMTAgYW5kIGxldA0KWW49zqNYaS5GaW5kIG4gc28gdGhhdCBtYXgoWW4pPDEwMA0KYGBge3J9DQptYXgxMDA8LSBmdW5jdGlvbih4KXsNCiAgc2V0LnNlZWQoMjA5KQ0KICBzdW09MA0KICBpPTENCiAgbj1sZW5ndGgoeCkNCiAgd2hpbGUgKHN1bTwxMDApew0KICAgIHN1bTwtc3VtK3hbaV0NCiAgICBpPC1pKzENCiAgfQ0KICBjYXQoIm4gPSIsaSwiXG4iKQ0KICBjYXQoIlN1bSA9IixzdW0pDQp9DQoNCm1heDEwMChzYW1wbGUoMToxMCwgMTAwLCByZXBsYWNlPVRSVUUpKQ0KYGBgDQpDcmVhdGUgYSB1c2VyLWRlZmluZWQgZnVuY3Rpb24gdG8gY29tcHV0ZSB0aGUgbWVhbiBvZiBudW1lcmljIHZhcmlhYmxlcyBvbmx5IGFuZCBhcHBseSBpdCB0byB0aGUgYmlydGh3dCBkYXRhc2V0Lg0KYGBge3J9DQpkYXRhLm1lYW48LWZ1bmN0aW9uKHgpew0KICBpZihpcy5udW1lcmljKHgpPT1UKXsNCiAgICBtZWFuKHgpfQ0KICBlbHNlew0KICAgIE5BDQogIH0NCn0NCmxpYnJhcnkoTUFTUykNCmhlYWQoYmlydGh3dCkNCmF0dGFjaChiaXJ0aHd0KQ0KYmlydGh3dCRsb3c8LWFzLmZhY3RvcihiaXJ0aHd0JGxvdykNCmJpcnRod3QkcmFjZTwtYXMuZmFjdG9yKGJpcnRod3QkcmFjZSkNCmJpcnRod3Qkc21va2U8LWFzLmZhY3RvcihiaXJ0aHd0JHNtb2tlKQ0KYmlydGh3dCR1aTwtYXMuZmFjdG9yKGJpcnRod3QkdWkpDQpiaXJ0aHd0JGh0PC1hcy5mYWN0b3IoYmlydGh3dCRodCkNCnNhcHBseShiaXJ0aHd0LGRhdGEubWVhbikNCg0KYGBgDQojIElOQ18yMDI0LTENCg0KIyMjIFBhcnQtMQ0KYGBge3J9DQoiKGEpIg0KeCA8LSBzZXEoMywgNiwgYnkgPSAwLjEpDQp2IDwtIGV4cCh4KSAqIGNvcyh4XjIpDQpzdW1fdiA8LSBzdW0odikNCnN1bV92DQoNCiIoYikiDQojIHk8LXJub3JtKDE1LCAwLCAxKQ0KbiA8LSBsZW5ndGgoeSkNCmF2Z195IDwtIG1lYW4oeSkNCmZvciAoaSBpbiAxOm4pew0KICB2IDwtIHNxcnQoYWJzKHkgLSBhdmdfeSkpDQp9DQpwcmludCh2KQ0KYXZnX3YgPC0gbWVhbih2KQ0KcHJpbnQoYXZnX3YpDQoNCg0KIihjKSINCiMgdiA8LSBjKDUuMiwgNy4wLCA5LjEsIDMuOCwgNy41LCA1LjksIDYuNSkNCnBpY2tlZCA8LSB2W3YgPCA2XQ0KaW5kaWNlcyA8LSB3aGljaCh2ID4gNiAmIHYgPCA4KQ0KcHJpbnQocGlja2VkKQ0KcHJpbnQoaW5kaWNlcykNCg0KIihkKSINCmludC52IDwtIHJvdW5kKHYpDQpzdW0oaW50LnYgJSUgMyA9PSAwKQ0KDQoiKGUpIg0KbXkubWVhbnMgPC0gZnVuY3Rpb24oeCl7DQogIGFtIDwtIG1lYW4oeCkNCiAgZ20gPC0gZXhwKG1lYW4obG9nKHhbeD4wXSkpKSAgICMgR00gcmVxdWlyZXMgcG9zaXRpdmUgdmFsdWVzDQogIGhtIDwtIGxlbmd0aCh4KSAvIHN1bSgxL3hbeCE9MF0pDQogIGMoQU0gPSBhbSwgR00gPSBnbSwgSE0gPSBobSkNCn0NCg0KIihmKSINCm15Lm1lYW5zKHYpDQpgYGANCiMjIyBQYXJ0LTINCmBgYHtyfQ0KIyAoYSkNCnNldC5zZWVkKDc1KQ0KeCA8LSBzYW1wbGUoMToxMDAsIDYwLCByZXBsYWNlID0gVFJVRSkNCk0gPC0gbWF0cml4KHgsIG5yb3cgPSA2LCBuY29sID0gMTAsIGJ5cm93ID0gVFJVRSkNCnJvd3RvdGFscyA8LSByb3dTdW1zKE0pDQpyb3d0b3RhbHMNCg0KIyAoYikNCmNvdW50Lm92ZXIgPC0gZnVuY3Rpb24odmVjLCBrKSB7DQogIHN1bSh2ZWMgPiBrKQ0KfQ0KDQojIChjKQ0KYXBwbHkoTSwgTUFSR0lOID0gMSwgY291bnQub3ZlciwgayA9IDQpICMgMSBtZWFucyBieSByb3csIDIgbWVhbnMgYnkgY29sdW1uDQpgYGANCiMjIyBQYXJ0LTMNCmBgYHtyfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBTaW11bGF0ZSBzYW1wbGUgKGdpdmVuKQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIihhKSINCnNldC5zZWVkKDEyMykNClkgPC0gcmJpbm9tKDIwMDAsIHNpemUgPSAxNSwgcHJvYiA9IDAuMjUpDQoNCiMgKGkpIEVzdGltYXRlZCBQKDIgPCBZIDwgMTApDQplc3RfcHJvYiA8LSBtZWFuKFkgPiAyICYgWSA8IDEwKQ0KZXN0X3Byb2INCiMgKGlpKQ0KcXVhbnRpbGUoWSwgMC43NSkNCg0KIihiKSINCg0KIyAoaSkgQWN0dWFsIFAoMiA8IFkgPCAxMCkNCmFjdHVhbF9wcm9iIDwtIHBiaW5vbSg5LCAxNSwgMC4yNSkgLSBwYmlub20oMiwgMTUsIDAuMjUpDQphY3R1YWxfcHJvYg0KDQojIChpaSkgQWN0dWFsIFEzIGZyb20gdGhlIGV4YWN0IGRpc3RyaWJ1dGlvbg0KYWN0dWFsX1EzIDwtIHFiaW5vbSgwLjc1LCAxNSwgMC4yNSkNCmFjdHVhbF9RMw0KDQpgYGANCiMgSU5DXzIwMjMtMQ0KIyMjIFBhcnQgMQ0KKGEpIENyZWF0ZSBhIHZlY3RvciB4IHRoYXQgc3RvcmVzIHRoZSBzZXF1ZW5jZSB7MS4xLCAxLjUsIDEuOSwgLi4uLCAxMTEuMX0NCmBgYHtyfQ0KeCA8LSBzZXEoMS4xLDExMS4xLCBieT0wLjQpDQpgYGANCihiKSBDcmVhdGUgYSB2ZWN0b3IgeSB3aGVyZSB5PWxvZ3gNCmBgYHtyfQ0KeSA8LSBsb2coeCkNCg0KYGBgDQooYykgRmluZCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBpbiB5DQpgYGB7cn0NCm4gPC0gbGVuZ3RoKHkpDQpuDQpgYGANCihkKSBDcmVhdGUgdmVjdG9yIHkxMiB3aXRoIGV2ZXJ5IDEydGggZWxlbWVudA0KYGBge3J9DQp5MTIgPC0geVtzZXEoMTIsIGxlbmd0aCh5KSwgYnkgPSAxMildDQpgYGANCihlKSBEaXNwbGF5IHRoZSBwb3NpdGlvbnMgKGluZGljZXMpIG9mIHRoZSBlbGVtZW50cyBpbiB2ZWN0b3IgWSB0aGF0IGxpZSBiZXR3ZWVuIDAuNSBhbmQgMi4NCmBgYHtyfQ0KaW5kaWNlcyA8LSB3aGljaCgoeSA+IDAuNSkgJiAoeSA8IDIpKQ0KcHJpbnQoaW5kaWNlcykNCmBgYA0KKGYpIFN1bSBvZiBlbGVtZW50cyBpbiB5IHRoYXQgYXJlIGJlbG93IDMNCmBgYHtyfQ0Kc3VtX2JlbG93XzMgPC0gc3VtKHlbeSA8IDNdKQ0Kc3VtX2JlbG93XzMNCmBgYA0KIyMjIFBhcnQgMiAocmVncmVzc2lvbiBjb250ZXh0KQ0KYGBge3J9DQonKGEpJw0KIyBTZXQgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5DQpzZXQuc2VlZCgxMjMpDQoNCiMgR2VuZXJhdGUgZGF0YQ0KbiA8LSAxMDAwDQoNCiMgWCB+IE4oMCwgNCkgKHZhcmlhbmNlID0gNCwgc28gc2QgPSAyKQ0KWCA8LSBybm9ybShuLCBtZWFuID0gMCwgc2QgPSBzcXJ0KDQpKQ0KDQojIM61IH4gTigxMCwgMikgKHZhcmlhbmNlID0gMiwgc28gc2QgPSBzcXJ0KDIpKQ0KIyBOb3RlOiBUaGlzIGVycm9yIHRlcm0gd2l0aCBtZWFuIDEwIHNlZW1zIHVudXN1YWwgZm9yIHJlZ3Jlc3Npb24NCmUgPC0gcm5vcm0obiwgbWVhbiA9IDAsIHNkID0gc3FydCgyKSkNCg0KIyBHZW5lcmF0ZSBZID0gMC41ICsgMC44KlggKyBlDQpZIDwtIDAuNSArIDAuOCAqIFggKyBlDQoNCiMgU3RvcmUgdGhlIHZhbHVlcyBvZiBYIGFzIHggYW5kIFkgYXMgeSwgYXMgcmVxdWVzdGVkDQp4IDwtIFgNCnkgPC0gWQ0KYGBgDQpgYGB7cn0NCicoYiknDQojIDEuIENyZWF0ZSBtYXRyaXggRDoNCiMgRmlyc3QgY29sdW1uOiBjb25zdGFudCAxICgxMDAwIHJvd3MpDQojIFNlY29uZCBjb2x1bW46IHZlY3RvciB4IGZyb20gcGFydCAoYSkNCkQgPC0gbWF0cml4KGMocmVwKDEsIG4pLCB4KSwgbmNvbCA9IDIpDQoNCiMgMi4gQ3JlYXRlIGNvbHVtbiBtYXRyaXggTSB1c2luZyB2ZWN0b3IgeSBmcm9tIHBhcnQgKGEpDQpNIDwtIG1hdHJpeCh5LCBuY29sID0gMSkNCmBgYA0KYGBge3J9DQonKEMpJw0KIyAxLiBDYWxjdWxhdGUgYiA9IChEXlQgRCleey0xfSBEXlQgTQ0KRF90cmFuc3Bvc2UgPC0gdChEKQ0KRF90cmFuc3Bvc2VfRCA8LSBEX3RyYW5zcG9zZSAlKiUgRA0KRF90cmFuc3Bvc2VfTSA8LSBEX3RyYW5zcG9zZSAlKiUgTQ0KDQojIENhbGN1bGF0ZSBpbnZlcnNlIGFuZCBiDQpEX3RyYW5zcG9zZV9EX2ludiA8LSBzb2x2ZShEX3RyYW5zcG9zZV9EKQ0KYiA8LSBEX3RyYW5zcG9zZV9EX2ludiAlKiUgRF90cmFuc3Bvc2VfTQ0KcHJpbnQoYikNCiMgMi4gVHJ1ZSBwYXJhbWV0ZXIgdmVjdG9yIEIgZnJvbSBwYXJ0IChhKQ0KQiA8LSBjKDAuNSwgMC44KQ0KcHJpbnQoQikNCg0KIyAzLiBDYWxjdWxhdGUgYWJzb2x1dGUgZGlmZmVyZW5jZXMgfGIgLSBCfA0KYWJzX2RpZmZlcmVuY2UgPC0gYWJzKGItQikNCg0KY2F0KCJBYnNvbHV0ZSBkaWZmZXJlbmNlczpcbiIpDQpwcmludChhYnNfZGlmZmVyZW5jZSkNCmBgYA0KDQoNCg0KDQoNCg==