Este documento tem como objetivo contribuir para o entendimento de programação em R sobre os seguintes temas:
- Operadores relacionais
==
<
>
e lógicos and
or
not
;
- Condições
if
else
;
- Loops;
- Funções;
- A família de funções apply;
- Datas;
- Pacotes
Basicamente, é um resumo do curso Intermediate R do DataCamp (2017). Recomendo que você faça o curso para um entendimento mais detalhado dos temas estudados.
OPERADORES RELACIONAIS
Comumente temos que fazer escolhas dada uma condição. Se alguma coisa for verdade, então iremos agir de uma maneira, caso contrário, então podemos tomar outra ação. Você pode fazer isso também em uma análise de dados e por meio do R.
Abaixo, veremos quais são os operadores relacionais usados para testar condições como as citadas acima.
################################
#### IGUALDADE #####
################################
# Comparação de valores lógicos
TRUE == FALSE
# Comparação de valores numéricos
-6 * 14 != 17 - 101
# Comparação de strings
"useR" == "user"
# Comparação de um valor numérico com outro lógico
TRUE == 1
################################
#### MAIOR OU MENOR QUE #####
################################
# Comparação de números (resultado de cada lado)
-6 * 5 + 2 >= -10 + 1
# Comparação de strings
"raining" <= "raining dogs"
# Comparação de strings
TRUE > FALSE
################################
#### COMPARAR VETORES #####
################################
# Vetores com acessos ao LinkedIn and Facebook
linkedin <- c(16, 9, 13, 5, 2, 17, 14)
facebook <- c(17, 7, 5, 16, 8, 13, 14)
# Dias populares
linkedin > 15
# Dias com pouco acesso
linkedin <= 5
# Dias em que o LinkedIn foi mais popular que o Facebook
linkedin > facebook
################################
#### COMPARAR MATRIZES #####
################################
# Matriz com as visualizações do LinkedIn e Facebook
views <- matrix(c(linkedin, facebook), nrow = 2, byrow = TRUE)
# Quando as visualizações foram iguais a 13?
views == 13
# Quando as visualizações foram menores ou iguais a 14?
views <= 14
# Com que frequência o Facebook tem visualizações iguais ou superiores às do LinkedIn multiplicado por 2?
sum(facebook >= linkedin * 2)
OPERADORES LÓGICOS
Até o momento, nos operadores relacionais estávamos testando apenas uma condição. Agora, com a inserção dos operadores lógicos podemos testar mais de uma condição, o que é útil no dia a dia.
Abaixo, códigos em R que exemplificam como usar os operadores lógicos.
################################
#### & e | #####
################################
# Quando o LinkedIn excede 10 e Facebook menor que 10?
linkedin > 10 & facebook < 10
# Quando um ou outro foi visitado mais que 12 vezes?
linkedin > 12 | facebook > 12
# Quando as visitas foram maiores que 11 e menores ou iguais a 14?
views > 11 & views <= 14
################################
#### NOT #####
################################
# Contrário do resultado da condição
!(5 > 3)
CONDIÇÕES
Indepedente do operador utilizado anteriormente (relacional ou lógico) tínhamos como resultado os valores TRUE ou FALSE. Porém, nenhuma ação era tomada a partir dos testes.
Agora, usaremos condições e a partir dos resultados uma ação será executada como mostram os códigos em R abaixo.
################################
#### IFELSE #####
################################
# Último dia de visualização do LinkedIn e Facebook
li <- 15
fb <- 9
# Ifelse para testar condições
if (li >= 15 & fb >= 15) { # Testar se em ambos temos 15 ou mais visitas
sms <- (li + fb) * 2 # Se for verdade, execute a soma das visitas multiplicado por 2
} else if (li < 10 & fb < 10) { # Caso contrário, teste se em ambos temos menos que 10 visitas
sms <- (li + fb) / 2 # Se for verdade, execute a média de visitas
} else { # Caso contrário, apenas some as visitas
sms <- (li + fb)
}
# resultado
print(sms)
LOOPS
Muitas vezes pode ser preciso reescrever o seu código em função da necessidade de se repetir uma atividade. Isso pode ser trabalhoso e consumir bastante tempo. Felizmente, temos em programação a opção de usar loops
(no R, as funções for()
, while()
e repeat()
).
Nos códigos abaixo, temos exemplos de como usar os loops
no R.
################################
#### WHILE LOOP #####
################################
# Uma variável de velocidade
speed <- 64
# Enquanto a velocidade for maior que 30 execute
while (speed > 30 ) {
print('Desacelerando!')
speed <- speed - 7 # Desacelerar a velocidade
}
# Mostre o resultado
print(speed)
################################
#### FOR LOOP #####
################################
# Versão 1
for (views in linkedin) { # Para cada valor da matriz views que existe no vetor linkedin
print(views) # Mostre o valor
}
# Versão 2
for (i in 1:length(linkedin)) { # Para cada índice da sequência de 1 a length(linkedin)
print(linkedin[i]) # Mostre o valor do vetor do respectivo índice
}
# Versão 3: Usando a função seq_along. Ela cria um vetor
# de inteiros com índices para acompanhar o objeto.
for (i in seq_along(linkedin)) { # Para cada índice do vetor linkdedin
print(linkedin[i]) # Mostre os resultados
}
################################
### LOOP SOBRE UMA LISTA ###
################################
# Criando uma lista
nyc <- list(pop = 8405837, bairros = c("Manhattan", "Bronx", "Brooklyn", "Queens", "Staten Island"),
capital = FALSE)
# Versão 1
for (value in nyc) { # Para cada item da lista
print(value) # Mostre os valores contidos em cada item da lista
}
# Versão 2
for (i in 1:length(nyc)) { # Para cada índice da sequência de 1 até o tamanho de itens na lista
print(nyc[[i]]) # Mostre os valores contidos em cada item da lista usando o índice
}
################################
### LOOP SOBRE UMA MATRIZ ###
################################
# Criar uma matriz
ttt <- matrix(c("O", NA, "X", NA, "O", NA, "X", "O", "X"), nrow = 3, ncol = 3)
# Executar o loop
for (i in 1:nrow(ttt)) { # Para cada linha da matriz (1:nrow(ttt) criará os índices das linhas)
for (j in 1:ncol(ttt)) { # Para cada coluna da matriz (1:ncol(ttt) criará os índices das colunas)
print(paste("Na linha",i,"e coluna",j,"temos",ttt[i,j])) # Mostre os resultados
}
}
################################
#### LOOP COM CONDIÇÕES ####
################################
# Executar o loop
for (li in linkedin) { # Para cada índice do vetor linkedin (chamamos o índice de li)
if (li > 10) { # Se o índice for maior que 10
print("Você é popular") # Mostre a mensagem "Você é popular"
} else { # Caso contrário, se o índice for <= 10
print("Seja mais visível!") # Mostre outra mensagem "Seja mais visível"
}
}
FUNÇÕES
Durante a programação em R você pode fazer uso de funções “prontas” de pacotes do R, mas em alguns casos você pode optar por criar sua própria função. Desta forma, você evita repetir códigos para executar a mesma tarefa.
Nos códigos abaixo, temos códigos em R que mostram como acessar a documentação de uma função nativa do R e como criar sua própria função.
################################
#### FUNÇÕES NATIVAS #####
################################
# Para acessar a documentação de uma função nativa.
help(mean)
help(sd)
# Existem argumentos obrigatórios e opcionais em funções. Exemplo:
sd(x, na.rm = FALSE)
################################
### FUNÇÕES PRÓPRIAS ###
################################
# Criando a função quadrado que recebe o argumento x
quadrado <- function(x) {
result <- x^2
return(result)
}
# Usando a função quadrado
quadrado(12)
# Criando a função somar_abs() que recebe os argumentos x e y
somar_abs <- function(x, y) {
result <- abs(x) + abs(y)
return(result)
}
# Usando a função somar_abs
somar_abs(-2, 3)
# Expandir a função quadrado() para receber os argumentos x e print_info
quadrado <- function(x, print_info = T) { # argumentos da função
y <- x ^ 2 # tarefa a ser executada
if (print_info == T) { # verificar o argumento print_info
print(paste(x, 'elevado ao quadrado é',y)) # se TRUE, mostrar a mensagem
}
return(y) # a função deve retornar como saído os valores de y
}
quadrado(5)
quadrado(5, print_info=F)
A FAMÍLIA DE FUNÇÕES APPLY
Escrever loops da forma tradicional pode ser uma verdadeira tortura, tanto para o usuário quanto para o computador em função de performance.
Em função disso, surgiram as funções apply()
que são muito úteis na manipulação de dados e simplificam e aceleram o processo. Tudo que você conseguiria fazer com um for()
pode ser realizado com funções da família apply()
.
Aplica uma função nas margens de um array qualquer. Geralmente é aplicado em uma matriz/dataframe de forma a executar uma mesma função em todas as linhas ou colunas daquele objeto. Recebe como argumento um array, a marginal sobre a qual a função será aplicada (linha ou coluna) e a função.
É uma função que é aplicada em cada elemento de um vetor ou cada nó de uma lista. O output é uma lista obrigatoriamente. Recebe como argumentos um vetor/lista e uma função.
Similar ao lapply, porém a saída geralmente é simplificada, sendo apenas um vetor. Caso sua saída seja mais de um elemento, a saída deixa de ser um vetor e passa a ser uma matriz. Recebe como argumentos um vetor/lista e uma função. A diferença para o lapply é que o sapply tenta simplificar o resultado, retornando assim um vetor ou algo parecido.
Função com o objetivo de aplicar funções em grupos diferentes. Suponha que você tenha um dataframe com 2 colunas, uma com altura e outra com gênero, e você queira calcula a média de idade para cada um dos gẽneros, então neste caso a função tapply se aplica perfeitamente. Recebe como argumentos um vetor, um vetor com os fatores que irão estratificar o resultado e a função a ser aplicada em cada estrato.
Abaixo, códigos em R que mostram como fazer uso de cada uma das funções da família de funções apply.
################################
###### APPLY #####
################################
# matriz com 20 colunas e 10 linhas
x <- matrix(rnorm(200), ncol=20)
# média na linha (MARGIN = 1)
media_linha <- apply(x, MARGIN = 1, mean) # aplicar a função mean nas linhas
# média na coluna (MARGIN = 2)
media_coluna <- apply(x, MARGIN = 2, mean) # aplicar a função mean nas colunas
################################
###### LAPPLY #####
################################
# Uma lista qualquer com 7 vetores de temperaturas em cada dia
temp <- list(
c(3, 7, 9, 6, -1),
c(6, 9, 12, 13, 5),
c(4, 8, 3, -1, -3),
c(1, 4, 7, 2, -2),
c(5, 7, 9, 4, 2),
c(-3, 5, 8, 9, 4),
c(3, 6, 9, 4, 1)
)
# Temperatura mínima em cada dia. Retorna uma lista.
lapply(temp, min)
# Temperatura máxima em cada dia. Retorna uma lista.
lapply(temp, max)
# Temperatura média em cada dia. Retorna uma lista.
lapply(temp, mean)
################################
###### SAPPLY #####
################################
# Temperatura mínima em cada dia. Retorna um vetor.
sapply(temp, min)
# Temperatura máxima em cada dia. Retorna um vetor.
sapply(temp, max)
# Temperatura média em cada dia. Retorna um vetor.
sapply(temp, mean)
# Teste que retorna apenas em formato diferente, mas com resultados iguais
unlist(lapply(temp, max)) == sapply(temp, max)
# Função que calcula a média do mínimo e máximo de um vetor
extremes_avg <- function(x) {
avg <- mean(c(min(x), max(x)))
return(avg)
}
# Usando ela com o sapply(). Poderíamos usar ela em lapply() ou apply().
sapply(temp, extremes_avg)
PACOTES
Como comentado anteriormente, você pode fazer uso de funcionalidades de pacotes do R. Neste caso, você precisa adicionar esse pacote no conjunto de bibliotecas disponíveis no R para que seja possível usar suas funções.
Isto é necessário porque quando iniciamos o RStudio apenas alguns pacotes básicos são carregados automaticamente. Para que os outros também sejam carregados, é preciso acioná-los.
Abaixo, veremos como fazer a instalação de pacotes bem como seu carregamento no RStudio.
################################
##### INSTALAR #####
################################
# Além dessa opção você pode instalar pacotes diretamente no painel inferior direito do RStudio
install.packages("dplyr")
install.packages(c("dplyr", "data.table"))
################################
##### CARREGAR #####
################################
# Forma tradicional. Aqui, não precisamos das aspas porque o R já reconhece que há o pacote no ambiente
require(dplyr)
require(data.table)
# Alternativa para no momento de carregamento do pacote não aparecerem mensagens
suppressMessages(require(dplyr))
suppressMessages(require(data.table))
# Acionando todas as funções disponíveis no pacote
help(dplyr)
help(data.table)
REFERÊNCIAS
Wickham, Hadley. 2014. Advanced R. CRC Press.
LS0tCnRpdGxlOiA8Y2VudGVyPiA8aDI+IDxiPlByb2dyYW1hw6fDo28gZW0gUiAtIEludGVybWVkacOhcmlvIDwvYj4gPC9oMj4gPC9jZW50ZXI+IAphdXRob3I6IDxjZW50ZXI+IEZyYW5rIE1hZ2FsaMOjZXMgZGUgUGluaG8gLSBJQk1FQy9NRyA8L2NlbnRlcj4KZ3JhcGhpY3M6IHllcwpsaW5rY29sb3I6IGJsdWUKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGNlcnVsZWFuCiAgICBmaWdfY2FwdGlvbjogeWVzCnJlZmVyZW5jZXM6Ci0gaWQ6IHdpY2toYW0yMDE0YWR2YW5jZWQKICB0aXRsZTogQWR2YW5jZWQgUgogIGF1dGhvcjoKICAtIGZhbWlseTogV2lja2hhbQogICAgZ2l2ZW46IEhhZGxleQogIHB1Ymxpc2hlcjogQ1JDIFByZXNzCiAgdHlwZTogYm9vawogIGlzc3VlZDoKICAgIHllYXI6IDIwMTQKLSBpZDogZGF0YWNhbXAKICB0aXRsZTogSW50ZXJtZWRpYXRlIFIKICBhdXRob3I6IAogIC0gZmFtaWx5OiBEYXRhQ2FtcAogICAgZ2l2ZW46IEluYwogIFVSTDogaHR0cHM6Ly93d3cuZGF0YWNhbXAuY29tL2NvdXJzZXMvaW50ZXJtZWRpYXRlLXIKICBpc3N1ZWQ6CiAgICB5ZWFyOiAyMDE3Ci0gaWQ6IGN1cnNvUgogIHRpdGxlOiBDdXJzby1SCiAgYXV0aG9yOgogIC0gZmFtaWx5OgogICAgZ2l2ZW46CiAgVVJMOiBodHRwOi8vbWF0ZXJpYWwuY3Vyc28tci5jb20vCiAgaXNzdWVkOgogICAgeWVhcjogMjAxOApub2NpdGU6IHwgCiAgQHdpY2toYW0yMDE0YWR2YW5jZWQsIEBkYXRhY2FtcCwgQGN1cnNvUgotLS0KCkVzdGUgZG9jdW1lbnRvIHRlbSBjb21vIG9iamV0aXZvIGNvbnRyaWJ1aXIgcGFyYSBvIGVudGVuZGltZW50byBkZSBwcm9ncmFtYcOnw6NvIGVtIFtSXShodHRwczovL3d3dy5yLXByb2plY3Qub3JnLykgc29icmUgb3Mgc2VndWludGVzIHRlbWFzOgoKKiBPcGVyYWRvcmVzIHJlbGFjaW9uYWlzIGA9PWAgYDxgIGA+YCAgZSBsw7NnaWNvcyBgYW5kYCBgb3JgIGBub3RgOwoqIENvbmRpw6fDtWVzIGBpZmAgYGVsc2VgOwoqIExvb3BzOwoqIEZ1bsOnw7VlczsKKiBBIGZhbcOtbGlhIGRlIGZ1bsOnw7VlcyBhcHBseTsKKiBEYXRhczsKKiBQYWNvdGVzCgpCYXNpY2FtZW50ZSwgw6kgdW0gcmVzdW1vIGRvIGN1cnNvIFtJbnRlcm1lZGlhdGUgUl0oaHR0cHM6Ly93d3cuZGF0YWNhbXAuY29tL2NvdXJzZXMvaW50ZXJtZWRpYXRlLXIpIGRvIEBkYXRhY2FtcC4gUmVjb21lbmRvIHF1ZSB2b2PDqiBmYcOnYSBvIGN1cnNvIHBhcmEgdW0gZW50ZW5kaW1lbnRvIG1haXMgZGV0YWxoYWRvIGRvcyB0ZW1hcyBlc3R1ZGFkb3MuCgojIyMjICoqT1BFUkFET1JFUyBSRUxBQ0lPTkFJUyoqCgpDb211bWVudGUgdGVtb3MgcXVlIGZhemVyIGVzY29saGFzIGRhZGEgdW1hIGNvbmRpw6fDo28uIFNlIGFsZ3VtYSBjb2lzYSBmb3IgdmVyZGFkZSwgZW50w6NvIGlyZW1vcyBhZ2lyIGRlIHVtYSBtYW5laXJhLCBjYXNvIGNvbnRyw6FyaW8sIGVudMOjbyBwb2RlbW9zIHRvbWFyIG91dHJhIGHDp8Ojby4gVm9jw6ogcG9kZSBmYXplciBpc3NvIHRhbWLDqW0gZW0gdW1hIGFuw6FsaXNlIGRlIGRhZG9zIGUgcG9yIG1laW8gZG8gUi4gCgpBYmFpeG8sIHZlcmVtb3MgcXVhaXMgc8OjbyBvcyBvcGVyYWRvcmVzIHJlbGFjaW9uYWlzIHVzYWRvcyBwYXJhIHRlc3RhciBjb25kacOnw7VlcyBjb21vIGFzIGNpdGFkYXMgYWNpbWEuIAoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgIElHVUFMREFERSAgICAgICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIENvbXBhcmHDp8OjbyBkZSB2YWxvcmVzIGzDs2dpY29zClRSVUUgPT0gRkFMU0UKCiMgQ29tcGFyYcOnw6NvIGRlIHZhbG9yZXMgbnVtw6lyaWNvcwotNiAqIDE0ICE9IDE3IC0gMTAxCgojIENvbXBhcmHDp8OjbyBkZSBzdHJpbmdzCiJ1c2VSIiA9PSAidXNlciIKCiMgQ29tcGFyYcOnw6NvIGRlIHVtIHZhbG9yIG51bcOpcmljbyBjb20gb3V0cm8gbMOzZ2ljbwpUUlVFID09IDEKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgIE1BSU9SIE9VIE1FTk9SIFFVRSAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIENvbXBhcmHDp8OjbyBkZSBuw7ptZXJvcyAocmVzdWx0YWRvIGRlIGNhZGEgbGFkbykKLTYgKiA1ICsgMiA+PSAtMTAgKyAxCgojIENvbXBhcmHDp8OjbyBkZSBzdHJpbmdzCiJyYWluaW5nIiA8PSAicmFpbmluZyBkb2dzIgoKIyBDb21wYXJhw6fDo28gZGUgc3RyaW5ncwpUUlVFID4gRkFMU0UKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICBDT01QQVJBUiBWRVRPUkVTICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFZldG9yZXMgY29tIGFjZXNzb3MgYW8gTGlua2VkSW4gYW5kIEZhY2Vib29rCmxpbmtlZGluIDwtIGMoMTYsIDksIDEzLCA1LCAyLCAxNywgMTQpCmZhY2Vib29rIDwtIGMoMTcsIDcsIDUsIDE2LCA4LCAxMywgMTQpCgojIERpYXMgcG9wdWxhcmVzCmxpbmtlZGluID4gMTUKCiMgRGlhcyBjb20gcG91Y28gYWNlc3NvCmxpbmtlZGluIDw9IDUKCiMgRGlhcyBlbSBxdWUgbyBMaW5rZWRJbiBmb2kgbWFpcyBwb3B1bGFyIHF1ZSBvIEZhY2Vib29rCmxpbmtlZGluID4gZmFjZWJvb2sKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICBDT01QQVJBUiBNQVRSSVpFUyAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIE1hdHJpeiBjb20gYXMgdmlzdWFsaXphw6fDtWVzIGRvIExpbmtlZEluIGUgRmFjZWJvb2sKdmlld3MgPC0gbWF0cml4KGMobGlua2VkaW4sIGZhY2Vib29rKSwgbnJvdyA9IDIsIGJ5cm93ID0gVFJVRSkKCiMgUXVhbmRvIGFzIHZpc3VhbGl6YcOnw7VlcyBmb3JhbSBpZ3VhaXMgYSAxMz8Kdmlld3MgPT0gMTMKCiMgUXVhbmRvIGFzIHZpc3VhbGl6YcOnw7VlcyBmb3JhbSBtZW5vcmVzIG91IGlndWFpcyBhIDE0Pwp2aWV3cyA8PSAxNAoKIyBDb20gcXVlIGZyZXF1w6puY2lhIG8gRmFjZWJvb2sgdGVtIHZpc3VhbGl6YcOnw7VlcyBpZ3VhaXMgb3Ugc3VwZXJpb3JlcyDDoHMgZG8gTGlua2VkSW4gbXVsdGlwbGljYWRvIHBvciAyPwpzdW0oZmFjZWJvb2sgPj0gbGlua2VkaW4gKiAyKQpgYGAKCiMjIyMgKipPUEVSQURPUkVTIEzDk0dJQ09TKioKCkF0w6kgbyBtb21lbnRvLCBub3Mgb3BlcmFkb3JlcyByZWxhY2lvbmFpcyBlc3TDoXZhbW9zIHRlc3RhbmRvIGFwZW5hcyB1bWEgY29uZGnDp8Ojby4gQWdvcmEsIGNvbSBhIGluc2Vyw6fDo28gZG9zIG9wZXJhZG9yZXMgbMOzZ2ljb3MgcG9kZW1vcyB0ZXN0YXIgbWFpcyBkZSB1bWEgY29uZGnDp8OjbywgbyBxdWUgw6kgw7p0aWwgbm8gZGlhIGEgZGlhLiAKCkFiYWl4bywgY8OzZGlnb3MgZW0gUiBxdWUgZXhlbXBsaWZpY2FtIGNvbW8gdXNhciBvcyBvcGVyYWRvcmVzIGzDs2dpY29zLgoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgICAgICAmIGUgfCAgICAgICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFF1YW5kbyBvIExpbmtlZEluIGV4Y2VkZSAxMCBlIEZhY2Vib29rIG1lbm9yIHF1ZSAxMD8KbGlua2VkaW4gPiAxMCAmIGZhY2Vib29rIDwgMTAKCiMgUXVhbmRvIHVtIG91IG91dHJvIGZvaSB2aXNpdGFkbyBtYWlzIHF1ZSAxMiB2ZXplcz8KbGlua2VkaW4gPiAxMiB8IGZhY2Vib29rID4gMTIKCiMgUXVhbmRvIGFzIHZpc2l0YXMgZm9yYW0gbWFpb3JlcyBxdWUgMTEgZSBtZW5vcmVzIG91IGlndWFpcyBhIDE0Pwp2aWV3cyA+IDExICYgdmlld3MgPD0gMTQKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgICAgICBOT1QgICAgICAgICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIENvbnRyw6FyaW8gZG8gcmVzdWx0YWRvIGRhIGNvbmRpw6fDo28KISg1ID4gMykKCmBgYAoKIyMjIyAqKkNPTkRJw4fDlUVTKioKCkluZGVwZWRlbnRlIGRvIG9wZXJhZG9yIHV0aWxpemFkbyBhbnRlcmlvcm1lbnRlIChyZWxhY2lvbmFsIG91IGzDs2dpY28pIHTDrW5oYW1vcyBjb21vIHJlc3VsdGFkbyBvcyB2YWxvcmVzICoqVFJVRSoqIG91ICoqRkFMU0UqKi4gUG9yw6ltLCBuZW5odW1hIGHDp8OjbyBlcmEgdG9tYWRhIGEgcGFydGlyIGRvcyB0ZXN0ZXMuIAoKQWdvcmEsIHVzYXJlbW9zIGNvbmRpw6fDtWVzIGUgYSBwYXJ0aXIgZG9zIHJlc3VsdGFkb3MgdW1hIGHDp8OjbyBzZXLDoSBleGVjdXRhZGEgY29tbyBtb3N0cmFtIG9zIGPDs2RpZ29zIGVtIFIgYWJhaXhvLgoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgICAgICBJRkVMU0UgICAgICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIMOabHRpbW8gZGlhIGRlIHZpc3VhbGl6YcOnw6NvIGRvIExpbmtlZEluIGUgRmFjZWJvb2sKbGkgPC0gMTUKZmIgPC0gOQoKIyBJZmVsc2UgcGFyYSB0ZXN0YXIgY29uZGnDp8O1ZXMKaWYgKGxpID49IDE1ICYgZmIgPj0gMTUpIHsgICAgICAgICAgIyBUZXN0YXIgc2UgZW0gYW1ib3MgdGVtb3MgMTUgb3UgbWFpcyB2aXNpdGFzCiAgc21zIDwtIChsaSArIGZiKSAqIDIgICAgICAgICAgICAgICMgU2UgZm9yIHZlcmRhZGUsIGV4ZWN1dGUgYSBzb21hIGRhcyB2aXNpdGFzIG11bHRpcGxpY2FkbyBwb3IgMiAKfSBlbHNlIGlmIChsaSA8IDEwICYgZmIgPCAxMCkgeyAgICAgIyBDYXNvIGNvbnRyw6FyaW8sIHRlc3RlIHNlIGVtIGFtYm9zIHRlbW9zIG1lbm9zIHF1ZSAxMCB2aXNpdGFzCiAgc21zIDwtIChsaSArIGZiKSAvIDIgICAgICAgICAgICAgICMgU2UgZm9yIHZlcmRhZGUsIGV4ZWN1dGUgYSBtw6lkaWEgZGUgdmlzaXRhcwp9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIENhc28gY29udHLDoXJpbywgYXBlbmFzIHNvbWUgYXMgdmlzaXRhcwogIHNtcyA8LSAobGkgKyBmYikKfQoKIyByZXN1bHRhZG8KcHJpbnQoc21zKQpgYGAKCiMjIyMgKipMT09QUyoqCgpNdWl0YXMgdmV6ZXMgcG9kZSBzZXIgcHJlY2lzbyByZWVzY3JldmVyIG8gc2V1IGPDs2RpZ28gZW0gZnVuw6fDo28gZGEgbmVjZXNzaWRhZGUgZGUgc2UgcmVwZXRpciB1bWEgYXRpdmlkYWRlLiBJc3NvIHBvZGUgc2VyIHRyYWJhbGhvc28gZSBjb25zdW1pciBiYXN0YW50ZSB0ZW1wby4gRmVsaXptZW50ZSwgdGVtb3MgZW0gcHJvZ3JhbWHDp8OjbyBhIG9ww6fDo28gZGUgdXNhciBgbG9vcHNgIChubyBSLCBhcyBmdW7Dp8O1ZXMgYGZvcigpYCwgYHdoaWxlKClgIGUgYHJlcGVhdCgpYCkuIAoKTm9zIGPDs2RpZ29zIGFiYWl4bywgdGVtb3MgZXhlbXBsb3MgZGUgY29tbyB1c2FyIG9zIGBsb29wc2Agbm8gUi4KCmBgYHtyfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjICAgICAgV0hJTEUgTE9PUCAgICAgICAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBVbWEgdmFyacOhdmVsIGRlIHZlbG9jaWRhZGUKc3BlZWQgPC0gNjQKCiMgRW5xdWFudG8gYSB2ZWxvY2lkYWRlIGZvciBtYWlvciBxdWUgMzAgZXhlY3V0ZQp3aGlsZSAoc3BlZWQgPiAzMCApIHsKICBwcmludCgnRGVzYWNlbGVyYW5kbyEnKQogIHNwZWVkIDwtIHNwZWVkIC0gNyAgICMgRGVzYWNlbGVyYXIgYSB2ZWxvY2lkYWRlICAgICAgICAKfQojIE1vc3RyZSBvIHJlc3VsdGFkbwpwcmludChzcGVlZCkKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgICAgRk9SIExPT1AgICAgICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojICBWZXJzw6NvIDEKZm9yICh2aWV3cyBpbiBsaW5rZWRpbikgeyAgICAgICAjIFBhcmEgY2FkYSB2YWxvciBkYSBtYXRyaXogdmlld3MgcXVlIGV4aXN0ZSBubyB2ZXRvciBsaW5rZWRpbgogIHByaW50KHZpZXdzKSAgICAgICAgICAgICAgICAgICMgTW9zdHJlIG8gdmFsb3IKfQoKIyBWZXJzw6NvIDIKZm9yIChpIGluIDE6bGVuZ3RoKGxpbmtlZGluKSkgeyAjIFBhcmEgY2FkYSDDrW5kaWNlIGRhIHNlcXXDqm5jaWEgZGUgMSBhIGxlbmd0aChsaW5rZWRpbikgCiAgcHJpbnQobGlua2VkaW5baV0pICAgICAgICAgICAgIyBNb3N0cmUgbyB2YWxvciBkbyB2ZXRvciBkbyByZXNwZWN0aXZvIMOtbmRpY2UKfQoKIyBWZXJzw6NvIDM6IFVzYW5kbyBhIGZ1bsOnw6NvIHNlcV9hbG9uZy4gRWxhIGNyaWEgdW0gdmV0b3IgCiMgZGUgaW50ZWlyb3MgY29tIMOtbmRpY2VzIHBhcmEgYWNvbXBhbmhhciBvIG9iamV0by4gCmZvciAoaSBpbiBzZXFfYWxvbmcobGlua2VkaW4pKSB7ICMgUGFyYSBjYWRhIMOtbmRpY2UgZG8gdmV0b3IgbGlua2RlZGluCiAgcHJpbnQobGlua2VkaW5baV0pICAgICAgICAgICAgICMgTW9zdHJlIG9zIHJlc3VsdGFkb3MKfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjICAgTE9PUCBTT0JSRSBVTUEgTElTVEEgICAjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgQ3JpYW5kbyB1bWEgbGlzdGEKbnljIDwtIGxpc3QocG9wID0gODQwNTgzNywgYmFpcnJvcyA9IGMoIk1hbmhhdHRhbiIsICJCcm9ueCIsICJCcm9va2x5biIsICJRdWVlbnMiLCAiU3RhdGVuIElzbGFuZCIpLCAKICAgICAgICAgICAgY2FwaXRhbCA9IEZBTFNFKQoKIyBWZXJzw6NvIDEKZm9yICh2YWx1ZSBpbiBueWMpIHsgICAgICAgICAgICAgIyBQYXJhIGNhZGEgaXRlbSBkYSBsaXN0YSAKICBwcmludCh2YWx1ZSkgICAgICAgICAgICAgICAgICAgIyBNb3N0cmUgb3MgdmFsb3JlcyBjb250aWRvcyBlbSBjYWRhIGl0ZW0gZGEgbGlzdGEKfQoKIyBWZXJzw6NvIDIKZm9yIChpIGluIDE6bGVuZ3RoKG55YykpIHsgICAgICAgIyBQYXJhIGNhZGEgw61uZGljZSBkYSBzZXF1w6puY2lhIGRlIDEgYXTDqSBvIHRhbWFuaG8gZGUgaXRlbnMgbmEgbGlzdGEKICBwcmludChueWNbW2ldXSkgICAgICAgICAgICAgICAgIyBNb3N0cmUgb3MgdmFsb3JlcyBjb250aWRvcyBlbSBjYWRhIGl0ZW0gZGEgbGlzdGEgdXNhbmRvIG8gw61uZGljZQp9CgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMgICBMT09QIFNPQlJFIFVNQSBNQVRSSVogICMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBDcmlhciB1bWEgbWF0cml6CnR0dCA8LSBtYXRyaXgoYygiTyIsIE5BLCAiWCIsIE5BLCAiTyIsIE5BLCAiWCIsICJPIiwgIlgiKSwgbnJvdyA9IDMsIG5jb2wgPSAzKQoKIyBFeGVjdXRhciBvIGxvb3AgCmZvciAoaSBpbiAxOm5yb3codHR0KSkgeyAgICAgICAgIyBQYXJhIGNhZGEgbGluaGEgZGEgbWF0cml6ICgxOm5yb3codHR0KSBjcmlhcsOhIG9zIMOtbmRpY2VzIGRhcyBsaW5oYXMpCiAgZm9yIChqIGluIDE6bmNvbCh0dHQpKSB7ICAgICAgIyBQYXJhIGNhZGEgY29sdW5hIGRhIG1hdHJpeiAoMTpuY29sKHR0dCkgY3JpYXLDoSBvcyDDrW5kaWNlcyBkYXMgY29sdW5hcykKICBwcmludChwYXN0ZSgiTmEgbGluaGEiLGksImUgY29sdW5hIixqLCJ0ZW1vcyIsdHR0W2ksal0pKSAgIyBNb3N0cmUgb3MgcmVzdWx0YWRvcyAKICB9Cn0KCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgIExPT1AgQ09NIENPTkRJw4fDlUVTICAgICMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgRXhlY3V0YXIgbyBsb29wCmZvciAobGkgaW4gbGlua2VkaW4pIHsgICAgICAgICAgICAjIFBhcmEgY2FkYSDDrW5kaWNlIGRvIHZldG9yIGxpbmtlZGluIChjaGFtYW1vcyBvIMOtbmRpY2UgZGUgbGkpCiAgaWYgKGxpID4gMTApIHsgICAgICAgICAgICAgICAgICAjIFNlIG8gw61uZGljZSBmb3IgbWFpb3IgcXVlIDEwCiAgICBwcmludCgiVm9jw6ogw6kgcG9wdWxhciIpICAgICAgICMgTW9zdHJlIGEgbWVuc2FnZW0gIlZvY8OqIMOpIHBvcHVsYXIiCiAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAjIENhc28gY29udHLDoXJpbywgc2UgbyDDrW5kaWNlIGZvciA8PSAxMAogICAgcHJpbnQoIlNlamEgbWFpcyB2aXPDrXZlbCEiKSAgICMgTW9zdHJlIG91dHJhIG1lbnNhZ2VtICJTZWphIG1haXMgdmlzw612ZWwiCiAgfQp9CgpgYGAKCiMjIyMgKipGVU7Dh8OVRVMqKgoKRHVyYW50ZSBhIHByb2dyYW1hw6fDo28gZW0gUiB2b2PDqiBwb2RlIGZhemVyIHVzbyBkZSBmdW7Dp8O1ZXMgInByb250YXMiIGRlIHBhY290ZXMgZG8gUiwgbWFzIGVtIGFsZ3VucyBjYXNvcyB2b2PDqiBwb2RlIG9wdGFyIHBvciBjcmlhciBzdWEgcHLDs3ByaWEgZnVuw6fDo28uIERlc3RhIGZvcm1hLCB2b2PDqiBldml0YSByZXBldGlyIGPDs2RpZ29zIHBhcmEgZXhlY3V0YXIgYSBtZXNtYSB0YXJlZmEuCgpOb3MgY8OzZGlnb3MgYWJhaXhvLCB0ZW1vcyBjw7NkaWdvcyBlbSBSIHF1ZSBtb3N0cmFtIGNvbW8gYWNlc3NhciBhIGRvY3VtZW50YcOnw6NvIGRlIHVtYSBmdW7Dp8OjbyBuYXRpdmEgZG8gUiBlIGNvbW8gY3JpYXIgc3VhIHByw7NwcmlhIGZ1bsOnw6NvLiAKCmBgYHtyfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjICAgRlVOw4fDlUVTIE5BVElWQVMgICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFBhcmEgYWNlc3NhciBhIGRvY3VtZW50YcOnw6NvIGRlIHVtYSBmdW7Dp8OjbyBuYXRpdmEuCmhlbHAobWVhbikKaGVscChzZCkKCiMgRXhpc3RlbSBhcmd1bWVudG9zIG9icmlnYXTDs3Jpb3MgZSBvcGNpb25haXMgZW0gZnVuw6fDtWVzLiBFeGVtcGxvOgpzZCh4LCBuYS5ybSA9IEZBTFNFKQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjICAgRlVOw4fDlUVTIFBSw5NQUklBUyAgICAgICAjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgQ3JpYW5kbyBhIGZ1bsOnw6NvIHF1YWRyYWRvIHF1ZSByZWNlYmUgbyBhcmd1bWVudG8geApxdWFkcmFkbyA8LSBmdW5jdGlvbih4KSB7CiByZXN1bHQgPC0geF4yCiByZXR1cm4ocmVzdWx0KQp9CgojIFVzYW5kbyBhIGZ1bsOnw6NvIHF1YWRyYWRvCnF1YWRyYWRvKDEyKQoKIyBDcmlhbmRvIGEgZnVuw6fDo28gc29tYXJfYWJzKCkgcXVlIHJlY2ViZSBvcyBhcmd1bWVudG9zIHggZSB5CnNvbWFyX2FicyA8LSBmdW5jdGlvbih4LCB5KSB7CiAgcmVzdWx0IDwtIGFicyh4KSArIGFicyh5KQogIHJldHVybihyZXN1bHQpCn0KCiMgVXNhbmRvIGEgZnVuw6fDo28gc29tYXJfYWJzCnNvbWFyX2FicygtMiwgMykKCgojIEV4cGFuZGlyIGEgZnVuw6fDo28gcXVhZHJhZG8oKSBwYXJhIHJlY2ViZXIgb3MgYXJndW1lbnRvcyB4IGUgcHJpbnRfaW5mbwpxdWFkcmFkbyA8LSBmdW5jdGlvbih4LCBwcmludF9pbmZvID0gVCkgeyAgICAgICAgICMgYXJndW1lbnRvcyBkYSBmdW7Dp8OjbwogIHkgPC0geCBeIDIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGFyZWZhIGEgc2VyIGV4ZWN1dGFkYQogIGlmIChwcmludF9pbmZvID09IFQpIHsgICAgICAgICAgICAgICAgICAgICAgICAgICMgdmVyaWZpY2FyIG8gYXJndW1lbnRvIHByaW50X2luZm8KICAgIHByaW50KHBhc3RlKHgsICdlbGV2YWRvIGFvIHF1YWRyYWRvIMOpJyx5KSkgICAgIyBzZSBUUlVFLCBtb3N0cmFyIGEgbWVuc2FnZW0KICB9CiAgcmV0dXJuKHkpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhIGZ1bsOnw6NvIGRldmUgcmV0b3JuYXIgY29tbyBzYcOtZG8gb3MgdmFsb3JlcyBkZSB5Cn0KCnF1YWRyYWRvKDUpCnF1YWRyYWRvKDUsIHByaW50X2luZm89RikKYGBgCgojIyMjIyAqKkEgRkFNw41MSUEgREUgRlVOw4fDlUVTIEFQUExZKioKCkVzY3JldmVyIGxvb3BzIGRhIGZvcm1hIHRyYWRpY2lvbmFsIHBvZGUgc2VyIHVtYSB2ZXJkYWRlaXJhIHRvcnR1cmEsIHRhbnRvIHBhcmEgbyB1c3XDoXJpbyBxdWFudG8gcGFyYSBvIGNvbXB1dGFkb3IgZW0gZnVuw6fDo28gZGUgcGVyZm9ybWFuY2UuIAoKRW0gZnVuw6fDo28gZGlzc28sIHN1cmdpcmFtIGFzIGZ1bsOnw7VlcyBgYXBwbHkoKWAgcXVlIHPDo28gbXVpdG8gw7p0ZWlzIG5hIG1hbmlwdWxhw6fDo28gZGUgZGFkb3MgZSBzaW1wbGlmaWNhbSBlIGFjZWxlcmFtIG8gcHJvY2Vzc28uIFR1ZG8gcXVlIHZvY8OqIGNvbnNlZ3VpcmlhIGZhemVyIGNvbSB1bSBgZm9yKClgIHBvZGUgc2VyIHJlYWxpemFkbyBjb20gZnVuw6fDtWVzIGRhIGZhbcOtbGlhIGBhcHBseSgpYC4gCgoqICoqYGFwcGx5KClgKio6CgpBcGxpY2EgdW1hIGZ1bsOnw6NvIG5hcyBtYXJnZW5zIGRlIHVtIGFycmF5IHF1YWxxdWVyLiBHZXJhbG1lbnRlIMOpIGFwbGljYWRvIGVtIHVtYSBtYXRyaXovZGF0YWZyYW1lIGRlIGZvcm1hIGEgZXhlY3V0YXIgdW1hIG1lc21hIGZ1bsOnw6NvIGVtIHRvZGFzIGFzIGxpbmhhcyBvdSBjb2x1bmFzIGRhcXVlbGUgb2JqZXRvLiBSZWNlYmUgY29tbyBhcmd1bWVudG8gdW0gYXJyYXksIGEgbWFyZ2luYWwgc29icmUgYSBxdWFsIGEgZnVuw6fDo28gc2Vyw6EgYXBsaWNhZGEgKGxpbmhhIG91IGNvbHVuYSkgZSBhIGZ1bsOnw6NvLgoKKiAqKmBsYXBwbHkoKWAqKjoKCsOJIHVtYSBmdW7Dp8OjbyBxdWUgw6kgYXBsaWNhZGEgZW0gY2FkYSBlbGVtZW50byBkZSB1bSB2ZXRvciBvdSBjYWRhIG7DsyBkZSB1bWEgbGlzdGEuIE8gb3V0cHV0IMOpIHVtYSBsaXN0YSBvYnJpZ2F0b3JpYW1lbnRlLiBSZWNlYmUgY29tbyBhcmd1bWVudG9zIHVtIHZldG9yL2xpc3RhIGUgdW1hIGZ1bsOnw6NvLgoKKiAqKmBzYXBwbHkoKWAqKjoKClNpbWlsYXIgYW8gbGFwcGx5LCBwb3LDqW0gYSBzYcOtZGEgZ2VyYWxtZW50ZSDDqSBzaW1wbGlmaWNhZGEsIHNlbmRvIGFwZW5hcyB1bSB2ZXRvci4gQ2FzbyBzdWEgc2HDrWRhIHNlamEgbWFpcyBkZSB1bSBlbGVtZW50bywgYSBzYcOtZGEgZGVpeGEgZGUgc2VyIHVtIHZldG9yIGUgcGFzc2EgYSBzZXIgdW1hIG1hdHJpei4gUmVjZWJlIGNvbW8gYXJndW1lbnRvcyB1bSB2ZXRvci9saXN0YSBlIHVtYSBmdW7Dp8Ojby4gQSBkaWZlcmVuw6dhIHBhcmEgbyBsYXBwbHkgw6kgcXVlIG8gc2FwcGx5IHRlbnRhIHNpbXBsaWZpY2FyIG8gcmVzdWx0YWRvLCByZXRvcm5hbmRvIGFzc2ltIHVtIHZldG9yIG91IGFsZ28gcGFyZWNpZG8uCgoqICoqYHRhcHBseSgpYCoqOgoKRnVuw6fDo28gY29tIG8gb2JqZXRpdm8gZGUgYXBsaWNhciBmdW7Dp8O1ZXMgZW0gZ3J1cG9zIGRpZmVyZW50ZXMuIFN1cG9uaGEgcXVlIHZvY8OqIHRlbmhhIHVtIGRhdGFmcmFtZSBjb20gMiBjb2x1bmFzLCB1bWEgY29tIGFsdHVyYSBlIG91dHJhIGNvbSBnw6puZXJvLCBlIHZvY8OqIHF1ZWlyYSBjYWxjdWxhIGEgbcOpZGlhIGRlIGlkYWRlIHBhcmEgY2FkYSB1bSBkb3MgZ+G6vW5lcm9zLCBlbnTDo28gbmVzdGUgY2FzbyBhIGZ1bsOnw6NvIHRhcHBseSBzZSBhcGxpY2EgcGVyZmVpdGFtZW50ZS4gUmVjZWJlIGNvbW8gYXJndW1lbnRvcyB1bSB2ZXRvciwgdW0gdmV0b3IgY29tIG9zIGZhdG9yZXMgcXVlIGlyw6NvIGVzdHJhdGlmaWNhciBvIHJlc3VsdGFkbyBlIGEgZnVuw6fDo28gYSBzZXIgYXBsaWNhZGEgZW0gY2FkYSBlc3RyYXRvLgoKQWJhaXhvLCBjw7NkaWdvcyBlbSBSIHF1ZSBtb3N0cmFtIGNvbW8gZmF6ZXIgdXNvIGRlIGNhZGEgdW1hIGRhcyBmdW7Dp8O1ZXMgZGEgZmFtw61saWEgZGUgZnVuw6fDtWVzIGFwcGx5LiAKCmBgYHtyfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMgICAgICAgQVBQTFkgICAgICAgICAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBtYXRyaXogY29tIDIwIGNvbHVuYXMgZSAxMCBsaW5oYXMKeCA8LSBtYXRyaXgocm5vcm0oMjAwKSwgbmNvbD0yMCkKCiMgbcOpZGlhIG5hIGxpbmhhIChNQVJHSU4gPSAxKQptZWRpYV9saW5oYSA8LSBhcHBseSh4LCBNQVJHSU4gPSAxLCBtZWFuKSAgICMgYXBsaWNhciBhIGZ1bsOnw6NvIG1lYW4gbmFzIGxpbmhhcwoKIyBtw6lkaWEgbmEgY29sdW5hIChNQVJHSU4gPSAyKQptZWRpYV9jb2x1bmEgPC0gYXBwbHkoeCwgTUFSR0lOID0gMiwgbWVhbikgICMgYXBsaWNhciBhIGZ1bsOnw6NvIG1lYW4gbmFzIGNvbHVuYXMKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMjIyAgICAgICBMQVBQTFkgICAgICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFVtYSBsaXN0YSBxdWFscXVlciBjb20gNyB2ZXRvcmVzIGRlIHRlbXBlcmF0dXJhcyBlbSBjYWRhIGRpYQp0ZW1wIDwtIGxpc3QoCiAgYygzLCA3LCAgOSwgIDYsIC0xKSwKICBjKDYsICA5LCAxMiwgMTMsICA1KSwKICBjKDQsICA4LCAgMywgLTEsIC0zKSwKICBjKDEsICA0LCAgNywgIDIsIC0yKSwKICBjKDUsIDcsIDksIDQsIDIpLAogIGMoLTMsICA1LCAgOCwgIDksICA0KSwKICBjKDMsIDYsIDksIDQsIDEpCiAgKQoKIyBUZW1wZXJhdHVyYSBtw61uaW1hIGVtIGNhZGEgZGlhLiBSZXRvcm5hIHVtYSBsaXN0YS4KbGFwcGx5KHRlbXAsIG1pbikKCiMgVGVtcGVyYXR1cmEgbcOheGltYSBlbSBjYWRhIGRpYS4gUmV0b3JuYSB1bWEgbGlzdGEuIApsYXBwbHkodGVtcCwgbWF4KQoKIyBUZW1wZXJhdHVyYSBtw6lkaWEgZW0gY2FkYSBkaWEuIFJldG9ybmEgdW1hIGxpc3RhLgpsYXBwbHkodGVtcCwgbWVhbikKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMjIyAgICAgICBTQVBQTFkgICAgICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFRlbXBlcmF0dXJhIG3DrW5pbWEgZW0gY2FkYSBkaWEuIFJldG9ybmEgdW0gdmV0b3IuCnNhcHBseSh0ZW1wLCBtaW4pCgojIFRlbXBlcmF0dXJhIG3DoXhpbWEgZW0gY2FkYSBkaWEuIFJldG9ybmEgdW0gdmV0b3IuCnNhcHBseSh0ZW1wLCBtYXgpCgojIFRlbXBlcmF0dXJhIG3DqWRpYSBlbSBjYWRhIGRpYS4gUmV0b3JuYSB1bSB2ZXRvci4Kc2FwcGx5KHRlbXAsIG1lYW4pCgojIFRlc3RlIHF1ZSByZXRvcm5hIGFwZW5hcyBlbSBmb3JtYXRvIGRpZmVyZW50ZSwgbWFzIGNvbSByZXN1bHRhZG9zIGlndWFpcwp1bmxpc3QobGFwcGx5KHRlbXAsIG1heCkpID09IHNhcHBseSh0ZW1wLCBtYXgpCgojIEZ1bsOnw6NvIHF1ZSBjYWxjdWxhIGEgbcOpZGlhIGRvIG3DrW5pbW8gZSBtw6F4aW1vIGRlIHVtIHZldG9yCmV4dHJlbWVzX2F2ZyA8LSBmdW5jdGlvbih4KSB7CiBhdmcgPC0gbWVhbihjKG1pbih4KSwgbWF4KHgpKSkKIHJldHVybihhdmcpCn0KCiMgVXNhbmRvIGVsYSBjb20gbyBzYXBwbHkoKS4gUG9kZXLDrWFtb3MgdXNhciBlbGEgZW0gbGFwcGx5KCkgb3UgYXBwbHkoKS4Kc2FwcGx5KHRlbXAsIGV4dHJlbWVzX2F2ZykKYGBgCgojIyMjIyAqKlRSQUJBTEhBTkRPIENPTSBEQVRBUyoqCgpBIGRhdGEgb3UgdGVtcG8gw6kgdW0gZGFkbyBxdWUgbmVjZXNzaXRhIGRlIHVtYSBtYW5pcHVsYcOnw6NvIGVzcGVjw61maWNhLiBDb21vIHRyYWJhbGhhcmVtb3MgY29tIHPDqXJpZXMgdGVtcG9yYWlzLCDDqSBkZSBzdW1hIGltcG9ydMOibmNpYSBvIGJvbSBlbnRlbmRpbWVudG8gZGUgY29tbyBsaWRhciBjb20gZGFkb3MgdGVtcG9yYWlzIHF1ZSwgbmVjZXNzw6FyaWFtZW50ZSwgc2Vyw6NvIGFybWF6ZW5hZG9zIGNyb25vbMOzZ2ljYW1lbnRlLiAKCk5vIFIgdGVtb3MgdsOhcmlhcyBmb3JtYXMgZGUgdHJhYmFsaGFyIGNvbSBkYXRhcy4gQWJhaXhvLCBhbGd1bnMgZXhlbXBsb3MgcXVlIHBvZGVtIG5vcyBhanVkYXIuCgpgYGB7cn0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMgICAgREFUQS9URU1QTyAgICAgICAgIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgQSBkYXRhIGF0dWFsLiBBIGZ1bsOnw6NvIHByaW1pdGl2YSBTeXMuRGF0ZSgpIGNyaWEgdW1hIGRhdGEgbm8gZm9ybWF0byBjb3JyZXRvCnRvZGF5IDwtIFN5cy5EYXRlKCkKCiMgU2UgZXhjbHVpcm1vcyBhIGNsYXNzZSB2ZW1vcyBxdWUgdGVyZW1vcyB1bSBuw7ptZXJvIHF1ZSBuw6NvIMOpIGludGVycHJldMOhdmVsIAp1bmNsYXNzKHRvZGF5KQoKIyBBIGhvcmEgY29ycmVudGUKbm93IDwtIFN5cy50aW1lKCkKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgIENSSUFORE8gREFUQS9URU1QTyAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIERlZmluaW5kbyBkYXRhcyBlbSB1bSBmb3JtYXRvIHF1YWxxdWVyIGNvbW8gY2hhcmFjdGVyCnN0cjEgPC0gIjIwMTItMy0xNSIKc3RyMiA8LSAiMDIvMjcvOTIiCgojIENvbnZlcnRlbmRvIHBhcmEgZGF0YXMgbm8gZm9ybWF0byBxdWUgbyBSIHJlY29uaGVjZQpkYXRlMSA8LSBhcy5EYXRlKHN0cjEsIGZvcm1hdCA9ICIlWS0lbS0lZCIpCmRhdGUyIDwtIGFzLkRhdGUoc3RyMiwgZm9ybWF0ID0gIiVtLyVkLyV5IikKCiMgRGVmaW5pbmRvIHRlbXBvIGVtIGZvcm1hdG8gZGUgc3RyaW5nCnN0cjEgPC0gIjIwMTItMy0xMiAxNDoyMzowOCIKCiMgQ29udmVydGVyIGFzIHN0cmluZyBwYXJhIHVtIG9iamVjdG8gUE9TSVhjdAp0aW1lMSA8LSBhcy5QT1NJWGN0KHN0cjEsIGZvcm1hdCA9ICIlWS0lbS0lZCAlVCIpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjICBDw4FMQ1VMTyBEQVRBL1RFTVBPICAgIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgRGF0YXMKZGF5MSA8LSBhcy5EYXRlKCIyMDE3LTAzLTEyIikKZGF5MiA8LSBhcy5EYXRlKCIyMDE3LTAzLTE0IikKZGF5MyA8LSBhcy5EYXRlKCIyMDE3LTAzLTE5IikKZGF5NCA8LSBhcy5EYXRlKCIyMDE3LTAzLTI1IikKZGF5NSA8LSBhcy5EYXRlKCIyMDE3LTAzLTMwIikKCiMgRGlmZXJlbsOnYSBlbnRyZSBvIHByaW1laXJvIGUgbyDDumx0aW1vIGRpYQpkYXk1LWRheTEKCiMgQ3JpYXIgdW0gdmV0b3IgY29tIGFzIGRhdGFzCnBpenphIDwtIGMoZGF5MSwgZGF5MiwgZGF5MywgZGF5NCwgZGF5NSkKcGl6emEKCiMgQ3JpYXIgdW0gdmV0b3IgY29tIGEgZGlmZXJlbsOnYSBlbnRyZSBvcyBkaWFzIGNvbnNlY3V0aXZvcwpkYXlfZGlmZiA8LSBkaWZmKHBpenphKQpkYXlfZGlmZgoKIyBQZXLDrW9kbyBtw6lkaW8gZW50cmUgZG9pcyBkaWFzIGNvbnNlY3V0aXZvcyAKbWVhbihkYXlfZGlmZikKYGBgCgojIyMjIyAqKlBBQ09URVMqKgoKQ29tbyBjb21lbnRhZG8gYW50ZXJpb3JtZW50ZSwgdm9jw6ogcG9kZSBmYXplciB1c28gZGUgZnVuY2lvbmFsaWRhZGVzIGRlIHBhY290ZXMgZG8gUi4gTmVzdGUgY2Fzbywgdm9jw6ogcHJlY2lzYSBhZGljaW9uYXIgZXNzZSBwYWNvdGUgbm8gY29uanVudG8gZGUgYmlibGlvdGVjYXMgZGlzcG9uw612ZWlzIG5vIFIgcGFyYSBxdWUgc2VqYSBwb3Nzw612ZWwgdXNhciBzdWFzIGZ1bsOnw7Vlcy4gCgpJc3RvIMOpIG5lY2Vzc8OhcmlvIHBvcnF1ZSBxdWFuZG8gaW5pY2lhbW9zIG8gUlN0dWRpbyBhcGVuYXMgYWxndW5zIHBhY290ZXMgYsOhc2ljb3Mgc8OjbyBjYXJyZWdhZG9zIGF1dG9tYXRpY2FtZW50ZS4gUGFyYSBxdWUgb3Mgb3V0cm9zIHRhbWLDqW0gc2VqYW0gY2FycmVnYWRvcywgw6kgcHJlY2lzbyBhY2lvbsOhLWxvcy4gCgpBYmFpeG8sIHZlcmVtb3MgY29tbyBmYXplciBhIGluc3RhbGHDp8OjbyBkZSBwYWNvdGVzIGJlbSBjb21vIHNldSBjYXJyZWdhbWVudG8gbm8gUlN0dWRpby4KCmBgYHtyfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyAgICAgIElOU1RBTEFSICAgICAgICAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBBbMOpbSBkZXNzYSBvcMOnw6NvIHZvY8OqIHBvZGUgaW5zdGFsYXIgcGFjb3RlcyBkaXJldGFtZW50ZSBubyBwYWluZWwgaW5mZXJpb3IgZGlyZWl0byBkbyBSU3R1ZGlvCmluc3RhbGwucGFja2FnZXMoImRwbHlyIikKaW5zdGFsbC5wYWNrYWdlcyhjKCJkcGx5ciIsICJkYXRhLnRhYmxlIikpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyAgICAgICBDQVJSRUdBUiAgICAgICAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBGb3JtYSB0cmFkaWNpb25hbC4gQXF1aSwgbsOjbyBwcmVjaXNhbW9zIGRhcyBhc3BhcyBwb3JxdWUgbyBSIGrDoSByZWNvbmhlY2UgcXVlIGjDoSBvIHBhY290ZSBubyBhbWJpZW50ZQpyZXF1aXJlKGRwbHlyKQpyZXF1aXJlKGRhdGEudGFibGUpCgojIEFsdGVybmF0aXZhIHBhcmEgbm8gbW9tZW50byBkZSBjYXJyZWdhbWVudG8gZG8gcGFjb3RlIG7Do28gYXBhcmVjZXJlbSBtZW5zYWdlbnMKc3VwcHJlc3NNZXNzYWdlcyhyZXF1aXJlKGRwbHlyKSkKc3VwcHJlc3NNZXNzYWdlcyhyZXF1aXJlKGRhdGEudGFibGUpKQoKIyBBY2lvbmFuZG8gdG9kYXMgYXMgZnVuw6fDtWVzIGRpc3BvbsOtdmVpcyBubyBwYWNvdGUKaGVscChkcGx5cikKaGVscChkYXRhLnRhYmxlKQpgYGAKCiMjIyMgKipSRUZFUsOKTkNJQVMqKg==