En RStudio se puede reconocer 4 secciones, el editor de R, la
consola, las variables de ambiente, y los archivos y ayuda de R. En la
consola es posible ejecutar código; realizar operaciones aritméticas,
correr funciones y evaluar variables, sin embargo no es posible
almacenar el código que se escribe en la consola, por esta razón se
utiliza el script de R.
En el script se escribe el código que se quiere almacenar para volver
a ejecutar en el futuro. Al guardar, el archivo resultante es un script
de R que tiene extensión “.R”.
Las variables globales que sean definidas en el código aparecerán en
las variables de ambiente y en la pestaña de ayuda de R se encontrará la
información de paquetes, funciones y gráficas que sean generadas
Primero, vamos a definir las variables, hay dos operadores para
dfinirlas
a = 1
b <- 2
Existen diferentes clases de objetos en R
Caracteres Numeros (reales) Enteros Complejos Logicos
(True/False)
VECTORES
Tambien podemos crear vectores de diferentes clases de objetos
#Vector con numeros enteros
vectorA = c(1,5)
#Vector con caracteres
vectorB = c('hola', 'bien','modelos')
#Vector con diferentes calses de objetos
vectorDiverso = c(1.4, 'dos', TRUE)
class(vectorDiverso)
vectorExplicito = 0:7
class(vectorExplicito)
as.character(vectorExplicito)
as.logical(vectorExplicito)
Como instalar paquetes de R?
# install.packages("Nombre del paquete")
# library('Nombre del paquete')
install.packages('markovchain')
library('markovchain')
Funciones en R
#------------------------------------Funciones en R-------------------------#
#estructura de codigo de una funciC3n
funcion1 = function(arg1,arg2){
statements
return(object)
}
Ejemplo. Vamos a crear una funcion como parametro un numero y calcule
su raiz cubica y suma 10
funcion2 = function(n){
valor = (n^(1/3))+10
return(valor)
}
funcion2(4)
Una función, no necesariamente debe retornar un valor numerico, puede
retornar graficas
funcion3 = function(x){
y <- seq(from = 1, to = length(x), by = 1)
plot(y,x, type = 'c', col = 'red')
}
vector1 = c(5,4,7,6,10)
funcion3(vector1)
Recorridos en R
funcion4 = function(v1,v2){
vectorResultado = rep(0,times = length(v1))
for(i in 1:length(v1)){
vectorResultado[i] = max(v1[i],v2[i])
}
return(vectorResultado)
}
vectorp = c(2,3,4,5,6)
vectorp2 = c(3,1,9,8,2)
funcion4(vectorp,vectorp2)
ESTRUCTURAS DE CONTROL O CONDIONALES
x = 4
if (x <= 10) {
print('x es menor a 10')
} else {
print('x es mayor a 10')
}
x = 10
if (x > 1 & x < 7) {
print('X es un numero entre 1 y 7')
} else if (x > 8 & x < 15) {
print(('X es un numero entre 8 y 15'))
}
Poniendo en practica lo aprendido, vamos a elaborar una funciC3n que
retorne TRUE si un numero especifico esta dentro de un vector
funcion5 = function(vector,n){
for (i in 1:length(vector)) {
if (vector[i] == n) {
return(TRUE)
}
}
return(FALSE)
}
vectorE = c(3,4,7,9,10,18,23,78,95)
y = 18
funcion5(vectorE,y)
#Graficas en R
#Vamos a crear un grafico de lineas usando dos vectores
vectorC = c(1,3,4,7,8,4,2)
vectorD = c(1,2,3,4,5,6,7)
grafica = plot(vectorD, vectorC, type = 'l', col = 'blue')
COMPLEMENTARIA 2
El objetivo de esta complementaria es definir y manejar matrices en
R. Ya qué estas son las las matrices que usaremos para definir las
cadenas de Markov.
Primero vamos a hacer una matri< que nos diga algunas estadisticas
importantes de equipos de futbol colombiano.
Para esto usaremos la funcion matrix
¿Cuales son los pricnipales argumentos de la función matrix?. Set de
datos, número de filas y numero de columnas
mat = matrix(c(1,4,1,3,2,4,4,0,3,2,1,1,4,2,2,0), nrow = 4, ncol = 4)
Es importante tener en cuenta que la matriz se genera por columna por
defecto, a menos que utilizemos el comendo byrow
mat = matrix(c(1,4,1,3,2,4,4,0,3,2,1,1,4,2,2,0), nrow = 4, ncol = 4, byrow = TRUE)
Tambien podemos incorporar nombres a las filas y a las columnas de
nuestra matriz. Utilizando el comando dimnames
dimnames(mat) = list(c('America', 'Alianza','Santafe','Fortaleza'),
c('Pos','Goles marcados', 'Goles recibidos', 'Diferencia'))
Ahora, digamos que queremos añadir las estadisticas de otro equipo a
nuestra matriz. Esto lo podemos hacer con ayuda de la funcion rbind
Millonarios = c(5,0,3,-5)
mat = rbind(mat, Millonarios)
Como podemos acceder a las filas o a las columnas de la matriz?
mat['America',]
mat[,'Goles recibidos']
#Otro ejemplo
mat[1,]
mat[,3]
Es importante verificar que el conjunto de datos o matriz que estemos
creando sea efectivamente de tipo matrix
Para evaluar si un conjunto de datos es de tipo matrix
is.matrix(mat)
Para convertir un set de datos a matriz
as.matrix(mat)
Porque es importante esto, por las operacionesque podemos hacer entre
matrices. Aqui hay algunos ejemplos
Vamos a crear dos matrices cutos valores van a seguir una
dsirtribución normal, esto es para efectos de generara rapidamente
valores aleatorios.
A = matrix(rnorm(n=36, mean = 20, sd = 8), nrow = 6, ncol = 6)
B = matrix(rnorm(n=36, mean = 10, sd = 3), nrow = 6, ncol = 6)
Operaciones entre matrices
#transpuesta de una matriz
t(A)
#Suma de matrices
A + B
#Producto matricial
A%*%B
#Producto elemento a elemento
A*B
#Inversa de una matriz
solve(A)
#determinante de una matriz
det(A)
#diagonal de la matriz
diag(A)
#Suma de columnas y filas
rowSums(A)
colSums(B)
Ahora veremos como reflejar una cadena de markov a R, entonces vamos
a hacer el primer problema de de la complementaria 2
estados = c(1:5)
mat1 = matrix(0, nrow = 5, ncol = 5, dimnames = list(estados,estados))
filas = estados
columnas = estados
for (i in filas) {
for (j in columnas) {
if (j == i & i >= 2 & i <= 4) {
mat1[i,j] = 0.3
}
if (j == i - 1 & i >= 2) {
mat1[i,j] = 0.2
}
if (j == i + 1 & i <= 4) {
mat1[i,j] = 0.5
}
if (j == i & i == 1 ) {
mat1[i,j] = 0.5
}
if (j == i & i == 5) {
mat1[i,j] = 0.8
}
}
}
View(mat1)
rowSums(mat1)
LS0tDQp0aXRsZTogIkNvbXBsZW1lbnRhcmlhIDIiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KRW4gUlN0dWRpbyBzZSBwdWVkZSByZWNvbm9jZXIgNCBzZWNjaW9uZXMsIGVsIGVkaXRvciBkZSBSLCBsYSBjb25zb2xhLCBsYXMgdmFyaWFibGVzIGRlIGFtYmllbnRlLCB5IGxvcyBhcmNoaXZvcyB5IGF5dWRhIGRlIFIuIEVuIGxhIGNvbnNvbGEgZXMgcG9zaWJsZSBlamVjdXRhciBjw7NkaWdvOyByZWFsaXphciBvcGVyYWNpb25lcyBhcml0bcOpdGljYXMsIGNvcnJlciBmdW5jaW9uZXMgeSBldmFsdWFyIHZhcmlhYmxlcywgc2luIGVtYmFyZ28gbm8gZXMgcG9zaWJsZSBhbG1hY2VuYXIgZWwgY8OzZGlnbyBxdWUgc2UgZXNjcmliZSBlbiBsYSBjb25zb2xhLCBwb3IgZXN0YSByYXrDs24gc2UgdXRpbGl6YSBlbCBzY3JpcHQgZGUgUi4gDQoNCg0KRW4gZWwgc2NyaXB0IHNlIGVzY3JpYmUgZWwgY8OzZGlnbyBxdWUgc2UgcXVpZXJlIGFsbWFjZW5hciBwYXJhIHZvbHZlciBhIGVqZWN1dGFyIGVuIGVsIGZ1dHVyby4gQWwgZ3VhcmRhciwgZWwgYXJjaGl2byByZXN1bHRhbnRlIGVzIHVuIHNjcmlwdCBkZSBSIHF1ZSB0aWVuZSBleHRlbnNpw7NuIOKAnC5S4oCdLiANCg0KDQpMYXMgdmFyaWFibGVzIGdsb2JhbGVzIHF1ZSBzZWFuIGRlZmluaWRhcyBlbiBlbCBjw7NkaWdvIGFwYXJlY2Vyw6FuIGVuIGxhcyB2YXJpYWJsZXMgZGUgYW1iaWVudGUgeSBlbiBsYSBwZXN0YcOxYSBkZSBheXVkYSBkZSBSIHNlIGVuY29udHJhcsOhIGxhIGluZm9ybWFjacOzbiBkZSBwYXF1ZXRlcywgZnVuY2lvbmVzIHkgZ3LDoWZpY2FzIHF1ZSBzZWFuIGdlbmVyYWRhcw0KDQpQcmltZXJvLCB2YW1vcyBhIGRlZmluaXIgbGFzIHZhcmlhYmxlcywgaGF5IGRvcyBvcGVyYWRvcmVzIHBhcmEgZGZpbmlybGFzDQpgYGB7cn0NCmEgPSAxDQpiIDwtIDINCg0KYGBgDQoNCkV4aXN0ZW4gZGlmZXJlbnRlcyBjbGFzZXMgZGUgb2JqZXRvcyBlbiBSDQoNCkNhcmFjdGVyZXMNCk51bWVyb3MgKHJlYWxlcykNCkVudGVyb3MNCkNvbXBsZWpvcw0KTG9naWNvcyAoVHJ1ZS9GYWxzZSkNCg0KVkVDVE9SRVMNCg0KVGFtYmllbiBwb2RlbW9zIGNyZWFyIHZlY3RvcmVzIGRlIGRpZmVyZW50ZXMgY2xhc2VzIGRlIG9iamV0b3MNCg0KYGBge3J9DQojVmVjdG9yIGNvbiBudW1lcm9zIGVudGVyb3MNCnZlY3RvckEgPSBjKDEsNSkNCg0KI1ZlY3RvciBjb24gY2FyYWN0ZXJlcw0KdmVjdG9yQiA9IGMoJ2hvbGEnLCAnYmllbicsJ21vZGVsb3MnKQ0KDQojVmVjdG9yIGNvbiBkaWZlcmVudGVzIGNhbHNlcyBkZSBvYmpldG9zDQp2ZWN0b3JEaXZlcnNvID0gYygxLjQsICdkb3MnLCBUUlVFKQ0KY2xhc3ModmVjdG9yRGl2ZXJzbykNCg0KdmVjdG9yRXhwbGljaXRvID0gMDo3DQpjbGFzcyh2ZWN0b3JFeHBsaWNpdG8pDQoNCmFzLmNoYXJhY3Rlcih2ZWN0b3JFeHBsaWNpdG8pDQoNCmFzLmxvZ2ljYWwodmVjdG9yRXhwbGljaXRvKQ0KDQpgYGANCg0KQ29tbyBpbnN0YWxhciBwYXF1ZXRlcyBkZSBSPw0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygiTm9tYnJlIGRlbCBwYXF1ZXRlIikNCiMgbGlicmFyeSgnTm9tYnJlIGRlbCBwYXF1ZXRlJykNCg0KaW5zdGFsbC5wYWNrYWdlcygnbWFya292Y2hhaW4nKQ0KbGlicmFyeSgnbWFya292Y2hhaW4nKQ0KYGBgDQoNCkZ1bmNpb25lcyBlbiBSDQoNCmBgYHtyfQ0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLUZ1bmNpb25lcyBlbiBSLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMNCg0KI2VzdHJ1Y3R1cmEgZGUgY29kaWdvIGRlIHVuYSBmdW5jaUMzbg0KZnVuY2lvbjEgPSBmdW5jdGlvbihhcmcxLGFyZzIpew0KICBzdGF0ZW1lbnRzDQogIHJldHVybihvYmplY3QpDQp9DQpgYGANCkVqZW1wbG8uIFZhbW9zIGEgY3JlYXIgdW5hIGZ1bmNpb24gY29tbyBwYXJhbWV0cm8gdW4gbnVtZXJvIHkgY2FsY3VsZSBzdSByYWl6IGN1YmljYSB5IHN1bWEgMTANCg0KYGBge3J9DQpmdW5jaW9uMiA9IGZ1bmN0aW9uKG4pew0KICB2YWxvciA9IChuXigxLzMpKSsxMA0KICByZXR1cm4odmFsb3IpDQp9DQpmdW5jaW9uMig0KQ0KYGBgDQoNClVuYSBmdW5jacOzbiwgbm8gbmVjZXNhcmlhbWVudGUgZGViZSByZXRvcm5hciB1biB2YWxvciBudW1lcmljbywgcHVlZGUgcmV0b3JuYXIgZ3JhZmljYXMNCmBgYHtyfQ0KZnVuY2lvbjMgPSBmdW5jdGlvbih4KXsNCiAgeSA8LSBzZXEoZnJvbSA9IDEsIHRvID0gbGVuZ3RoKHgpLCBieSA9IDEpDQogIHBsb3QoeSx4LCB0eXBlID0gJ2MnLCBjb2wgPSAncmVkJykNCn0NCnZlY3RvcjEgPSBjKDUsNCw3LDYsMTApDQpmdW5jaW9uMyh2ZWN0b3IxKQ0KYGBgDQoNClJlY29ycmlkb3MgZW4gUg0KDQpgYGB7cn0NCmZ1bmNpb240ID0gZnVuY3Rpb24odjEsdjIpew0KICB2ZWN0b3JSZXN1bHRhZG8gPSByZXAoMCx0aW1lcyA9IGxlbmd0aCh2MSkpDQogIA0KICBmb3IoaSBpbiAxOmxlbmd0aCh2MSkpew0KICAgIHZlY3RvclJlc3VsdGFkb1tpXSA9IG1heCh2MVtpXSx2MltpXSkNCiAgIH0NCiAgcmV0dXJuKHZlY3RvclJlc3VsdGFkbykNCn0NCg0KdmVjdG9ycCA9IGMoMiwzLDQsNSw2KQ0KdmVjdG9ycDIgPSBjKDMsMSw5LDgsMikNCg0KZnVuY2lvbjQodmVjdG9ycCx2ZWN0b3JwMikNCmBgYA0KDQpFU1RSVUNUVVJBUyBERSBDT05UUk9MIE8gQ09ORElPTkFMRVMNCg0KYGBge3J9DQp4ID0gNA0KaWYgKHggPD0gMTApIHsNCiAgcHJpbnQoJ3ggZXMgbWVub3IgYSAxMCcpDQp9IGVsc2Ugew0KICBwcmludCgneCBlcyBtYXlvciBhIDEwJykNCn0gDQoNCnggPSAxMA0KaWYgKHggPiAxICYgeCA8IDcpIHsNCiAgcHJpbnQoJ1ggZXMgdW4gbnVtZXJvIGVudHJlIDEgeSA3JykNCn0gZWxzZSBpZiAoeCA+IDggJiB4IDwgMTUpIHsNCiAgcHJpbnQoKCdYIGVzIHVuIG51bWVybyBlbnRyZSA4IHkgMTUnKSkNCn0NCmBgYA0KDQoNClBvbmllbmRvIGVuIHByYWN0aWNhIGxvIGFwcmVuZGlkbywgdmFtb3MgYSBlbGFib3JhciB1bmEgZnVuY2lDM24gcXVlIHJldG9ybmUgVFJVRSBzaSB1biBudW1lcm8gZXNwZWNpZmljbyBlc3RhIGRlbnRybyBkZSB1biB2ZWN0b3INCg0KYGBge3J9DQpmdW5jaW9uNSA9IGZ1bmN0aW9uKHZlY3RvcixuKXsNCiAgZm9yIChpIGluIDE6bGVuZ3RoKHZlY3RvcikpIHsNCiAgICBpZiAodmVjdG9yW2ldID09IG4pIHsNCiAgICAgIHJldHVybihUUlVFKQ0KICAgIH0gDQogIH0NCiAgcmV0dXJuKEZBTFNFKQ0KfQ0KDQoNCnZlY3RvckUgPSBjKDMsNCw3LDksMTAsMTgsMjMsNzgsOTUpDQp5ID0gMTgNCmZ1bmNpb241KHZlY3RvckUseSkNCmBgYA0KDQpgYGB7cn0NCiNHcmFmaWNhcyBlbiBSDQojVmFtb3MgYSBjcmVhciB1biBncmFmaWNvIGRlIGxpbmVhcyB1c2FuZG8gZG9zIHZlY3RvcmVzDQoNCnZlY3RvckMgPSBjKDEsMyw0LDcsOCw0LDIpDQp2ZWN0b3JEID0gYygxLDIsMyw0LDUsNiw3KQ0KDQpncmFmaWNhID0gcGxvdCh2ZWN0b3JELCB2ZWN0b3JDLCB0eXBlID0gJ2wnLCBjb2wgPSAnYmx1ZScpDQoNCmBgYA0KDQoNCkNPTVBMRU1FTlRBUklBIDINCg0KRWwgb2JqZXRpdm8gZGUgZXN0YSBjb21wbGVtZW50YXJpYSBlcyBkZWZpbmlyIHkgbWFuZWphciBtYXRyaWNlcyBlbiBSLiBZYSBxdcOpIGVzdGFzIHNvbiBsYXMgbGFzIG1hdHJpY2VzIHF1ZSB1c2FyZW1vcyBwYXJhIGRlZmluaXIgbGFzIGNhZGVuYXMgZGUgTWFya292Lg0KDQpQcmltZXJvIHZhbW9zIGEgaGFjZXIgdW5hIG1hdHJpPCBxdWUgbm9zIGRpZ2EgYWxndW5hcyBlc3RhZGlzdGljYXMgaW1wb3J0YW50ZXMgZGUgZXF1aXBvcyBkZSBmdXRib2wgY29sb21iaWFuby4NCg0KUGFyYSBlc3RvIHVzYXJlbW9zIGxhIGZ1bmNpb24gbWF0cml4DQoNCsK/Q3VhbGVzIHNvbiBsb3MgcHJpY25pcGFsZXMgYXJndW1lbnRvcyBkZSBsYSBmdW5jacOzbiBtYXRyaXg/LiBTZXQgZGUgZGF0b3MsIG7Dum1lcm8gZGUgZmlsYXMgeSBudW1lcm8gZGUgY29sdW1uYXMNCg0KYGBge3J9DQptYXQgPSBtYXRyaXgoYygxLDQsMSwzLDIsNCw0LDAsMywyLDEsMSw0LDIsMiwwKSwgbnJvdyA9IDQsIG5jb2wgPSA0KQ0KYGBgDQoNCkVzIGltcG9ydGFudGUgdGVuZXIgZW4gY3VlbnRhIHF1ZSBsYSBtYXRyaXogc2UgZ2VuZXJhIHBvciBjb2x1bW5hIHBvciBkZWZlY3RvLCBhIG1lbm9zIHF1ZSB1dGlsaXplbW9zIGVsIGNvbWVuZG8gYnlyb3cNCg0KYGBge3J9DQptYXQgPSBtYXRyaXgoYygxLDQsMSwzLDIsNCw0LDAsMywyLDEsMSw0LDIsMiwwKSwgbnJvdyA9IDQsIG5jb2wgPSA0LCBieXJvdyA9IFRSVUUpDQoNCmBgYA0KDQpUYW1iaWVuIHBvZGVtb3MgaW5jb3Jwb3JhciBub21icmVzIGEgbGFzIGZpbGFzIHkgYSBsYXMgY29sdW1uYXMgZGUgbnVlc3RyYSBtYXRyaXouIFV0aWxpemFuZG8gZWwgY29tYW5kbyBkaW1uYW1lcw0KDQpgYGB7cn0NCmRpbW5hbWVzKG1hdCkgPSBsaXN0KGMoJ0FtZXJpY2EnLCAnQWxpYW56YScsJ1NhbnRhZmUnLCdGb3J0YWxlemEnKSwNCiAgICAgICAgICAgICAgICAgICAgIGMoJ1BvcycsJ0dvbGVzIG1hcmNhZG9zJywgJ0dvbGVzIHJlY2liaWRvcycsICdEaWZlcmVuY2lhJykpDQoNCmBgYA0KDQpBaG9yYSwgZGlnYW1vcyBxdWUgcXVlcmVtb3MgYcOxYWRpciBsYXMgZXN0YWRpc3RpY2FzIGRlIG90cm8gZXF1aXBvIGEgbnVlc3RyYSBtYXRyaXouIEVzdG8gbG8gcG9kZW1vcyBoYWNlciBjb24gYXl1ZGEgZGUgbGEgZnVuY2lvbiByYmluZA0KDQpgYGB7cn0NCk1pbGxvbmFyaW9zID0gYyg1LDAsMywtNSkNCm1hdCA9IHJiaW5kKG1hdCwgTWlsbG9uYXJpb3MpDQoNCmBgYA0KDQpDb21vIHBvZGVtb3MgYWNjZWRlciBhIGxhcyBmaWxhcyBvIGEgbGFzIGNvbHVtbmFzIGRlIGxhIG1hdHJpej8NCg0KYGBge3J9DQptYXRbJ0FtZXJpY2EnLF0NCm1hdFssJ0dvbGVzIHJlY2liaWRvcyddDQojT3RybyBlamVtcGxvDQptYXRbMSxdDQptYXRbLDNdDQoNCmBgYA0KDQpFcyBpbXBvcnRhbnRlIHZlcmlmaWNhciBxdWUgZWwgY29uanVudG8gZGUgZGF0b3MgbyBtYXRyaXogcXVlIGVzdGVtb3MgY3JlYW5kbyBzZWEgZWZlY3RpdmFtZW50ZSBkZSB0aXBvIG1hdHJpeA0KDQpQYXJhIGV2YWx1YXIgc2kgdW4gY29uanVudG8gZGUgZGF0b3MgZXMgZGUgdGlwbyBtYXRyaXgNCg0KYGBge3J9DQppcy5tYXRyaXgobWF0KQ0KDQpgYGANCg0KUGFyYSBjb252ZXJ0aXIgdW4gc2V0IGRlIGRhdG9zIGEgbWF0cml6DQoNCmBgYHtyfQ0KYXMubWF0cml4KG1hdCkNCg0KYGBgDQoNClBvcnF1ZSBlcyBpbXBvcnRhbnRlIGVzdG8sIHBvciBsYXMgb3BlcmFjaW9uZXNxdWUgcG9kZW1vcyBoYWNlciBlbnRyZSBtYXRyaWNlcy4gQXF1aSBoYXkgYWxndW5vcyBlamVtcGxvcw0KDQpWYW1vcyBhIGNyZWFyIGRvcyBtYXRyaWNlcyBjdXRvcyB2YWxvcmVzIHZhbiBhIHNlZ3VpciB1bmEgZHNpcnRyaWJ1Y2nDs24gbm9ybWFsLCBlc3RvIGVzIHBhcmEgZWZlY3RvcyBkZSBnZW5lcmFyYSByYXBpZGFtZW50ZSB2YWxvcmVzIGFsZWF0b3Jpb3MuDQoNCmBgYHtyfQ0KQSA9IG1hdHJpeChybm9ybShuPTM2LCBtZWFuID0gMjAsIHNkID0gOCksIG5yb3cgPSA2LCBuY29sID0gNikNCkIgPSBtYXRyaXgocm5vcm0obj0zNiwgbWVhbiA9IDEwLCBzZCA9IDMpLCBucm93ID0gNiwgbmNvbCA9IDYpDQpgYGANCg0KT3BlcmFjaW9uZXMgZW50cmUgbWF0cmljZXMNCg0KDQpgYGB7cn0NCiN0cmFuc3B1ZXN0YSBkZSB1bmEgbWF0cml6DQp0KEEpDQoNCiNTdW1hIGRlIG1hdHJpY2VzDQpBICsgQg0KDQojUHJvZHVjdG8gbWF0cmljaWFsDQpBJSolQg0KDQojUHJvZHVjdG8gZWxlbWVudG8gYSBlbGVtZW50bw0KQSpCDQoNCiNJbnZlcnNhIGRlIHVuYSBtYXRyaXoNCnNvbHZlKEEpDQoNCiNkZXRlcm1pbmFudGUgZGUgdW5hIG1hdHJpeg0KZGV0KEEpDQoNCiNkaWFnb25hbCBkZSBsYSBtYXRyaXoNCmRpYWcoQSkNCg0KI1N1bWEgZGUgY29sdW1uYXMgeSBmaWxhcw0Kcm93U3VtcyhBKQ0KY29sU3VtcyhCKQ0KDQpgYGANCg0KQWhvcmEgdmVyZW1vcyBjb21vIHJlZmxlamFyIHVuYSBjYWRlbmEgZGUgbWFya292IGEgUiwgZW50b25jZXMgdmFtb3MgYSBoYWNlciBlbCBwcmltZXIgcHJvYmxlbWEgZGUgZGUgbGEgY29tcGxlbWVudGFyaWEgMg0KDQpgYGB7cn0NCmVzdGFkb3MgPSBjKDE6NSkNCg0KbWF0MSA9IG1hdHJpeCgwLCBucm93ID0gNSwgbmNvbCA9IDUsIGRpbW5hbWVzID0gbGlzdChlc3RhZG9zLGVzdGFkb3MpKQ0KDQpmaWxhcyA9IGVzdGFkb3MNCmNvbHVtbmFzID0gZXN0YWRvcw0KDQpmb3IgKGkgaW4gZmlsYXMpIHsNCiAgZm9yIChqIGluIGNvbHVtbmFzKSB7DQogICAgDQogICAgaWYgKGogPT0gaSAmIGkgPj0gMiAmIGkgPD0gNCkgew0KICAgICAgbWF0MVtpLGpdID0gMC4zDQogICAgfQ0KICAgIGlmIChqID09IGkgLSAxICYgaSA+PSAyKSB7DQogICAgICBtYXQxW2ksal0gPSAwLjINCiAgICB9DQogICAgaWYgKGogPT0gaSArIDEgJiBpIDw9IDQpIHsNCiAgICAgIG1hdDFbaSxqXSA9IDAuNQ0KICAgIH0NCiAgICBpZiAoaiA9PSBpICYgaSA9PSAxICkgew0KICAgICAgbWF0MVtpLGpdID0gMC41DQogICAgfQ0KICAgIGlmIChqID09IGkgJiBpID09IDUpIHsNCiAgICAgIG1hdDFbaSxqXSA9IDAuOA0KICAgIH0NCiAgfQ0KfQ0KVmlldyhtYXQxKQ0Kcm93U3VtcyhtYXQxKQ0KDQpgYGANCg0KDQoNCg==