Write a function to solve a 2x2 system using Cramer’s rule.
solver2by2 <- function(A,b){
A_inv <- (1/(A[1,1]*A[2,2]-A[2,1]*A[1,2]))* matrix(c(A[2,2],-A[1,2],-A[2,1],A[1,1]), byrow= TRUE, nrow=2)
sol <- A_inv %*% b
cat("x=",sol[1],"\ny=",sol[2])
}
A <- matrix(c(2,3,4,-1), byrow=TRUE, nrow=2)
b<- matrix(c(8,6), nrow=2)
solver2by2(A,b)
x= 1.857143
y= 1.428571
# built in
solve(A,b)
[,1]
[1,] 1.857143
[2,] 1.428571
Write a function to find the determinant of a 2x2 matrix.
det2by2 <- function(A){
detA22<- (A[1,1]*A[2,2]-A[2,1]*A[1,2])
cat("Determinant=",detA22)
return(detA22)
}
det2by2(A)
Determinant= -14[1] -14
# built in
det(A)
[1] -14
determinant of a 3x3 matrix
det3by3 <- function(A){
detA33 <- A[1,1]*(A[2,2]*A[3,3]-A[2,3]*A[3,2])-A[2,1]*(A[1,2]*A[3,3]-A[1,3]*A[3,2])+A[3,1]*(A[1,2]*A[2,3]-A[1,3]*A[2,2])
cat("Determinant=",detA33)
}
B <- rbind(cbind(A,b),c(b,1))
det3by3(B)
Determinant= 314
Write a function to check if a 2x2 matrix is invertible.
inv_checker <- function(A){
if (det2by2(A)==0){
print("Inverse Not Possible.")
} else{
print("Inverse Possible.")
}
}
inv_checker(A)
Determinant= -14[1] "Inverse Possible."
Write a function to scale a row in a matrix by a constant.
row_scaler <- function(A,i,c){
A[i]<-A[i]*c
print(A)
}
row_scaler(A,1,5)
[,1] [,2]
[1,] 10 3
[2,] 4 -1
Write a function to add a multiple of one row to another row.
row_operation <- function(A,row1,row2,c){
A[row1,]<-A[row1]+A[row2,]*c
print(A)
}
row_operation(A,1,2,4)
[,1] [,2]
[1,] 18 -2
[2,] 4 -1
Write a function to convert a 3x3 augmented matrix to upper
triangular form.
to_upper_tri <- function(A) {
# Forward elimination
# Step 1: Eliminate x from row 2
if (A[1,1] != 0) {
factor <- A[2,1] / A[1,1]
A[2,] <- A[2,] - factor * A[1,]
}
# Step 2: Eliminate x from row 3
if (A[1,1] != 0) {
factor <- A[3,1] / A[1,1]
A[3,] <- A[3,] - factor * A[1,]
}
# Step 3: Eliminate y from row 3
if (A[2,2] != 0) {
factor <- A[3,2] / A[2,2]
A[3,] <- A[3,] - factor * A[2,]
}
return(A)
}
B <- matrix(c(
2, 1, -1, 8, # 2x + y - z = 8
4, -2, 1, 1, # 4x - 2y + z = 1
-2, 1, 2, 5 # -2x + y + 2z = 5
), nrow = 3, byrow = TRUE)
C <- to_upper_tri(B)
print(C)
[,1] [,2] [,3] [,4]
[1,] 2 1 -1.0 8.0
[2,] 0 -4 3.0 -15.0
[3,] 0 0 2.5 5.5
Write a function to solve a 3x3 system using Gaussian
elimination.
solve_3x3 <- function(A, b) {
# Create augmented matrix
aug <- cbind(A, b)
# Forward elimination
# Step 1: Eliminate x1 from rows 2 and 3
if (aug[1,1] != 0) {
# Row 2
factor <- aug[2,1] / aug[1,1]
aug[2,] <- aug[2,] - factor * aug[1,]
# Row 3
factor <- aug[3,1] / aug[1,1]
aug[3,] <- aug[3,] - factor * aug[1,]
}
# Step 2: Eliminate x2 from row 3
if (aug[2,2] != 0) {
factor <- aug[3,2] / aug[2,2]
aug[3,] <- aug[3,] - factor * aug[2,]
}
# Back substitution
x <- numeric(3)
x[3] <- aug[3,4] / aug[3,3]
x[2] <- (aug[2,4] - aug[2,3] * x[3]) / aug[2,2]
x[1] <- (aug[1,4] - aug[1,2] * x[2] - aug[1,3] * x[3]) / aug[1,1]
return(x)
}
A <- matrix(c(2, 1, -1,
0, 3, 1,
0, 0, 4), nrow = 3, byrow = TRUE)
b <- c(3, 9, 12)
solution <- solve_3x3(A, b)
print(solution) # Output: 2 2 3
[1] 2 2 3
Write a function to check if a 2x2 system has a unique
solution.
unique_sol_checker<- function(A){
D <- A[1,1]*A[2,2]-A[2,1]*A[1,2]
if (D!=0){
print("Unique Solution")
}
else{
print("Not unique solution")
}
}
A <- matrix(c(2,3,4,-1), byrow=TRUE, nrow=2)
unique_sol_checker(A)
[1] "Unique Solution"
Write a function to check if a 3x3 system is inconsistent using row
echelon form.
is_inconsistent <- function(A, b) {
aug <- cbind(A, b)
# Forward elimination to row echelon form
for (col in 1:3) {
# Find non-zero pivot
pivot_row <- which(aug[col:3, col] != 0)[1]
if (!is.na(pivot_row)) {
pivot_row <- pivot_row + col - 1
if (pivot_row != col) {
# Swap rows
aug[c(col, pivot_row),] <- aug[c(pivot_row, col),]
}
# Eliminate below
if (col < 3) {
for (row in (col+1):3) {
factor <- aug[row, col] / aug[col, col]
aug[row,] <- aug[row,] - factor * aug[col,]
}
}
}
}
# Check for inconsistency: row of zeros in A with non-zero in b
for (row in 1:3) {
if (all(aug[row, 1:3] == 0) && aug[row, 4] != 0) {
return(TRUE) # Inconsistent system
}
}
return(FALSE) # Consistent system
}
# Consistent system
A1 <- matrix(c(1, 2, 3,
0, 1, 2,
0, 0, 1), nrow = 3, byrow = TRUE)
b1 <- c(14, 8, 3)
print(is_inconsistent(A1, b1)) # FALSE
[1] FALSE
# Inconsistent system: 0x + 0y + 0z = 5
A2 <- matrix(c(1, 2, 3,
0, 0, 0,
0, 0, 1), nrow = 3, byrow = TRUE)
b2 <- c(14, 5, 3)
print(is_inconsistent(A2, b2)) # TRUE
[1] TRUE
# Another inconsistent example
A3 <- matrix(c(1, 1, 1,
2, 2, 2,
1, 0, 1), nrow = 3, byrow = TRUE)
b3 <- c(3, 7, 2)
print(is_inconsistent(A3, b3)) # TRUE (rows 1 and 2 are multiples but give different b)
[1] TRUE
Write a function to find the inverse of a 2x2 matrix.
inverse_2x2 <- function(A) {
det_A <- A[1,1] * A[2,2] - A[1,2] * A[2,1]
if (abs(det_A) < 1e-10) {
return(NULL) # or return(matrix(NA, nrow=2, ncol=2))
}
inv <- matrix(c(A[2,2], -A[2,1], -A[1,2], A[1,1]), nrow=2, byrow=TRUE) / det_A
return(inv)
}
A <- matrix(c(4, 7, 2, 6), nrow=2)
inv_A <- inverse_2x2(A)
print(inv_A)
[,1] [,2]
[1,] 0.6 -0.7
[2,] -0.2 0.4
Write a function to multiply a matrix by a vector (Ax).
matxvec<- function(A,b){
return(A%*%b)
}
A1 <- matrix(c(1, 2, 3,
0, 1, 2,
0, 0, 1), nrow = 3, byrow = TRUE)
b1 <- c(14, 8, 3)
matxvec(A1,b1)
[,1]
[1,] 39
[2,] 14
[3,] 3
Write a function to verify a solution x satisfies Ax = b for given A
and b.
sol_checker <- function(A,b,x){
if (all(abs(A %*% x - b) < 1e-10)){
print("Yes")
} else{
print("Wrong")
}
}
A <- matrix(c(2, 1, -1,
0, 3, 1,
0, 0, 4), nrow = 3, byrow = TRUE)
b <- c(3, 9, 12)
x <- c(2, 2, 3) # Correct solution
sol_checker(A,b,x)
[1] "Yes"
Write a function to find the trace of a square matrix.
trace <- function(A){
val = 0
for (i in 1:nrow(A)){
for (j in 1:ncol(A)){
if (i==j){
val = val + A[i,i]
}
}
}
return(val)
}
ans <- trace(A)
print(ans)
[1] 9
Write a function to create a diagonal matrix from a vector.
vec_diag_mat <- function(b){
n<-length(b)
A <- matrix(0, nrow=n, ncol=n)
for (i in 1:n){
A[i,i]<-b[i]
}
print(A)
}
vec_diag_mat(b)
[,1] [,2] [,3]
[1,] 3 0 0
[2,] 0 9 0
[3,] 0 0 12
Write a function to create an identity matrix of size n.
In <- function(n){
A<-matrix(0,nrow=n,ncol=n)
for (i in 1:n){
A[i,i]<-1
}
return(A)
}
A<-In(5)
A
[,1] [,2] [,3] [,4] [,5]
[1,] 1 0 0 0 0
[2,] 0 1 0 0 0
[3,] 0 0 1 0 0
[4,] 0 0 0 1 0
[5,] 0 0 0 0 1
Write a function to compute the sum of each column in a matrix.
col_sum <- function(A){
colsum<-c()
for (i in 1:ncol(A)){
colsum<-append(colsum,sum(A[,i]))
}
colsum
}
col_sum(A)
[1] 1 1 1 1 1
Write a function to compute the mean of each row in a matrix.
rowmean <- function(A){
x<-c()
for (i in 1:nrow(A)){
x<-append(x,mean(A[i,]))
}
return(x)
}
x<-rowmean(A)
print(x)
[1] 0.2 0.2 0.2 0.2 0.2
Write a function to check if two matrices are equal.
equal_check <- function(A,B){
for (i in 1:nrow(A)){
for (j in 1:ncol(A)){
if (A[i,j]!=B[i,j]){
return (FALSE)
}
}
}
return (TRUE)
}
A<-matrix(c(1,2,3,4), nrow=2)
B<-matrix(c(1,2,3,4.000000001), nrow=2)
equal_check(A,B)
[1] FALSE
Write a function to find the transpose of a matrix.
trans<-function(A){
B<-matrix(NA,nrow=nrow(A),ncol=ncol(A))
for (i in 1:nrow(A)){
for (j in 1:ncol(B)){
B[j,i]<-A[i,j]
}
}
return(B)
}
ans<-trans(A)
print(ans)
[,1] [,2]
[1,] 1 2
[2,] 3 4
A
[,1] [,2]
[1,] 1 3
[2,] 2 4
A
[,1] [,2]
[1,] 1 3
[2,] 2 4
solve(A)
[,1] [,2]
[1,] -2 1.5
[2,] 1 -0.5
Write a function to multiply two 2x2 matrices.
mul2by2 <- function(A,B){
C <- matrix(NA, nrow=2, ncol=2)
C[1,1] <- A[1,1]*B[1,1] + A[1,2]*B[2,1]
C[1,2] <- A[1,1]*B[1,2] + A[1,2]*B[2,2]
C[2,1] <- A[2,1]*B[1,1] + A[2,2]*B[2,1]
C[2,2] <- A[2,1]*B[1,2] + A[2,2]*B[2,2]
return(C)
}
A<-matrix(c(1,2,7,4),nrow=2)
B<-matrix(c(2,3,4,10),nrow=2)
mul2by2(A,B)
[,1] [,2]
[1,] 23 74
[2,] 16 48
Write a function to multiply two matrices of compatible
dimensions.
#2*3
#3*2
matrix_multiply <- function(A, B) {
if (ncol(A) != nrow(B)) {
stop("Incompatible dimensions: ncol(A) must equal nrow(B)")
}
result <- matrix(0, nrow = nrow(A), ncol = ncol(B))
for (i in 1:nrow(A)) {
for (j in 1:ncol(B)) {
result[i, j] <- sum(A[i, ] * B[, j])
}
}
result
}
ans=matrix_multiply(A,B)
print(ans)
[,1] [,2]
[1,] 23 74
[2,] 16 48
Write a function to replace a row in a matrix with a vector.
row_replace <- function(A,r,vect){
A[r,]<-vect
return(A)
}
ans<-row_replace(A,2,c(0,0))
print(ans)
[,1] [,2]
[1,] 1 7
[2,] 0 0
Write a function to find the maximum element in a matrix.
max_ele<- function(A){
maxi<-A[1,1]
for (i in 1:nrow(A)){
for (j in 1:ncol(A)){
if (A[i,j]>maxi){
maxi<-A[i,j]
}
}
}
return(maxi)
}
ans<-max_ele(A)
print(ans)
[1] 7
Write a function to compute row sums of a matrix.
A
[,1] [,2]
[1,] 1 7
[2,] 2 4
row_sums<-function(A){
result<-numeric(nrow(A))
for (i in 1:nrow(A)){
result[i]<-sum(A[i,])
}
return(result)
}
ans<-row_sums(A)
print(ans)
[1] 8 6
Write a function to check if a matrix is upper triangular.
uptrian <- function(A){
for (i in 1:nrow(A)){
for (j in 1:ncol(A)){
if (i>j){
A[i,j]!=0
return(FALSE)
}
}
}
return(TRUE)
}
ans<-uptrian(A)
print(ans)
[1] FALSE
A<-c()
A<-append(A,2)
A<-append(A,4)
class(A)
[1] "numeric"
Write a function to check if a matrix is scalar (multiple of
identity).
scaler_check <- function(A){
for (i in 1:nrow(A)){
for (j in 1:ncol(A)){
if(i != j & A[i,j]!=0){
return(FALSE)
}
else if(i==j & A[i,j]!=A[1,1]){
return(FALSE)
}
}
}
return(TRUE)
}
A<-matrix(c(1,2,7,4),nrow=2)
B<-matrix(c(1,0,0,1), nrow=2)
scaler_check(B)
[1] TRUE
Write a function to compute the row-wise maximum of a matrix.
rowmax<-function(A){
maxs<-numeric(nrow(A))
for (i in 1:nrow(A)){
max=A[i,1]
for (j in 1:ncol(A)){
if (A[i,j]>max){
max<-A[i,j]
}
}
maxs[i]<-max
}
return(maxs)
}
print(rowmax(A))
[1] 7 4
A
[,1] [,2]
[1,] 1 7
[2,] 2 4
Write a function to compute cumulative sum of each row.
cumsumrow <- function(A){
mat<-matrix(NA,nrow=nrow(A),ncol=ncol(A))
for (i in 1:nrow(A)){
cumsum<-numeric(ncol(A))
cumsum[1]<-A[i,1]
for (j in 2:ncol(A)){
cumsum[j]<-A[i,j]+cumsum[j-1]
}
mat[i,]<-cumsum
}
return(mat)
}
print(cumsumrow(A))
[,1] [,2]
[1,] 1 8
[2,] 2 6
A
[,1] [,2]
[1,] 1 7
[2,] 2 4
25. Cumulative product
cumprod_vec <- function(a) { result <- numeric(length(a))
result[1] <- a[1] for (i in 2:length(a)) { result[i] <-
result[i-1] * a[i] } result }
vecx<-c(10,20,188,348)
sum(vecx^2)
[1] 156948
A<-c(1,2,3,4)
B<-c(2,4,6,8)
all(A/B==A[1]/B[1])
[1] TRUE
# 21. Bubble sort
bubble_sort <- function(a) {
n <- length(a)
for (i in 1:(n-1)) {
for (j in 1:(n-i)) {
if (a[j] > a[j+1]) {
temp <- a[j]
a[j] <- a[j+1]
a[j+1] <- temp
}
}
}
a
View(solve)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gc29sdmUgYSAyeDIgc3lzdGVtIHVzaW5nIENyYW1lcidzIHJ1bGUuDQpgYGB7cn0NCnNvbHZlcjJieTIgPC0gZnVuY3Rpb24oQSxiKXsNCiAgQV9pbnYgPC0gKDEvKEFbMSwxXSpBWzIsMl0tQVsyLDFdKkFbMSwyXSkpKiBtYXRyaXgoYyhBWzIsMl0sLUFbMSwyXSwtQVsyLDFdLEFbMSwxXSksIGJ5cm93PSBUUlVFLCBucm93PTIpDQogIHNvbCA8LSBBX2ludiAlKiUgIGINCiAgY2F0KCJ4PSIsc29sWzFdLCJcbnk9Iixzb2xbMl0pDQp9DQpBIDwtIG1hdHJpeChjKDIsMyw0LC0xKSwgYnlyb3c9VFJVRSwgbnJvdz0yKQ0KYjwtIG1hdHJpeChjKDgsNiksIG5yb3c9MikNCnNvbHZlcjJieTIoQSxiKQ0KDQojIGJ1aWx0IGluDQpzb2x2ZShBLGIpDQpgYGANCiMjIyBXcml0ZSBhIGZ1bmN0aW9uIHRvIGZpbmQgdGhlIGRldGVybWluYW50IG9mIGEgMngyIG1hdHJpeC4NCmBgYHtyfQ0KZGV0MmJ5MiA8LSBmdW5jdGlvbihBKXsNCiAgZGV0QTIyPC0gKEFbMSwxXSpBWzIsMl0tQVsyLDFdKkFbMSwyXSkNCiAgY2F0KCJEZXRlcm1pbmFudD0iLGRldEEyMikNCiAgcmV0dXJuKGRldEEyMikNCn0NCmRldDJieTIoQSkNCiMgYnVpbHQgaW4NCmRldChBKQ0KYGBgDQojIyMgZGV0ZXJtaW5hbnQgb2YgYSAzeDMgbWF0cml4DQpgYGB7cn0NCmRldDNieTMgPC0gZnVuY3Rpb24oQSl7DQogIGRldEEzMyA8LSBBWzEsMV0qKEFbMiwyXSpBWzMsM10tQVsyLDNdKkFbMywyXSktQVsyLDFdKihBWzEsMl0qQVszLDNdLUFbMSwzXSpBWzMsMl0pK0FbMywxXSooQVsxLDJdKkFbMiwzXS1BWzEsM10qQVsyLDJdKQ0KICBjYXQoIkRldGVybWluYW50PSIsZGV0QTMzKQ0KfQ0KQiA8LSByYmluZChjYmluZChBLGIpLGMoYiwxKSkNCmRldDNieTMoQikNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gY2hlY2sgaWYgYSAyeDIgbWF0cml4IGlzIGludmVydGlibGUuDQpgYGB7cn0NCmludl9jaGVja2VyIDwtIGZ1bmN0aW9uKEEpew0KICBpZiAoZGV0MmJ5MihBKT09MCl7DQogICAgcHJpbnQoIkludmVyc2UgTm90IFBvc3NpYmxlLiIpDQogIH0gZWxzZXsNCiAgICBwcmludCgiSW52ZXJzZSBQb3NzaWJsZS4iKQ0KICB9DQp9DQppbnZfY2hlY2tlcihBKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBmb3JtIGFuIGF1Z21lbnRlZCBtYXRyaXggZnJvbSBjb2VmZmljaWVudCBtYXRyaXggQSBhbmQgdmVjdG9yIGIuDQpgYGB7cn0NCmNiaW5kKEEsYikNCmF1Z19tYXQgPC0gZnVuY3Rpb24oQSxiKXsNCiAgYXVnIDwtIGNiaW5kKEEsYikNCiAgY2F0KCJBdWdtZW50ZWQgTWF0cml4OlxuIikNCiAgcmV0dXJuKGF1ZykNCn0NCmF1Z19BPC1hdWdfbWF0KEEsYikNCnByaW50KGF1Z19BKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBwZXJmb3JtIHJvdyBzd2FwcGluZyBpbiBhbiBhdWdtZW50ZWQgbWF0cml4Lg0KYGBge3J9DQpzd2FwX3Jvd3MgPC0gZnVuY3Rpb24oQSwgaSwgaikgew0KICB0ZW1wIDwtIEFbaSwgXQ0KICBBW2ksIF0gPC0gQVtqLCBdDQogIEFbaiwgXSA8LSB0ZW1wDQogIHByaW50KEEpDQogIHJldHVybihBKQ0KfQ0KIyBTd2FwIHJvd3MgMSBhbmQgMg0KQV9zd2FwcGVkIDwtIHN3YXBfcm93cyhBLCAxLCAyKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBzY2FsZSBhIHJvdyBpbiBhIG1hdHJpeCBieSBhIGNvbnN0YW50Lg0KYGBge3J9DQpyb3dfc2NhbGVyIDwtIGZ1bmN0aW9uKEEsaSxjKXsNCiAgQVtpXTwtQVtpXSpjDQogIHByaW50KEEpDQp9DQpyb3dfc2NhbGVyKEEsMSw1KQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBhZGQgYSBtdWx0aXBsZSBvZiBvbmUgcm93IHRvIGFub3RoZXIgcm93Lg0KYGBge3J9DQpyb3dfb3BlcmF0aW9uIDwtIGZ1bmN0aW9uKEEscm93MSxyb3cyLGMpew0KICBBW3JvdzEsXTwtQVtyb3cxXStBW3JvdzIsXSpjDQogIHByaW50KEEpDQp9DQoNCnJvd19vcGVyYXRpb24oQSwxLDIsNCkNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gY29udmVydCBhIDN4MyBhdWdtZW50ZWQgbWF0cml4IHRvIHVwcGVyIHRyaWFuZ3VsYXIgZm9ybS4NCmBgYHtyfQ0KdG9fdXBwZXJfdHJpIDwtIGZ1bmN0aW9uKEEpIHsNCiAgIyBGb3J3YXJkIGVsaW1pbmF0aW9uDQogICMgU3RlcCAxOiBFbGltaW5hdGUgeCBmcm9tIHJvdyAyDQogIGlmIChBWzEsMV0gIT0gMCkgew0KICAgIGZhY3RvciA8LSBBWzIsMV0gLyBBWzEsMV0NCiAgICBBWzIsXSA8LSBBWzIsXSAtIGZhY3RvciAqIEFbMSxdDQogIH0NCiAgDQogICMgU3RlcCAyOiBFbGltaW5hdGUgeCBmcm9tIHJvdyAzDQogIGlmIChBWzEsMV0gIT0gMCkgew0KICAgIGZhY3RvciA8LSBBWzMsMV0gLyBBWzEsMV0NCiAgICBBWzMsXSA8LSBBWzMsXSAtIGZhY3RvciAqIEFbMSxdDQogIH0NCiAgDQogICMgU3RlcCAzOiBFbGltaW5hdGUgeSBmcm9tIHJvdyAzDQogIGlmIChBWzIsMl0gIT0gMCkgew0KICAgIGZhY3RvciA8LSBBWzMsMl0gLyBBWzIsMl0NCiAgICBBWzMsXSA8LSBBWzMsXSAtIGZhY3RvciAqIEFbMixdDQogIH0NCiAgDQogIHJldHVybihBKQ0KfQ0KDQpCIDwtIG1hdHJpeChjKA0KICAyLCAgMSwgLTEsICA4LCAgIyAyeCArIHkgLSB6ID0gOA0KICA0LCAtMiwgIDEsICAxLCAgIyA0eCAtIDJ5ICsgeiA9IDENCiAtMiwgIDEsICAyLCAgNSAgICMgLTJ4ICsgeSArIDJ6ID0gNQ0KKSwgbnJvdyA9IDMsIGJ5cm93ID0gVFJVRSkNCg0KDQoNCkMgPC0gdG9fdXBwZXJfdHJpKEIpDQpwcmludChDKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBwZXJmb3JtIGJhY2sgc3Vic3RpdHV0aW9uIG9uIGFuIHVwcGVyIHRyaWFuZ3VsYXIgc3lzdGVtLg0KYGBge3J9DQpiYWNrX3N1YnN0aXR1dGlvbiA8LSBmdW5jdGlvbihVKSB7DQogIG4gPC0gbnJvdyhVKQ0KICB4IDwtIG51bWVyaWMobikNCiAgDQogIGZvciAoaSBpbiBuOjEpIHsNCiAgICAjIFN1bSBvZiAoY29lZmZpY2llbnQgw5cgYWxyZWFkeS1zb2x2ZWQtdmFyaWFibGUpDQogICAgc3VtX2NvZWZmX3RpbWVzX2tub3duIDwtIDANCiAgICBpZiAoaSA8IG4pIHsNCiAgICAgIHN1bV9jb2VmZl90aW1lc19rbm93biA8LSBzdW0oVVtpLCAoaSsxKTpuXSAqIHhbKGkrMSk6bl0pDQogICAgfQ0KICAgIHhbaV0gPC0gKFVbaSwgbisxXSAtIHN1bV9jb2VmZl90aW1lc19rbm93bikgLyBVW2ksIGldDQogIH0NCiAgDQogIHJldHVybih4KQ0KfQ0KDQpEPC1iYWNrX3N1YnN0aXR1dGlvbihDKQ0KcHJpbnQoRCkNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gc29sdmUgYSAzeDMgc3lzdGVtIHVzaW5nIEdhdXNzaWFuIGVsaW1pbmF0aW9uLg0KYGBge3J9DQpzb2x2ZV8zeDMgPC0gZnVuY3Rpb24oQSwgYikgew0KICAjIENyZWF0ZSBhdWdtZW50ZWQgbWF0cml4DQogIGF1ZyA8LSBjYmluZChBLCBiKQ0KICANCiAgIyBGb3J3YXJkIGVsaW1pbmF0aW9uDQogICMgU3RlcCAxOiBFbGltaW5hdGUgeDEgZnJvbSByb3dzIDIgYW5kIDMNCiAgaWYgKGF1Z1sxLDFdICE9IDApIHsNCiAgICAjIFJvdyAyDQogICAgZmFjdG9yIDwtIGF1Z1syLDFdIC8gYXVnWzEsMV0NCiAgICBhdWdbMixdIDwtIGF1Z1syLF0gLSBmYWN0b3IgKiBhdWdbMSxdDQogICAgDQogICAgIyBSb3cgMw0KICAgIGZhY3RvciA8LSBhdWdbMywxXSAvIGF1Z1sxLDFdDQogICAgYXVnWzMsXSA8LSBhdWdbMyxdIC0gZmFjdG9yICogYXVnWzEsXQ0KICB9DQogIA0KICAjIFN0ZXAgMjogRWxpbWluYXRlIHgyIGZyb20gcm93IDMNCiAgaWYgKGF1Z1syLDJdICE9IDApIHsNCiAgICBmYWN0b3IgPC0gYXVnWzMsMl0gLyBhdWdbMiwyXQ0KICAgIGF1Z1szLF0gPC0gYXVnWzMsXSAtIGZhY3RvciAqIGF1Z1syLF0NCiAgfQ0KICANCiAgIyBCYWNrIHN1YnN0aXR1dGlvbg0KICB4IDwtIG51bWVyaWMoMykNCiAgeFszXSA8LSBhdWdbMyw0XSAvIGF1Z1szLDNdDQogIHhbMl0gPC0gKGF1Z1syLDRdIC0gYXVnWzIsM10gKiB4WzNdKSAvIGF1Z1syLDJdDQogIHhbMV0gPC0gKGF1Z1sxLDRdIC0gYXVnWzEsMl0gKiB4WzJdIC0gYXVnWzEsM10gKiB4WzNdKSAvIGF1Z1sxLDFdDQogIA0KICByZXR1cm4oeCkNCn0NCg0KQSA8LSBtYXRyaXgoYygyLCAxLCAtMSwNCiAgICAgICAgICAgICAgMCwgMywgMSwNCiAgICAgICAgICAgICAgMCwgMCwgNCksIG5yb3cgPSAzLCBieXJvdyA9IFRSVUUpDQpiIDwtIGMoMywgOSwgMTIpDQoNCnNvbHV0aW9uIDwtIHNvbHZlXzN4MyhBLCBiKQ0KcHJpbnQoc29sdXRpb24pICAjIE91dHB1dDogMiAyIDMNCg0KDQpgYGANCiMjIyBXcml0ZSBhIGZ1bmN0aW9uIHRvIGNoZWNrIGlmIGEgMngyIHN5c3RlbSBoYXMgYSB1bmlxdWUgc29sdXRpb24uDQpgYGB7cn0NCnVuaXF1ZV9zb2xfY2hlY2tlcjwtIGZ1bmN0aW9uKEEpew0KICBEIDwtIEFbMSwxXSpBWzIsMl0tQVsyLDFdKkFbMSwyXQ0KICBpZiAoRCE9MCl7DQogICAgcHJpbnQoIlVuaXF1ZSBTb2x1dGlvbiIpDQogIH0NCiAgZWxzZXsNCiAgICBwcmludCgiTm90IHVuaXF1ZSBzb2x1dGlvbiIpDQogIH0NCn0NCg0KQSA8LSBtYXRyaXgoYygyLDMsNCwtMSksIGJ5cm93PVRSVUUsIG5yb3c9MikNCnVuaXF1ZV9zb2xfY2hlY2tlcihBKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBjaGVjayBpZiBhIDN4MyBzeXN0ZW0gaXMgaW5jb25zaXN0ZW50IHVzaW5nIHJvdyBlY2hlbG9uIGZvcm0uDQpgYGB7cn0NCmlzX2luY29uc2lzdGVudCA8LSBmdW5jdGlvbihBLCBiKSB7DQogIGF1ZyA8LSBjYmluZChBLCBiKQ0KICANCiAgIyBGb3J3YXJkIGVsaW1pbmF0aW9uIHRvIHJvdyBlY2hlbG9uIGZvcm0NCiAgZm9yIChjb2wgaW4gMTozKSB7DQogICAgIyBGaW5kIG5vbi16ZXJvIHBpdm90DQogICAgcGl2b3Rfcm93IDwtIHdoaWNoKGF1Z1tjb2w6MywgY29sXSAhPSAwKVsxXQ0KICAgIGlmICghaXMubmEocGl2b3Rfcm93KSkgew0KICAgICAgcGl2b3Rfcm93IDwtIHBpdm90X3JvdyArIGNvbCAtIDENCiAgICAgIGlmIChwaXZvdF9yb3cgIT0gY29sKSB7DQogICAgICAgICMgU3dhcCByb3dzDQogICAgICAgIGF1Z1tjKGNvbCwgcGl2b3Rfcm93KSxdIDwtIGF1Z1tjKHBpdm90X3JvdywgY29sKSxdDQogICAgICB9DQogICAgICANCiAgICAgICMgRWxpbWluYXRlIGJlbG93DQogICAgICBpZiAoY29sIDwgMykgew0KICAgICAgICBmb3IgKHJvdyBpbiAoY29sKzEpOjMpIHsNCiAgICAgICAgICBmYWN0b3IgPC0gYXVnW3JvdywgY29sXSAvIGF1Z1tjb2wsIGNvbF0NCiAgICAgICAgICBhdWdbcm93LF0gPC0gYXVnW3JvdyxdIC0gZmFjdG9yICogYXVnW2NvbCxdDQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0NCiAgDQogICMgQ2hlY2sgZm9yIGluY29uc2lzdGVuY3k6IHJvdyBvZiB6ZXJvcyBpbiBBIHdpdGggbm9uLXplcm8gaW4gYg0KICBmb3IgKHJvdyBpbiAxOjMpIHsNCiAgICBpZiAoYWxsKGF1Z1tyb3csIDE6M10gPT0gMCkgJiYgYXVnW3JvdywgNF0gIT0gMCkgew0KICAgICAgcmV0dXJuKFRSVUUpICAjIEluY29uc2lzdGVudCBzeXN0ZW0NCiAgICB9DQogIH0NCiAgDQogIHJldHVybihGQUxTRSkgICMgQ29uc2lzdGVudCBzeXN0ZW0NCn0NCg0KDQojIENvbnNpc3RlbnQgc3lzdGVtDQpBMSA8LSBtYXRyaXgoYygxLCAyLCAzLA0KICAgICAgICAgICAgICAgMCwgMSwgMiwNCiAgICAgICAgICAgICAgIDAsIDAsIDEpLCBucm93ID0gMywgYnlyb3cgPSBUUlVFKQ0KYjEgPC0gYygxNCwgOCwgMykNCnByaW50KGlzX2luY29uc2lzdGVudChBMSwgYjEpKSAgIyBGQUxTRQ0KDQojIEluY29uc2lzdGVudCBzeXN0ZW06IDB4ICsgMHkgKyAweiA9IDUNCkEyIDwtIG1hdHJpeChjKDEsIDIsIDMsDQogICAgICAgICAgICAgICAwLCAwLCAwLA0KICAgICAgICAgICAgICAgMCwgMCwgMSksIG5yb3cgPSAzLCBieXJvdyA9IFRSVUUpDQpiMiA8LSBjKDE0LCA1LCAzKQ0KcHJpbnQoaXNfaW5jb25zaXN0ZW50KEEyLCBiMikpICAjIFRSVUUNCg0KIyBBbm90aGVyIGluY29uc2lzdGVudCBleGFtcGxlDQpBMyA8LSBtYXRyaXgoYygxLCAxLCAxLA0KICAgICAgICAgICAgICAgMiwgMiwgMiwNCiAgICAgICAgICAgICAgIDEsIDAsIDEpLCBucm93ID0gMywgYnlyb3cgPSBUUlVFKQ0KYjMgPC0gYygzLCA3LCAyKQ0KcHJpbnQoaXNfaW5jb25zaXN0ZW50KEEzLCBiMykpICAjIFRSVUUgKHJvd3MgMSBhbmQgMiBhcmUgbXVsdGlwbGVzIGJ1dCBnaXZlIGRpZmZlcmVudCBiKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBmaW5kIHRoZSBpbnZlcnNlIG9mIGEgMngyIG1hdHJpeC4NCmBgYHtyfQ0KaW52ZXJzZV8yeDIgPC0gZnVuY3Rpb24oQSkgew0KICBkZXRfQSA8LSBBWzEsMV0gKiBBWzIsMl0gLSBBWzEsMl0gKiBBWzIsMV0NCiAgDQogIGlmIChhYnMoZGV0X0EpIDwgMWUtMTApIHsNCiAgICByZXR1cm4oTlVMTCkgICMgb3IgcmV0dXJuKG1hdHJpeChOQSwgbnJvdz0yLCBuY29sPTIpKQ0KICB9DQogIA0KICBpbnYgPC0gbWF0cml4KGMoQVsyLDJdLCAtQVsyLDFdLCAtQVsxLDJdLCBBWzEsMV0pLCBucm93PTIsIGJ5cm93PVRSVUUpIC8gZGV0X0ENCiAgcmV0dXJuKGludikNCn0NCg0KQSA8LSBtYXRyaXgoYyg0LCA3LCAyLCA2KSwgbnJvdz0yKQ0KaW52X0EgPC0gaW52ZXJzZV8yeDIoQSkNCnByaW50KGludl9BKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBtdWx0aXBseSBhIG1hdHJpeCBieSBhIHZlY3RvciAoQXgpLg0KYGBge3J9DQptYXR4dmVjPC0gZnVuY3Rpb24oQSxiKXsNCiAgcmV0dXJuKEElKiViKQ0KfQ0KDQpBMSA8LSBtYXRyaXgoYygxLCAyLCAzLA0KICAgICAgICAgICAgICAgMCwgMSwgMiwNCiAgICAgICAgICAgICAgIDAsIDAsIDEpLCBucm93ID0gMywgYnlyb3cgPSBUUlVFKQ0KYjEgPC0gYygxNCwgOCwgMykNCm1hdHh2ZWMoQTEsYjEpDQpgYGANCiMjIyBXcml0ZSBhIGZ1bmN0aW9uIHRvIHZlcmlmeSBhIHNvbHV0aW9uIHggc2F0aXNmaWVzIEF4ID0gYiBmb3IgZ2l2ZW4gQSBhbmQgYi4NCmBgYHtyfQ0Kc29sX2NoZWNrZXIgPC0gZnVuY3Rpb24oQSxiLHgpew0KICBpZiAoYWxsKGFicyhBICUqJSB4IC0gYikgPCAxZS0xMCkpew0KICAgIHByaW50KCJZZXMiKQ0KICB9IGVsc2V7DQogICAgcHJpbnQoIldyb25nIikNCiAgfQ0KfQ0KDQoNCkEgPC0gbWF0cml4KGMoMiwgMSwgLTEsDQogICAgICAgICAgICAgIDAsIDMsIDEsDQogICAgICAgICAgICAgIDAsIDAsIDQpLCBucm93ID0gMywgYnlyb3cgPSBUUlVFKQ0KYiA8LSBjKDMsIDksIDEyKQ0KeCA8LSBjKDIsIDIsIDMpICAjIENvcnJlY3Qgc29sdXRpb24NCnNvbF9jaGVja2VyKEEsYix4KQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBmaW5kIHRoZSB0cmFjZSBvZiBhIHNxdWFyZSBtYXRyaXguDQpgYGB7cn0NCnRyYWNlIDwtIGZ1bmN0aW9uKEEpew0KICB2YWwgPSAwDQogIGZvciAoaSBpbiAxOm5yb3coQSkpew0KICAgIGZvciAoaiBpbiAxOm5jb2woQSkpew0KICAgICAgaWYgKGk9PWopew0KICAgICAgICB2YWwgPSB2YWwgKyBBW2ksaV0NCiAgICAgIH0NCiAgICB9DQogIH0NCiAgcmV0dXJuKHZhbCkNCn0NCg0KYW5zIDwtIHRyYWNlKEEpDQpwcmludChhbnMpDQpgYGANCiMjIyBXcml0ZSBhIGZ1bmN0aW9uIHRvIGV4dHJhY3QgdGhlIGRpYWdvbmFsIGZyb20gYSBzcXVhcmUgbWF0cml4Lg0KYGBge3J9DQpkaWFnbyA8LSBmdW5jdGlvbihBKXsNCiAgdjwtIGMoKQ0KICBmb3IgKGkgaW4gMTpucm93KEEpKXsNCiAgICBmb3IgKGogaW4gMTpuY29sKEEpKXsNCiAgICAgIGlmIChpPT1qKXsNCiAgICAgICAgdiA8LSBhcHBlbmQodixBW2ksaV0pDQogICAgICB9DQogICAgfQ0KICB9DQogIHByaW50KHYpDQp9DQpkaWFnbyhBKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBjcmVhdGUgYSBkaWFnb25hbCBtYXRyaXggZnJvbSBhIHZlY3Rvci4NCmBgYHtyfQ0KdmVjX2RpYWdfbWF0IDwtIGZ1bmN0aW9uKGIpew0KICBuPC1sZW5ndGgoYikNCiAgQSA8LSBtYXRyaXgoMCwgbnJvdz1uLCBuY29sPW4pDQogIGZvciAoaSBpbiAxOm4pew0KICAgIEFbaSxpXTwtYltpXQ0KICB9DQogIHByaW50KEEpDQp9DQoNCnZlY19kaWFnX21hdChiKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBjcmVhdGUgYW4gaWRlbnRpdHkgbWF0cml4IG9mIHNpemUgbi4NCmBgYHtyfQ0KSW4gPC0gZnVuY3Rpb24obil7DQogIEE8LW1hdHJpeCgwLG5yb3c9bixuY29sPW4pDQogIGZvciAoaSBpbiAxOm4pew0KICAgIEFbaSxpXTwtMQ0KICB9DQogIHJldHVybihBKQ0KfQ0KQTwtSW4oNSkNCkENCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gY29tcHV0ZSB0aGUgc3VtIG9mIGVhY2ggY29sdW1uIGluIGEgbWF0cml4Lg0KYGBge3J9DQpjb2xfc3VtIDwtIGZ1bmN0aW9uKEEpew0KICBjb2xzdW08LWMoKQ0KICBmb3IgKGkgaW4gMTpuY29sKEEpKXsNCiAgICBjb2xzdW08LWFwcGVuZChjb2xzdW0sc3VtKEFbLGldKSkNCiAgfQ0KICBjb2xzdW0NCn0NCmNvbF9zdW0oQSkNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gY29tcHV0ZSB0aGUgbWVhbiBvZiBlYWNoIHJvdyBpbiBhIG1hdHJpeC4NCmBgYHtyfQ0Kcm93bWVhbiA8LSBmdW5jdGlvbihBKXsNCiAgeDwtYygpDQogIGZvciAoaSBpbiAxOm5yb3coQSkpew0KICAgIHg8LWFwcGVuZCh4LG1lYW4oQVtpLF0pKQ0KICB9DQogIHJldHVybih4KQ0KfQ0KDQp4PC1yb3dtZWFuKEEpDQpwcmludCh4KQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBjaGVjayBpZiB0d28gbWF0cmljZXMgYXJlIGVxdWFsLg0KYGBge3J9DQplcXVhbF9jaGVjayA8LSBmdW5jdGlvbihBLEIpew0KICBmb3IgKGkgaW4gMTpucm93KEEpKXsNCiAgICBmb3IgKGogaW4gMTpuY29sKEEpKXsNCiAgICAgIGlmIChBW2ksal0hPUJbaSxqXSl7DQogICAgICAgIHJldHVybiAoRkFMU0UpDQogICAgICB9DQogICAgfQ0KICB9DQogIHJldHVybiAoVFJVRSkNCn0NCkE8LW1hdHJpeChjKDEsMiwzLDQpLCBucm93PTIpDQpCPC1tYXRyaXgoYygxLDIsMyw0LjAwMDAwMDAwMSksIG5yb3c9MikNCmVxdWFsX2NoZWNrKEEsQikNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gZmluZCB0aGUgdHJhbnNwb3NlIG9mIGEgbWF0cml4Lg0KYGBge3J9DQp0cmFuczwtZnVuY3Rpb24oQSl7DQogIEI8LW1hdHJpeChOQSxucm93PW5yb3coQSksbmNvbD1uY29sKEEpKQ0KICBmb3IgKGkgaW4gMTpucm93KEEpKXsNCiAgICBmb3IgKGogaW4gMTpuY29sKEIpKXsNCiAgICAgIEJbaixpXTwtQVtpLGpdDQogICAgICB9DQogIH0NCiAgcmV0dXJuKEIpDQp9DQoNCmFuczwtdHJhbnMoQSkNCnByaW50KGFucykNCkENCmBgYA0KDQpgYGB7cn0NCg0KYGBgDQoNCg0KYGBge3J9DQpBDQpzb2x2ZShBKQ0KYGBgDQoNCg0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gbXVsdGlwbHkgdHdvIDJ4MiBtYXRyaWNlcy4NCmBgYHtyfQ0KbXVsMmJ5MiA8LSBmdW5jdGlvbihBLEIpew0KICBDIDwtIG1hdHJpeChOQSwgbnJvdz0yLCBuY29sPTIpDQogIA0KICBDWzEsMV0gPC0gQVsxLDFdKkJbMSwxXSArIEFbMSwyXSpCWzIsMV0NCiAgQ1sxLDJdIDwtIEFbMSwxXSpCWzEsMl0gKyBBWzEsMl0qQlsyLDJdDQogIENbMiwxXSA8LSBBWzIsMV0qQlsxLDFdICsgQVsyLDJdKkJbMiwxXQ0KICBDWzIsMl0gPC0gQVsyLDFdKkJbMSwyXSArIEFbMiwyXSpCWzIsMl0NCiAgDQogIHJldHVybihDKQ0KfQ0KQTwtbWF0cml4KGMoMSwyLDcsNCksbnJvdz0yKQ0KQjwtbWF0cml4KGMoMiwzLDQsMTApLG5yb3c9MikNCm11bDJieTIoQSxCKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBtdWx0aXBseSB0d28gbWF0cmljZXMgb2YgY29tcGF0aWJsZSBkaW1lbnNpb25zLg0KYGBge3J9DQojMiozDQojMyoyDQoNCm1hdHJpeF9tdWx0aXBseSA8LSBmdW5jdGlvbihBLCBCKSB7DQogIGlmIChuY29sKEEpICE9IG5yb3coQikpIHsNCiAgICBzdG9wKCJJbmNvbXBhdGlibGUgZGltZW5zaW9uczogbmNvbChBKSBtdXN0IGVxdWFsIG5yb3coQikiKQ0KICB9DQogIHJlc3VsdCA8LSBtYXRyaXgoMCwgbnJvdyA9IG5yb3coQSksIG5jb2wgPSBuY29sKEIpKQ0KICANCiAgZm9yIChpIGluIDE6bnJvdyhBKSkgew0KICAgIGZvciAoaiBpbiAxOm5jb2woQikpIHsNCiAgICAgIHJlc3VsdFtpLCBqXSA8LSBzdW0oQVtpLCBdICogQlssIGpdKQ0KICAgIH0NCiAgfQ0KICANCiAgcmVzdWx0DQp9DQoNCmFucz1tYXRyaXhfbXVsdGlwbHkoQSxCKQ0KcHJpbnQoYW5zKQ0KDQpgYGANCiMjIyBXcml0ZSBhIGZ1bmN0aW9uIHRvIHJlcGxhY2UgYSByb3cgaW4gYSBtYXRyaXggd2l0aCBhIHZlY3Rvci4NCmBgYHtyfQ0Kcm93X3JlcGxhY2UgPC0gZnVuY3Rpb24oQSxyLHZlY3Qpew0KICBBW3IsXTwtdmVjdA0KICByZXR1cm4oQSkNCiAgfQ0KYW5zPC1yb3dfcmVwbGFjZShBLDIsYygwLDApKQ0KcHJpbnQoYW5zKQ0KYGBgDQojIyMgV3JpdGUgYSBmdW5jdGlvbiB0byBmaW5kIHRoZSBtYXhpbXVtIGVsZW1lbnQgaW4gYSBtYXRyaXguDQpgYGB7cn0NCm1heF9lbGU8LSBmdW5jdGlvbihBKXsNCiAgbWF4aTwtQVsxLDFdDQogIGZvciAoaSBpbiAxOm5yb3coQSkpew0KICAgIGZvciAoaiBpbiAxOm5jb2woQSkpew0KICAgICAgaWYgKEFbaSxqXT5tYXhpKXsNCiAgICAgICAgbWF4aTwtQVtpLGpdDQogICAgICB9DQogICAgfQ0KICB9DQogIHJldHVybihtYXhpKQ0KfQ0KYW5zPC1tYXhfZWxlKEEpDQpwcmludChhbnMpDQpgYGANCiMjIyBXcml0ZSBhIGZ1bmN0aW9uIHRvIGNvbXB1dGUgcm93IHN1bXMgb2YgYSBtYXRyaXguDQpgYGB7cn0NCkENCnJvd19zdW1zPC1mdW5jdGlvbihBKXsNCiAgcmVzdWx0PC1udW1lcmljKG5yb3coQSkpDQogIGZvciAoaSBpbiAxOm5yb3coQSkpew0KICAgIHJlc3VsdFtpXTwtc3VtKEFbaSxdKQ0KICB9DQogIHJldHVybihyZXN1bHQpDQp9DQoNCmFuczwtcm93X3N1bXMoQSkNCnByaW50KGFucykNCmBgYA0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gY2hlY2sgaWYgYSBtYXRyaXggaXMgdXBwZXIgdHJpYW5ndWxhci4NCmBgYHtyfQ0KdXB0cmlhbiA8LSBmdW5jdGlvbihBKXsNCiAgZm9yIChpIGluIDE6bnJvdyhBKSl7DQogICAgZm9yIChqIGluIDE6bmNvbChBKSl7DQogICAgICBpZiAoaT5qKXsNCiAgICAgICAgQVtpLGpdIT0wDQogICAgICAgIHJldHVybihGQUxTRSkNCiAgICAgIH0NCiAgICB9DQogIH0NCiAgcmV0dXJuKFRSVUUpDQp9DQphbnM8LXVwdHJpYW4oQSkNCnByaW50KGFucykNCmBgYA0KYGBge3J9DQpBPC1jKCkNCkE8LWFwcGVuZChBLDIpDQpBPC1hcHBlbmQoQSw0KQ0KDQpgYGANCg0KIyMjIFdyaXRlIGEgZnVuY3Rpb24gdG8gY2hlY2sgaWYgYSBtYXRyaXggaXMgc2NhbGFyIChtdWx0aXBsZSBvZiBpZGVudGl0eSkuDQpgYGB7cn0NCnNjYWxlcl9jaGVjayA8LSBmdW5jdGlvbihBKXsNCiAgZm9yIChpIGluIDE6bnJvdyhBKSl7DQogICAgZm9yIChqIGluIDE6bmNvbChBKSl7DQogICAgICBpZihpIT1qICYgQVtpLGpdIT0wKXsNCiAgICAgICAgcmV0dXJuKEZBTFNFKQ0KICAgICAgfSANCiAgICAgIGVsc2UgaWYoaT09aiAmIEFbaSxqXSE9QVsxLDFdKXsNCiAgICAgICAgcmV0dXJuKEZBTFNFKQ0KICAgICAgfQ0KICAgIH0NCiAgfQ0KICByZXR1cm4oVFJVRSkNCiAgfQ0KDQpBPC1tYXRyaXgoYygxLDIsNyw0KSxucm93PTIpDQpCPC1tYXRyaXgoYygxLDAsMCwxKSwgbnJvdz0yKQ0Kc2NhbGVyX2NoZWNrKEIpDQpgYGANCiMjIyBXcml0ZSBhIGZ1bmN0aW9uIHRvIGNvbXB1dGUgdGhlIHJvdy13aXNlIG1heGltdW0gb2YgYSBtYXRyaXguDQpgYGB7cn0NCnJvd21heDwtZnVuY3Rpb24oQSl7DQogIG1heHM8LW51bWVyaWMobnJvdyhBKSkNCiAgZm9yIChpIGluIDE6bnJvdyhBKSl7DQogICAgbWF4PUFbaSwxXQ0KICAgIGZvciAoaiBpbiAxOm5jb2woQSkpew0KICAgICAgaWYgKEFbaSxqXT5tYXgpew0KICAgICAgICBtYXg8LUFbaSxqXQ0KICAgICAgfQ0KICAgIH0NCiAgICBtYXhzW2ldPC1tYXggDQogIH0NCiAgcmV0dXJuKG1heHMpDQp9DQpwcmludChyb3dtYXgoQSkpDQpBDQpgYGANCiMjIyBXcml0ZSBhIGZ1bmN0aW9uIHRvIGNvbXB1dGUgY3VtdWxhdGl2ZSBzdW0gb2YgZWFjaCByb3cuDQpgYGB7cn0NCmN1bXN1bXJvdyA8LSBmdW5jdGlvbihBKXsNCiAgbWF0PC1tYXRyaXgoTkEsbnJvdz1ucm93KEEpLG5jb2w9bmNvbChBKSkNCiAgZm9yIChpIGluIDE6bnJvdyhBKSl7DQogICAgY3Vtc3VtPC1udW1lcmljKG5jb2woQSkpDQogICAgY3Vtc3VtWzFdPC1BW2ksMV0NCiAgICBmb3IgKGogaW4gMjpuY29sKEEpKXsNCiAgICAgIGN1bXN1bVtqXTwtQVtpLGpdK2N1bXN1bVtqLTFdDQogICAgfQ0KICAgIG1hdFtpLF08LWN1bXN1bQ0KICB9DQogIHJldHVybihtYXQpDQp9DQoNCnByaW50KGN1bXN1bXJvdyhBKSkNCkENCmBgYA0KIyAyNS4gQ3VtdWxhdGl2ZSBwcm9kdWN0DQpjdW1wcm9kX3ZlYyA8LSBmdW5jdGlvbihhKSB7DQogIHJlc3VsdCA8LSBudW1lcmljKGxlbmd0aChhKSkNCiAgcmVzdWx0WzFdIDwtIGFbMV0NCiAgZm9yIChpIGluIDI6bGVuZ3RoKGEpKSB7DQogICAgcmVzdWx0W2ldIDwtIHJlc3VsdFtpLTFdICogYVtpXQ0KICB9DQogIHJlc3VsdA0KfQ0KDQpgYGB7cn0NCg0KDQp2ZWN4PC1jKDEwLDIwLDE4OCwzNDgpDQpzdW0odmVjeF4yKQ0KDQoNCmBgYA0KDQoNCg0KYGBge3J9DQpBPC1jKDEsMiwzLDQpDQpCPC1jKDIsNCw2LDgpDQphbGwoQS9CPT1BWzFdL0JbMV0pDQpgYGANCg0KYGBge3J9DQojIDIxLiBCdWJibGUgc29ydA0KYnViYmxlX3NvcnQgPC0gZnVuY3Rpb24oYSkgew0KICBuIDwtIGxlbmd0aChhKQ0KICBmb3IgKGkgaW4gMToobi0xKSkgew0KICAgIGZvciAoaiBpbiAxOihuLWkpKSB7DQogICAgICBpZiAoYVtqXSA+IGFbaisxXSkgew0KICAgICAgICB0ZW1wIDwtIGFbal0NCiAgICAgICAgYVtqXSA8LSBhW2orMV0NCiAgICAgICAgYVtqKzFdIDwtIHRlbXANCiAgICAgIH0NCiAgICB9DQogIH0NCiAgYQ0KYGBgDQoNCmBgYHtyfQ0KVmlldyhzb2x2ZSkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==