Conceitos Básicos

Um modelo probabilístico é uma descrição qualitativa de uma situação, fenômeno ou experimento cujo resultado é incerto. Para definir tal modelo seguimos os passos:

  1. Descrevemos os possívies resultados do experimento (especificamos o espaço amostral)
  2. Especificamos a lei probabilística, que atribui probabilidades aos resultados ou conjunto de resultados.

A probabilidade Pr(A) de um evento A é a proporção (aproximada) de vezes que o evento ocorre quando repetimos o experimento várias vezes, de maneira independente, sob as mesmas condições. Quanto maior o número de experimentos, melhor é esta aproximação.

Um evento é um resultado medido ou observado de um fenômeno, que aconteceu por chance.

Nas seções seguintes ilustraremos a ideia de probabilidade fazendo contagens de possibilidades e também por meio de experimentos computacionais usando o método de Monte Carlo.

Cartas de um baralho

Nesta seção utilizaremos mostraremos como utilizar o R para resolver problemas envolvendo objetos como cartas de um baralho. Embora os problemas listados abaixo possam resolvidos facilmente com uma calculadora, nosso objetivo é ilustrar o uso do R, com comandos que serão imprescidíveis em problemas bem mais complicados que abordaremos mais adiante. Para definir um baralho de cartas no R podemos proceder do seguinte modo, usando os comandos paste e expand.grid:

library(tidyverse)
library(gtools)
suits <- c("Diamonds", "Clubs", "Hearts", "Spades")
numbers <- c("Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King")
deck <- expand.grid(number=numbers, suit=suits)
deck2 <- paste(deck$number,deck$suit)
deck2
 [1] "Ace Diamonds"   "Deuce Diamonds"
 [3] "Three Diamonds" "Four Diamonds" 
 [5] "Five Diamonds"  "Six Diamonds"  
 [7] "Seven Diamonds" "Eight Diamonds"
 [9] "Nine Diamonds"  "Ten Diamonds"  
[11] "Jack Diamonds"  "Queen Diamonds"
[13] "King Diamonds"  "Ace Clubs"     
[15] "Deuce Clubs"    "Three Clubs"   
[17] "Four Clubs"     "Five Clubs"    
[19] "Six Clubs"      "Seven Clubs"   
[21] "Eight Clubs"    "Nine Clubs"    
[23] "Ten Clubs"      "Jack Clubs"    
[25] "Queen Clubs"    "King Clubs"    
[27] "Ace Hearts"     "Deuce Hearts"  
[29] "Three Hearts"   "Four Hearts"   
[31] "Five Hearts"    "Six Hearts"    
[33] "Seven Hearts"   "Eight Hearts"  
[35] "Nine Hearts"    "Ten Hearts"    
[37] "Jack Hearts"    "Queen Hearts"  
[39] "King Hearts"    "Ace Spades"    
[41] "Deuce Spades"   "Three Spades"  
[43] "Four Spades"    "Five Spades"   
[45] "Six Spades"     "Seven Spades"  
[47] "Eight Spades"   "Nine Spades"   
[49] "Ten Spades"     "Jack Spades"   
[51] "Queen Spades"   "King Spades"   

Por exemplo, calculemos qual é a probabilidade de obtermos King ao retirarmos a primeira carta do baralho. Como um baralho tem 52 cartas e temos 4 Kings, um de cada naipe, a probabilidade de retirarmos uma carta com King é:

4/52
[1] 0.07692308

Podemos reobter este resultado a partir das cartas do baralho. Inicialmente determinamos as cartas com King:

kings <- paste("King", suits)
kings
[1] "King Diamonds" "King Clubs"    "King Hearts"  
[4] "King Spades"  

Examinamos, entre as cartas do baralho, quais são que tem King:

deck2 %in% kings
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [9] FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
[17] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
[33] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
[41] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[49] FALSE FALSE FALSE  TRUE

O comando mean nos dá a proporção do número de resultados TRUE para o número de resultados FALSE:

mean( deck2 %in% kings)
[1] 0.07692308

que é aproximadamente 1/13, como esperado.

Calculemos agora qual é a probabilidade condicional de que a segunda carta seja King dado que a primeira carta for King. Como temos agora somente 3 cartas deste tipo e o baralho agora tem somente 51 cartas, esperamos que a probabilidade seja 3/51. Confirmemos este resultado em R.

Antes disso estudemos o comando permutations() que computa, para qualquer lista de tamanho n, todos diferentes modos que podemos selecionar r itens. Vejamos um exemplo: de quantos modos podemos selecionar 2 elementos de um grupo de 5 elementos?

permutations(5,2)
      [,1] [,2]
 [1,]    1    2
 [2,]    1    3
 [3,]    1    4
 [4,]    1    5
 [5,]    2    1
 [6,]    2    3
 [7,]    2    4
 [8,]    2    5
 [9,]    3    1
[10,]    3    2
[11,]    3    4
[12,]    3    5
[13,]    4    1
[14,]    4    2
[15,]    4    3
[16,]    4    5
[17,]    5    1
[18,]    5    2
[19,]    5    3
[20,]    5    4

Notemos que a ordem importa. Além disso números repetidos não ocorrem, pois uma vez que selecionamos um número, ele não aparece novamente. Opcionalmente o comando permutations pode ter um vetor como terceiro argumento. Por exemplo, façamos uma permutação (ou arranjo) de 4 números, 3,4,5,6 em grupos de 3 elementos. De outro modo, se temos uma caixa com 4 bolas marcadas com estes números, quais são os possíveis resultados ao selecionar 3 bolas aleatóriamente?

m <- permutations(4,3,c(3,4,5,6,7))
m
      [,1] [,2] [,3]
 [1,]    3    4    5
 [2,]    3    4    6
 [3,]    3    5    4
 [4,]    3    5    6
 [5,]    3    6    4
 [6,]    3    6    5
 [7,]    4    3    5
 [8,]    4    3    6
 [9,]    4    5    3
[10,]    4    5    6
[11,]    4    6    3
[12,]    4    6    5
[13,]    5    3    4
[14,]    5    3    6
[15,]    5    4    3
[16,]    5    4    6
[17,]    5    6    3
[18,]    5    6    4
[19,]    6    3    4
[20,]    6    3    5
[21,]    6    4    3
[22,]    6    4    5
[23,]    6    5    3
[24,]    6    5    4

Como vemos da matriz de saída do comando acima, o número de modos é 24, que pode ser obtido diretamente contando o número de linhas de m:

n <- nrow(m)
n
[1] 24

Façamos uma simulação de 6 escolhas aleatórias de 3 bolas

indice <- sample(n,6)
indice
[1] 13 23 20 15  2 16

Ou seja, as bolas selecionadas têm os números dados por:

m[indice,]
     [,1] [,2] [,3]
[1,]    5    3    4
[2,]    6    5    3
[3,]    6    3    5
[4,]    5    4    3
[5,]    3    4    6
[6,]    5    4    6

Exemplo:

Simule a seleção aleatória de de 5 números (0 a 9) de 7 dígitos (não mostre as possíveis seleções na tela).
Solução

numeros <- permutations(10,7,c(0:9))
n <- nrow(numeros)
n
[1] 604800

Selecionemos 5 números de 7 dígitos:

indice <- sample(n,5)
indice
[1] 149839  94593 349073 109609 408838
numeros[indice,]
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    2    5    3    4    7    9    6
[2,]    1    6    0    7    3    8    2
[3,]    5    7    9    3    8    4    0
[4,]    1    8    3    5    4    6    0
[5,]    6    7    8    4    9    5    1

Voltemos agora ao problema de calcular a probabilidade de que a segunda carta seja King dado que a primeira carta for King. Computemos todos os possíveis modos de escolher duas cartas, quando a ordem é relevante.

hands <- permutations(52,2,v=deck2)
nrow(hands)
[1] 2652

Ou seja, temos 2652 possibilidades. A primeira carta será selecionada da primeira coluna da matriz hands e similarmente com a segunda:

primeira_carta <- hands[,1]
segunda_carta <- hands[,2]

Vejamos em quantos casos a primeira carta é King:

k <- sum(primeira_carta %in% kings)
k
[1] 204

Ou seja, 204 casos. Para determinar a probabilidade condicional devemos agora determinar qual é a fração destes 204 casos em que temos King na segunda carta:

sum(primeira_carta %in% kings & segunda_carta %in% kings)/sum(primeira_carta %in% kings)
[1] 0.05882353

que é igual a 3/51, como esperado.

Notemos ainda que o mesmo resultado poderia ser obtido utilizando valores esperados:

mean(primeira_carta %in% kings & segunda_carta %in% kings)/mean(primeira_carta %in% kings)
[1] 0.05882353

Estas expressões acima são formas diferentes da relação fundamental \[ Pr(B|A)=\frac{Pr(A \cap B)}{Pr(A)} \] Suponhamos agora que a ordem não seja importante. No jogo blackjack se obtivermos um A e uma carta de face ou 10, teremos um 21 natural, a a vitória é instantânea. Queremos calcular a probabilidade disso acontecer. Notemos que agora devemos enumerar combinações e não permutações, pois a ordem não importa. Um A e um King ou um King e A são a mesma coisa e não queremos contar este caso duas vezes. Notemos a diferença entre permutaçôes, onde a ordem importa,

permutations(3,2)
     [,1] [,2]
[1,]    1    2
[2,]    1    3
[3,]    2    1
[4,]    2    3
[5,]    3    1
[6,]    3    2

e combinações, onde a ordem não importa:

combinations(3,2)
     [,1] [,2]
[1,]    1    2
[2,]    1    3
[3,]    2    3

Para calcular a probabilidade de um 21 natural, inicialmente definimos um vetor que contenha todos os A:

aces <- paste("Ace", suits)
aces
[1] "Ace Diamonds" "Ace Clubs"    "Ace Hearts"  
[4] "Ace Spades"  

Definimos agora um vetor que inclui todas as cartas de face e o 10:

facecard <- c("King","Queen", "Jack", "Ten")
facecard <- expand.grid(number=facecard, suit=suits)
facecard

Formamos o vetor explicitamente:

facecard <- paste(facecard$number,facecard$suit)
facecard
 [1] "King Diamonds"  "Queen Diamonds"
 [3] "Jack Diamonds"  "Ten Diamonds"  
 [5] "King Clubs"     "Queen Clubs"   
 [7] "Jack Clubs"     "Ten Clubs"     
 [9] "King Hearts"    "Queen Hearts"  
[11] "Jack Hearts"    "Ten Hearts"    
[13] "King Spades"    "Queen Spades"  
[15] "Jack Spades"    "Ten Spades"    

Calculamos todas as combinações de 2 cartas que podem ser obtidas a partir das 52 cartas:

hands <- combinations(52,2,v = deck2)
nrow(hands)
[1] 1326

Ou seja, temos 1326 pares de cartas.

summary(hands)
              V1                    V2      
 Ace Clubs     :  51   Three Spades  :  51  
 Ace Diamonds  :  50   Three Hearts  :  50  
 Ace Hearts    :  49   Three Diamonds:  49  
 Ace Spades    :  48   Three Clubs   :  48  
 Deuce Clubs   :  47   Ten Spades    :  47  
 Deuce Diamonds:  46   Ten Hearts    :  46  
 (Other)       :1035   (Other)       :1035  

Temos uma matriz com dois índices: o primeiro (1 a 1326) se refere ao ao par o segundo (1 a 2) à carta do par. Vejamos algumas cartas:

hands[1326,1]
[1] "Three Hearts"
hands[1326,2]
[1] "Three Spades"
hands[1325,1]
[1] "Three Diamonds"
hands[1,1]
[1] "Ace Clubs"
hands[1,2]
[1] "Ace Diamonds"

Por exemplo, o primeiro par é

hands[1,]
[1] "Ace Clubs"    "Ace Diamonds"

e o último par é:

hands[1326,]
[1] "Three Hearts" "Three Spades"

Calculemos agora as probabilidades:

mean(hands[,1] %in% aces & hands[,2] %in% facecard)
[1] 0.04826546

Notemos que embora tenhamos suposto acima que o A é a primeira carta, isso não é importante, pois nas combinações a ordem é irrelevante. Outro modo de calcular esta probabilidade é considerar ambas as possibilidades:

mean((hands[,1] %in% aces & hands[,2] %in% facecard) | (hands[,2] %in% aces & hands[,1] %in% facecard))
[1] 0.04826546

que dá o mesmo resultado.

Simulações de Monte Carlo

Um modo diferente de calcular probabilidades é por meio de experimentos computacionais. Ilustraremos esta ideia usando o chamado método de simulação de Monte Carlo. Vejamos um exemplo simples. Suponhamos que temos um caixa com 10 bolas iguais, mas com cores diferentes: 3 vermelhas, 5 azuis e 2 brancas. Vejamos com simular escolhas aleatórias, sem substituição de 5 bolas da caixa. A caixa com as bolas pode ser representada com ajuda do comando rep seguinte do R:

bolas <- rep(c("red", "blue", "white"),times = c(3,5,2))
bolas
 [1] "red"   "red"   "red"   "blue"  "blue"  "blue" 
 [7] "blue"  "blue"  "white" "white"

Selecionemos aleatoriamente, sem substituição, 5 bolas:

sample(bolas,5)
[1] "white" "blue"  "white" "blue"  "red"  

Se o comando for repetido, outra conjunto de bolas será obtido:

sample(bolas,5)
[1] "red"   "red"   "red"   "blue"  "white"

O experimento pode ser replicado quantas vezes quisermos usando o comando replicate:

B <- 6
eventos <- replicate(B, sample(bolas,5))
eventos
     [,1]   [,2]    [,3]    [,4]    [,5]   [,6]  
[1,] "blue" "red"   "blue"  "blue"  "blue" "blue"
[2,] "blue" "blue"  "red"   "blue"  "blue" "red" 
[3,] "blue" "blue"  "blue"  "white" "blue" "red" 
[4,] "red"  "blue"  "white" "blue"  "red"  "blue"
[5,] "blue" "white" "blue"  "white" "blue" "red" 

Podemos contar automaticamente o número de bolas de cada tipo obtidas da seguint forma:

tab <- table(eventos)
tab
eventos
 blue   red white 
   19     7     4 

Se selecionarmos 10 bolas o conjunto original é obtido:

sample(bolas,10)
 [1] "white" "blue"  "red"   "blue"  "white" "blue" 
 [7] "blue"  "blue"  "red"   "red"  

embora em ordem diferente. Se selecionarmos somente uma bola, é fácil entender que as probabilidades P1, P2 e P3 de obtermos bolas vermelhas, azuis e brancas devem ser dadas, P1 = 0.3, P2 = 0.5, P3 = 0.2. Façamos uma simulação de Monte Carlo com 10000 experimentos, selecionando uma bola por experimento e contando quantas são obtidas:

B <- 10000
eventos <- replicate(B,sample(bolas,1))
tab <- table(eventos)
tab
eventos
 blue   red white 
 4999  2988  2013 

Vejamos as proporções:

prop.table(tab)
eventos
  blue    red  white 
0.4999 0.2988 0.2013 
que é, aproximadamente, o resultado esperado.

Exemplo

Vejamos agora qual é a probabilidade de que tenhamos nas duas primeiras escolhas, realizadas sem substituição, obtenhamos bolas azuis. Denominemos tal probabilidade por \(Pr(BB)\). É fácil mostrar que \[ Pr(BB)= \frac{5}{10}\cdot \frac{4}{9} =\frac{2}{9} \approx 0.222 \] Vejamos como obter este resultado a partir de uma simulação de Monte Carlo. Devemos repetir o seguinte experimento diversas vezes e contar o número de vezes que obtemos “blue” “blue”:

experimento <- sample(bolas,2)
experimento
[1] "blue" "red" 

Façamos o experimento 10 vezes:

B <-10
bolasazuis <- replicate(B,{experimento <- sample(bolas,2) 
(experimento[1]=="blue" & experimento[2]=="blue")})
bolasazuis
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [9] FALSE  TRUE

O evento BB ocorreu 3 vezes. Calculemos a proporção de número de TRUE e número de FALSE:

mean(bolasazuis)
[1] 0.1

Façamos agora 100000 repetições:

B <-10000
bolasazuis <- replicate(B,{experimento <- sample(bolas,2) 
(experimento[1]=="blue" & experimento[2]=="blue")})
mean(bolasazuis)
[1] 0.224
de modo que reobtemos, aproximadamente, o resultado esperado.

Exemplo

Suponhamos que queremos saber agora qual é a probabilidade de obtermos os eventos \(RWB\) ao retirarmos 3 bolas, sem substituição. Sabemos que \[ Pr(RWB)=\frac{3}{10}\frac{2}{9}\frac{5}{8}=\frac{1}{24}\approx 0.04167\,. \] Vejamos como obter este resultado a partir de uma simulação de Monte Carlo, fazendo 800 000 repetições:

B <-800000
bolascoloridas <- replicate(B,{experimento <- sample(bolas,3) 
(experimento[1]=="red" & experimento[2]=="white" & experimento[3]=="blue")})
mean(bolascoloridas)
[1] 0.04179125
que é o resultado esperado.

Exemplo

Suponhamos agora que selecionamos aleatoriamente, sem substituição, 5 bolas e queremos saber qual é a probabilidade de que ao menos 2 bolas sejam vermelhas. Para resolver este problema pelo método tradicional anterior teríamos que listar muitos eventos \(RRBWW\), \(RWRRB\), etc., calcular a probabilidade de cada evento e somar. Façamos logo uma simulação de Monte Carlo, usando o comando str_count (pacote stringr) que funciona do seguinte modo:

s <- sample(bolas,5)
s
[1] "red"  "blue" "red"  "blue" "red" 

Contemos o número de bolas vermelhas na amostra:

str_count(s, "red")
[1] 1 0 1 0 1

Ou seja, quando o string é encontrado o valor 1 é atribuído à respectiva componente, caso contrário é 0. Para determinar o número de ocorrências de 1 no vetor usamos o comando:

n <- str_count(s, "red")
length(which(n==1))
[1] 3

Aplicando este comando ao nosso problema, repetindo o experimento 100 000 vezes, a proporção de casos nos quais temos duas ou mais bolas vermelhas é:

library(stringr)
B <- 100000
bolasvermelhas<-replicate(B,{experimento <- sample(bolas,5) 
n <- str_count(experimento, "red")
length(which(n==1)) >=2})
mean(bolasvermelhas)
[1] 0.49679

ou seja, aproximadamente 1/2.

Exemplo

De uma caixa com 20 bolas, sendo 6 brancas, 4 vermelhas, 7 azuis e 3 verdes são selecionadas 6, sem substituição. (i) Qual é a probabilidade de que a primeira e a última bola da seleção sejam azuis? (ii) Qual é a probabilidade de que ao menos três bolas sejam brancas?

Solução

  1. Definimos a caixa com bolas:
bolas <- rep(c("red", "blue", "white", "green"),times = c(4,7,6,3))
bolas
 [1] "red"   "red"   "red"   "red"   "blue"  "blue" 
 [7] "blue"  "blue"  "blue"  "blue"  "blue"  "white"
[13] "white" "white" "white" "white" "white" "green"
[19] "green" "green"

Selecionamos 6 bolas e repetimos o experimento 900 000 vezes, contando o número de vezes em que a primeira e a sexta bola são azuis:

B <-900000
bolasazuis <- replicate(B,{experimento <- sample(bolas,6) 
(experimento[1]=="blue" & experimento[6]=="blue")})
mean(bolasazuis)
[1] 0.1102656
  1. Devemos agora contabilizar todos os casos em que temos 3 ou mais bolas brancas:
B <-900000
BolasBrancas <- replicate(B,{experimento <- sample(bolas,6) 
n <- str_count(experimento, "white")
length(which(n==1)) >=3})
mean(BolasBrancas)
[1] 0.22508

Voltando ao problema do jogo blackjack, em vez de usar combinações para deduzir a exata probabilidade do 21 natural, podemos usar o método de Monte Carlo para estimar a probabilidade. Neste caso tiramos duas cartas repetidamente e contamos quantas vezes obtemos 21. Podemos usar o comando sample para retirar uma carta sem substituição:

hand <- sample(deck2, 2)
hand
[1] "Eight Diamonds" "Jack Diamonds" 

e checar se obtemos 21. Façamos este experimento 100 vezes:

B <- 100
resultados <- replicate(B,{hand <- sample(deck2,2) 
(hand[1] %in% aces & hand[2] %in% facecard) | (hand[2] %in% aces & hand[1] %in% facecard)})
resultados
  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
  [8] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [15] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [22] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [29] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [36] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [43] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE
 [50] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [57] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE
 [64] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [71] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [78] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
 [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [92] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [99] FALSE FALSE

Calculemos a proporção de número de TRUE e número de FALSE:

mean(resultados)
[1] 0.03

Façamos 100000 amostragens:

B <- 100000
resultados <- replicate(B,{hand <- sample(deck2,2) 
(hand[1] %in% aces & hand[2] %in% facecard) | (hand[2] %in% aces & hand[1] %in% facecard)})
mean(resultados)
[1] 0.04771
que é o resultado esperado.

Exemplo

Temos dois times de volei, Brasil e Argentina, que estão jogando uma séries de melhor de 7 jogos. O Brasil tem uma equipe melhor e tem 60% de chances de vencer um dado jogo.
(i) Qual é a probabilidade de que a Argentina vença ao menos um jogo?
(ii) Resolva este problema usando simulação de Monte Carlo.
Solução: Notemos que a Argentina precisa vencer ao menos um jogo dos primeiros 4 para que não seja eliminada sem vitórias. A probabililidade de que isso não aconteça é igual à probabilidade do Brasil vencer os 4 primeiros jogos, ou seja,

p_brasil_4v <- 0.6^4
p_brasil_4v
[1] 0.1296

Portanto, a probabilidade a Argentina vença ao menos um jogo entre os 4 primeiros é:

1-p_brasil_4v
[1] 0.8704
  1. Façamos a simulação do experimento 100000 vezes:
B = 100000
argentina_vence <- replicate(B,{resultados <- sample(c("lose","win"), 4, replace = TRUE, prob = c(0.6,0.4)) 
any(resultados=="win")})
mean(argentina_vence)
[1] 0.8722

o que está de acordo com o cálculo exato.

O Problema dos Aniversários

Suponhamos que temos uma sala de aula com 50 alunos. Qual é a probabilidade de que dois alunos façam aniversário no mesmo dia? Usemos simulação de Monte Carlo para resolver este problema. Vamos supor que ninguém faz aniversário no dia 29 de fevereiro (o que não muda significativamente o resultado final). Aniversários podem ser representados por números de 1 a 365. Portanto, selecionemos 50 dias de 365 aleatoriamente, com substituição uma vez que dias de aniversários não são exclusivos:

n <- 50
bd <- sample(1:365,n,replace = TRUE)

Para verificar se neste conjunto de 50 dias há ao menos dois repetidos (aniversários no mesmo dia), usaremos o comando duplicated, que retorna o valor TRUE sempre que um elemento do vetor já houver aparecido antes. Por exemplo,

dup <- duplicated(c(2,3,4,2,2,5,3,2,1))
dup
[1] FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE  TRUE
[9] FALSE

Portanto, obtemos o valor TRUE para o elemento 2 na quarta e quinta componentes, onde o 2 se repete.. Além disso, obtemos TRUE para os elementos 3 e 2 na sétima e oitava componentes, onde eles repetem. Se estivermos interessados somente no caso em que a duplicação, podemos usar o comando any:

any(dup)
[1] TRUE

Apliquemos estas ideias ao problema dos aniversários, fazendo 10 amostras:

n < - 50
[1] FALSE
B <- 10
resultado <- replicate(B,{bd <- sample(1:365,n,replace = TRUE) 
any(duplicated(bd))})
resultado
 [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[10] TRUE

Notemos que em 10 experimentos obtivemos repetições em todos eles. Façamos 100 000 experimentos e calculemos a proporção de repetições:

n < - 50
[1] FALSE
B <- 100000
mesmo_dia <- replicate(B,{bd <- sample(1:365,n,replace = TRUE) 
any(duplicated(bd))})
mean(mesmo_dia)
[1] 0.97155

Portanto, em um grupo de 50 pessoas, aniversários no mesmo dia ocorrem com probabilidade de aproximadamente 97%.

Consideremos agora o problema de calcular, para um dado grupo, as chances de haver aniversário no mesmo dia com diferentes probabilidades. Criaremos uma tabela para examinar as possibilidades.

Inicialmente criamos uma função a partir da simulação de Monte Carlo definida acima:

compute_prob <- function(n,
B=100000)
{mesmo_dia <- replicate(B,{bd <- sample(1:365,n,replace = TRUE) 
any(duplicated(bd))})
mean(mesmo_dia)
}

Testemos a função

compute_prob(40)
[1] 0.89203

Definimos agora um vetor com diversos valores para \(n\):

n <- 40:60

Notemos que a nossa função não funciona como esperado:

compute_prob(n)
[1] 0.89089

Ou seja, em vez de calcular a probabilidade para todos os n a função somente usou o primeiro valor (= 40). Isso é porque nossa função espera um escalar como entrada e não um vetor. Outras funções em R normalmente aceitam vetores como argumento. Por exemplo:

sqrt(n)
 [1] 6.324555 6.403124 6.480741 6.557439 6.633250
 [6] 6.708204 6.782330 6.855655 6.928203 7.000000
[11] 7.071068 7.141428 7.211103 7.280110 7.348469
[16] 7.416198 7.483315 7.549834 7.615773 7.681146
[21] 7.745967

Devemos usar aqui o comando sapply, que permite a que a avaliação do função seja feita em todas as componentes da entrada:

sapply(n,compute_prob)
 [1] 0.89126 0.90345 0.91504 0.92419 0.93273 0.94044
 [7] 0.94757 0.95625 0.96069 0.96579 0.96950 0.97417
[13] 0.97821 0.98146 0.98411 0.98599 0.98811 0.99065
[19] 0.99162 0.99308 0.99377

Façamos um gráfico para n de 2 a 60:

n <- 2:60
prob <- sapply(n,compute_prob)
plot(n,prob)

Calculemos as probabilidades exatas em vez de usar simulações de Monte Carlo. Neste caso, é mais simples calcular a probabilidade de que o evento (aniversários no mesmo dia) não ocorra. Examinemos a probabilidade Pr(n) de que um número n de pessoas tenha aniversário numa data única. Se n=1 teremos obviamente Pr(1)=1. A probabilidade de que a segunda pessoa tenha aniversário único, dado que a primeira pessoa tinha aniversário único é 363/365. A probabilidade de que a terceira pessoa tenha aniversário único, dado que as duas primeiras tinham aniversário único é 363/365. Assim, as probabilidades 2 e 3 pessoas tenham aniversário único são dada por \[ Pr(2) = 1 \times \frac{364}{365}\,, \quad Pr(3) = 1 \times \frac{364}{365} \times \frac{363}{365}\,. \] De modo geral, \[ Pr(n) = 1 \times \frac{364}{365} \times \frac{363}{365} \times \cdots \times \frac{365-n+1}{365}\,. \] Façamos a implementação em R:

p_exata <- function(n){
  p_unico <- seq(365, 365-n+1)/365
  1 - prod(p_unico)
}

Façamos um teste:

p_exata(40)
[1] 0.8912318

Podemos agora avaliar esta função nos vários valores de n:

eprob <- sapply(n,p_exata)
plot(n, eprob)

Comparemos este resultado gráfico com aquele obtido com o método de Monte Carlo, usando um curva contínua para o resultado exato:

plot(n, prob)
lines(n, eprob, col="blue")

Tal resultado mostra uma boa concordância entre os métodos.

Número de Amostras

Uma questão crucial em simulações de Monte Carlo envolve a escolha do número de experimentos a serem feitos. Definimos um intervalo de variação de B:

B <- 10^seq(1, 5, len = 100)

e agora uma função que calcula as probabilidades para cada simulação. Fixemos n=30.

compute_prob <- function(B, n = 30){
  same_day <- replicate (B, {
    bdays <- sample(1:365, n, replace=TRUE)
    any(duplicated(bdays))
  })
  mean(same_day)
}

Façamos agora a avaliação da função para todos os valores de B e plotemos o resultado:

prob <- sapply(B, compute_prob)
plot(log10(B), prob, type ="l")

Notemos que a partir de \(B = 10^3\) os resultados começam a estabilizar.

Exercícios

  1. Retiramos, com substituição, 5 bolas de uma caixa que contém 4 bolas brancas, 6 azuis e 7 amarelas. Supondo que as 5 primeiras bolas foram todas amarelas, qual é a probabilidade de que ao retirar a sexta bola encontremos novamente uma bola amarela? R: 0.47

  2. Jogamos um dado honesto 6 vezes. Qual é a probabilidade de não sair um 6 em nenhuma jogada? R: 0.33

  3. Um time de futebol precisa fazer 7 pontos em 5 jogos para não ser rebaixado para a liga inferior. Nos jogos que fará estima-se que ele tem 10% de chances de vencer, 50% de empatar e 40% de perder. Qual é a probabilidade do time não ser rebaixado. Calcule exatamente e usando uma simulação de Monte Carlo.

LS0tDQp0aXRsZTogIlByb2JhYmlsaWRhZGUgQsOhc2ljYSBlbSBSIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQphdXRob3I6ICJGZXJuYW5kbyBEZWVrZSBTYXNzZSINCmZpZ19jYXB0aW9uOiB5ZXMNCg0KLS0tDQo8aDM+Q29uY2VpdG9zIELDoXNpY29zPC9oMz4NClVtICptb2RlbG8gcHJvYmFiaWzDrXN0aWNvKiDDqSB1bWEgZGVzY3Jpw6fDo28gcXVhbGl0YXRpdmEgZGUgdW1hIHNpdHVhw6fDo28sIGZlbsO0bWVubyBvdSBleHBlcmltZW50byBjdWpvIHJlc3VsdGFkbyDDqSBpbmNlcnRvLiBQYXJhIGRlZmluaXIgdGFsIG1vZGVsbyBzZWd1aW1vcyBvcyBwYXNzb3M6IA0KDQogMS4gRGVzY3JldmVtb3Mgb3MgcG9zc8OtdmllcyByZXN1bHRhZG9zIGRvIGV4cGVyaW1lbnRvIChlc3BlY2lmaWNhbW9zIG8gZXNwYcOnbyBhbW9zdHJhbCkNCiAyLiBFc3BlY2lmaWNhbW9zIGEgbGVpIHByb2JhYmlsw61zdGljYSwgcXVlIGF0cmlidWkgcHJvYmFiaWxpZGFkZXMgYW9zIHJlc3VsdGFkb3Mgb3UgY29uanVudG8gZGUgcmVzdWx0YWRvcy4gDQogDQogQSBwcm9iYWJpbGlkYWRlICpQcihBKSogZGUgdW0gZXZlbnRvICAqQSAqw6kgYSBwcm9wb3LDp8OjbyAoYXByb3hpbWFkYSkgZGUgdmV6ZXMgcXVlIG8gZXZlbnRvIG9jb3JyZSBxdWFuZG8gcmVwZXRpbW9zIG8gZXhwZXJpbWVudG8gdsOhcmlhcyB2ZXplcywgZGUgbWFuZWlyYSBpbmRlcGVuZGVudGUsIHNvYiBhcyBtZXNtYXMgY29uZGnDp8O1ZXMuIFF1YW50byBtYWlvciBvIG7Dum1lcm8gZGUgZXhwZXJpbWVudG9zLCBtZWxob3Igw6kgZXN0YSBhcHJveGltYcOnw6NvLiANCiANClVtICpldmVudG8qIMOpIHVtIHJlc3VsdGFkbyBtZWRpZG8gb3Ugb2JzZXJ2YWRvIGRlIHVtIGZlbsO0bWVubywgcXVlIGFjb250ZWNldSBwb3IgY2hhbmNlLiANCg0KTmFzIHNlw6fDtWVzIHNlZ3VpbnRlcyBpbHVzdHJhcmVtb3MgYSBpZGVpYSBkZSBwcm9iYWJpbGlkYWRlIGZhemVuZG8gY29udGFnZW5zIGRlIHBvc3NpYmlsaWRhZGVzIGUgdGFtYsOpbSBwb3IgbWVpbyBkZSBleHBlcmltZW50b3MgY29tcHV0YWNpb25haXMgdXNhbmRvIG8gbcOpdG9kbyBkZSBNb250ZSBDYXJsby4gDQoNCjxoMz5DYXJ0YXMgZGUgdW0gYmFyYWxobzwvaDM+DQpOZXN0YSBzZcOnw6NvIHV0aWxpemFyZW1vcyBtb3N0cmFyZW1vcyBjb21vIHV0aWxpemFyIG8gUiBwYXJhIHJlc29sdmVyIHByb2JsZW1hcyBlbnZvbHZlbmRvIG9iamV0b3MgY29tbyBjYXJ0YXMgZGUgdW0gYmFyYWxoby4gRW1ib3JhIG9zIHByb2JsZW1hcyBsaXN0YWRvcyBhYmFpeG8gcG9zc2FtIHJlc29sdmlkb3MgZmFjaWxtZW50ZSBjb20gdW1hIGNhbGN1bGFkb3JhLCBub3NzbyBvYmpldGl2byDDqSBpbHVzdHJhciBvIHVzbyBkbyBSLCBjb20gY29tYW5kb3MgcXVlIHNlcsOjbyBpbXByZXNjaWTDrXZlaXMgZW0gcHJvYmxlbWFzIGJlbSBtYWlzIGNvbXBsaWNhZG9zIHF1ZSBhYm9yZGFyZW1vcyBtYWlzIGFkaWFudGUuICBQYXJhIGRlZmluaXIgdW0gYmFyYWxobyBkZSBjYXJ0YXMgbm8gUiBwb2RlbW9zIHByb2NlZGVyIGRvIHNlZ3VpbnRlIG1vZG8sIHVzYW5kbyBvcyBjb21hbmRvcyANCjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTpDb3VyYW50OyBmb250LXNpemU6MWVtO2NvbG9yOmJsdWUiPnBhc3RlPC9zcGFuPiBlIA0KPHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OkNvdXJhbnQ7IGZvbnQtc2l6ZToxZW07Y29sb3I6Ymx1ZSI+ZXhwYW5kLmdyaWQ8L3NwYW4+OiANCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGd0b29scykNCmBgYA0KYGBge3J9DQpzdWl0cyA8LSBjKCJEaWFtb25kcyIsICJDbHVicyIsICJIZWFydHMiLCAiU3BhZGVzIikNCm51bWJlcnMgPC0gYygiQWNlIiwgIkRldWNlIiwgIlRocmVlIiwgIkZvdXIiLCAiRml2ZSIsICJTaXgiLCAiU2V2ZW4iLCAiRWlnaHQiLCAiTmluZSIsICJUZW4iLCAiSmFjayIsICJRdWVlbiIsICJLaW5nIikNCmRlY2sgPC0gZXhwYW5kLmdyaWQobnVtYmVyPW51bWJlcnMsIHN1aXQ9c3VpdHMpDQpkZWNrMiA8LSBwYXN0ZShkZWNrJG51bWJlcixkZWNrJHN1aXQpDQpkZWNrMg0KYGBgDQpQb3IgZXhlbXBsbywgY2FsY3VsZW1vcyBxdWFsIMOpIGEgcHJvYmFiaWxpZGFkZSBkZSBvYnRlcm1vcyAqS2luZyogYW8gcmV0aXJhcm1vcyBhIHByaW1laXJhIGNhcnRhIGRvIGJhcmFsaG8uIENvbW8gdW0gYmFyYWxobyB0ZW0gNTIgY2FydGFzIGUgdGVtb3MgNCAqS2luZ3MqLCB1bSBkZSBjYWRhIG5haXBlLCBhIHByb2JhYmlsaWRhZGUgZGUgcmV0aXJhcm1vcyB1bWEgY2FydGEgY29tICpLaW5nKiDDqToNCmBgYHtyfQ0KNC81Mg0KYGBgDQpQb2RlbW9zIHJlb2J0ZXIgZXN0ZSByZXN1bHRhZG8gYSBwYXJ0aXIgZGFzIGNhcnRhcyBkbyBiYXJhbGhvLiBJbmljaWFsbWVudGUgZGV0ZXJtaW5hbW9zIGFzIGNhcnRhcyBjb20gKktpbmcqOiANCmBgYHtyfQ0Ka2luZ3MgPC0gcGFzdGUoIktpbmciLCBzdWl0cykNCmtpbmdzDQpgYGANCkV4YW1pbmFtb3MsIGVudHJlIGFzIGNhcnRhcyBkbyBiYXJhbGhvLCBxdWFpcyBzw6NvIHF1ZSB0ZW0gKktpbmcqOg0KYGBge3J9DQpkZWNrMiAlaW4lIGtpbmdzDQpgYGANCk8gY29tYW5kbyA8c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6Q291cmFudDsgZm9udC1zaXplOjFlbTsiPm1lYW48L3NwYW4+IG5vcyBkw6EgYSBwcm9wb3LDp8OjbyBkbyBuw7ptZXJvIGRlIHJlc3VsdGFkb3MgVFJVRSBwYXJhIG8gbsO6bWVybyBkZSByZXN1bHRhZG9zIEZBTFNFOg0KYGBge3J9DQptZWFuKCBkZWNrMiAlaW4lIGtpbmdzKQ0KYGBgDQpxdWUgw6kgYXByb3hpbWFkYW1lbnRlIDEvMTMsIGNvbW8gZXNwZXJhZG8uIA0KDQpDYWxjdWxlbW9zIGFnb3JhIHF1YWwgw6kgYSBwcm9iYWJpbGlkYWRlIGNvbmRpY2lvbmFsIGRlIHF1ZSBhIHNlZ3VuZGEgY2FydGEgc2VqYSAqS2luZyogZGFkbyBxdWUgYSBwcmltZWlyYSBjYXJ0YSBmb3IgKktpbmcqLiBDb21vIHRlbW9zIGFnb3JhIHNvbWVudGUgMyBjYXJ0YXMgZGVzdGUgdGlwbyBlIG8gYmFyYWxobyBhZ29yYSB0ZW0gc29tZW50ZSA1MSBjYXJ0YXMsIGVzcGVyYW1vcyBxdWUgYSBwcm9iYWJpbGlkYWRlIHNlamEgMy81MS4gQ29uZmlybWVtb3MgZXN0ZSByZXN1bHRhZG8gZW0gUi4gDQoNCkFudGVzIGRpc3NvIGVzdHVkZW1vcyBvIGNvbWFuZG8gPHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OkNvdXJhbnQ7IGZvbnQtc2l6ZToxZW07Ij5wZXJtdXRhdGlvbnMoKTwvc3Bhbj4gcXVlIGNvbXB1dGEsIHBhcmEgcXVhbHF1ZXIgbGlzdGEgZGUgdGFtYW5obyAqbiosIHRvZG9zIGRpZmVyZW50ZXMgbW9kb3MgcXVlIHBvZGVtb3Mgc2VsZWNpb25hciAqciogaXRlbnMuIFZlamFtb3MgdW0gZXhlbXBsbzogZGUgcXVhbnRvcyBtb2RvcyBwb2RlbW9zIHNlbGVjaW9uYXIgMiBlbGVtZW50b3MgZGUgdW0gZ3J1cG8gZGUgNSBlbGVtZW50b3M/DQpgYGB7cn0NCnBlcm11dGF0aW9ucyg1LDIpDQpgYGANCk5vdGVtb3MgcXVlIGEgb3JkZW0gaW1wb3J0YS4gQWzDqW0gZGlzc28gbsO6bWVyb3MgcmVwZXRpZG9zIG7Do28gb2NvcnJlbSwgcG9pcyB1bWEgdmV6IHF1ZSBzZWxlY2lvbmFtb3MgdW0gbsO6bWVybywgZWxlIG7Do28gYXBhcmVjZSBub3ZhbWVudGUuIE9wY2lvbmFsbWVudGUgbyBjb21hbmRvIDxzcGFuIHN0eWxlPSJmb250LWZhbWlseTpDb3VyYW50OyBmb250LXNpemU6MWVtOyI+cGVybXV0YXRpb25zPC9zcGFuPiBwb2RlIHRlciB1bSB2ZXRvciBjb21vIHRlcmNlaXJvIGFyZ3VtZW50by4gUG9yIGV4ZW1wbG8sIGZhw6dhbW9zIHVtYSBwZXJtdXRhw6fDo28gKG91IGFycmFuam8pIGRlIDQgbsO6bWVyb3MsIDMsNCw1LDYgZW0gZ3J1cG9zIGRlIDMgZWxlbWVudG9zLiBEZSBvdXRybyBtb2RvLCBzZSB0ZW1vcyB1bWEgY2FpeGEgY29tIDQgYm9sYXMgbWFyY2FkYXMgY29tIGVzdGVzIG7Dum1lcm9zLCBxdWFpcyBzw6NvIG9zIHBvc3PDrXZlaXMgcmVzdWx0YWRvcyBhbyBzZWxlY2lvbmFyIDMgYm9sYXMgYWxlYXTDs3JpYW1lbnRlPyANCmBgYHtyfQ0KbSA8LSBwZXJtdXRhdGlvbnMoNCwzLGMoMyw0LDUsNiw3KSkNCm0NCmBgYA0KQ29tbyB2ZW1vcyBkYSBtYXRyaXogZGUgc2HDrWRhIGRvIGNvbWFuZG8gYWNpbWEsIG8gbsO6bWVybyBkZSBtb2RvcyDDqSAyNCwgcXVlIHBvZGUgc2VyIG9idGlkbyBkaXJldGFtZW50ZSBjb250YW5kbyBvIG7Dum1lcm8gZGUgbGluaGFzIGRlICptKjogDQpgYGB7cn0NCm4gPC0gbnJvdyhtKQ0Kbg0KYGBgDQpGYcOnYW1vcyB1bWEgc2ltdWxhw6fDo28gZGUgNiBlc2NvbGhhcyBhbGVhdMOzcmlhcyBkZSAzIGJvbGFzDQpgYGB7cn0NCmluZGljZSA8LSBzYW1wbGUobiw2KQ0KaW5kaWNlDQpgYGANCk91IHNlamEsIGFzIGJvbGFzIHNlbGVjaW9uYWRhcyB0w6ptIG9zIG7Dum1lcm9zIGRhZG9zIHBvcjogDQpgYGB7cn0NCm1baW5kaWNlLF0NCmBgYA0KDQo8SDQ+RXhlbXBsbzo8L0g0PiANClNpbXVsZSBhIHNlbGXDp8OjbyBhbGVhdMOzcmlhIGRlIGRlIDUgbsO6bWVyb3MgKDAgYSA5KSBkZSA3IGTDrWdpdG9zIChuw6NvIG1vc3RyZSBhcyBwb3Nzw612ZWlzIHNlbGXDp8O1ZXMgbmEgdGVsYSkuPGJyPg0KU29sdcOnw6NvIA0KYGBge3J9DQpudW1lcm9zIDwtIHBlcm11dGF0aW9ucygxMCw3LGMoMDo5KSkNCm4gPC0gbnJvdyhudW1lcm9zKQ0Kbg0KYGBgDQpTZWxlY2lvbmVtb3MgNSBuw7ptZXJvcyBkZSA3IGTDrWdpdG9zOiANCmBgYHtyfQ0KaW5kaWNlIDwtIHNhbXBsZShuLDUpDQppbmRpY2UNCm51bWVyb3NbaW5kaWNlLF0NCmBgYA0KDQpWb2x0ZW1vcyBhZ29yYSBhbyBwcm9ibGVtYSBkZSBjYWxjdWxhciBhIHByb2JhYmlsaWRhZGUgZGUgcXVlIGEgc2VndW5kYSBjYXJ0YSBzZWphICpLaW5nKiBkYWRvIHF1ZSBhIHByaW1laXJhIGNhcnRhIGZvciAqS2luZyouIENvbXB1dGVtb3MgdG9kb3Mgb3MgcG9zc8OtdmVpcyBtb2RvcyBkZSBlc2NvbGhlciBkdWFzIGNhcnRhcywgcXVhbmRvIGEgb3JkZW0gw6kgcmVsZXZhbnRlLg0KYGBge3J9DQpoYW5kcyA8LSBwZXJtdXRhdGlvbnMoNTIsMix2PWRlY2syKQ0KbnJvdyhoYW5kcykNCmBgYA0KT3Ugc2VqYSwgdGVtb3MgMjY1MiBwb3NzaWJpbGlkYWRlcy4gQSBwcmltZWlyYSBjYXJ0YSBzZXLDoSBzZWxlY2lvbmFkYSBkYSBwcmltZWlyYSBjb2x1bmEgZGEgbWF0cml6IGhhbmRzIGUgc2ltaWxhcm1lbnRlIGNvbSBhIHNlZ3VuZGE6IA0KYGBge3J9DQpwcmltZWlyYV9jYXJ0YSA8LSBoYW5kc1ssMV0NCnNlZ3VuZGFfY2FydGEgPC0gaGFuZHNbLDJdDQpgYGANClZlamFtb3MgZW0gcXVhbnRvcyBjYXNvcyBhIHByaW1laXJhIGNhcnRhIMOpIEtpbmc6IA0KYGBge3J9DQprIDwtIHN1bShwcmltZWlyYV9jYXJ0YSAlaW4lIGtpbmdzKQ0Kaw0KYGBgDQpPdSBzZWphLCAyMDQgY2Fzb3MuIFBhcmEgZGV0ZXJtaW5hciBhIHByb2JhYmlsaWRhZGUgY29uZGljaW9uYWwgZGV2ZW1vcyBhZ29yYSBkZXRlcm1pbmFyIHF1YWwgw6kgYSBmcmHDp8OjbyBkZXN0ZXMgMjA0IGNhc29zIGVtIHF1ZSAgdGVtb3MgKktpbmcqIG5hIHNlZ3VuZGEgY2FydGE6DQpgYGB7cn0NCnN1bShwcmltZWlyYV9jYXJ0YSAlaW4lIGtpbmdzICYgc2VndW5kYV9jYXJ0YSAlaW4lIGtpbmdzKS9zdW0ocHJpbWVpcmFfY2FydGEgJWluJSBraW5ncykNCmBgYA0KcXVlIMOpIGlndWFsIGEgMy81MSwgY29tbyBlc3BlcmFkby4NCg0KTm90ZW1vcyBhaW5kYSBxdWUgbyBtZXNtbyByZXN1bHRhZG8gcG9kZXJpYSBzZXIgb2J0aWRvIHV0aWxpemFuZG8gdmFsb3JlcyBlc3BlcmFkb3M6DQpgYGB7cn0NCm1lYW4ocHJpbWVpcmFfY2FydGEgJWluJSBraW5ncyAmIHNlZ3VuZGFfY2FydGEgJWluJSBraW5ncykvbWVhbihwcmltZWlyYV9jYXJ0YSAlaW4lIGtpbmdzKQ0KYGBgDQpFc3RhcyBleHByZXNzw7VlcyBhY2ltYSBzw6NvIGZvcm1hcyBkaWZlcmVudGVzIGRhIHJlbGHDp8OjbyBmdW5kYW1lbnRhbCANCiQkDQpQcihCfEEpPVxmcmFje1ByKEEgXGNhcCBCKX17UHIoQSl9DQokJA0KU3Vwb25oYW1vcyBhZ29yYSBxdWUgYSBvcmRlbSBuw6NvIHNlamEgaW1wb3J0YW50ZS4gDQpObyBqb2dvICpibGFja2phY2sqIHNlIG9idGl2ZXJtb3MgdW0gQSBlIHVtYSBjYXJ0YSBkZSBmYWNlIG91IDEwLCB0ZXJlbW9zIHVtIDIxIG5hdHVyYWwsIGEgYSB2aXTDs3JpYSDDqSBpbnN0YW50w6JuZWEuIFF1ZXJlbW9zIGNhbGN1bGFyIGEgcHJvYmFiaWxpZGFkZSBkaXNzbyBhY29udGVjZXIuIE5vdGVtb3MgcXVlIGFnb3JhIGRldmVtb3MgZW51bWVyYXIgY29tYmluYcOnw7VlcyBlIG7Do28gcGVybXV0YcOnw7VlcywgcG9pcyBhIG9yZGVtIG7Do28gaW1wb3J0YS4gVW0gKkEqIGUgdW0gKktpbmcqIG91IHVtICpLaW5nKiBlICpBKiBzw6NvIGEgbWVzbWEgY29pc2EgZSBuw6NvIHF1ZXJlbW9zIGNvbnRhciBlc3RlIGNhc28gZHVhcyB2ZXplcy4gTm90ZW1vcyBhIGRpZmVyZW7Dp2EgZW50cmUgcGVybXV0YcOnw7Rlcywgb25kZSBhIG9yZGVtIGltcG9ydGEsDQpgYGB7cn0NCnBlcm11dGF0aW9ucygzLDIpDQpgYGANCmUgY29tYmluYcOnw7Vlcywgb25kZSBhIG9yZGVtIG7Do28gaW1wb3J0YTogDQpgYGB7cn0NCmNvbWJpbmF0aW9ucygzLDIpDQpgYGANClBhcmEgY2FsY3VsYXIgYSBwcm9iYWJpbGlkYWRlIGRlIHVtIDIxIG5hdHVyYWwsIGluaWNpYWxtZW50ZSBkZWZpbmltb3MgdW0gdmV0b3IgcXVlIGNvbnRlbmhhIHRvZG9zIG9zIEE6DQpgYGB7cn0NCmFjZXMgPC0gcGFzdGUoIkFjZSIsIHN1aXRzKQ0KYWNlcw0KYGBgDQpEZWZpbmltb3MgYWdvcmEgdW0gdmV0b3IgcXVlIGluY2x1aSB0b2RhcyBhcyBjYXJ0YXMgZGUgZmFjZSBlIG8gMTA6DQpgYGB7cn0NCmZhY2VjYXJkIDwtIGMoIktpbmciLCJRdWVlbiIsICJKYWNrIiwgIlRlbiIpDQpmYWNlY2FyZCA8LSBleHBhbmQuZ3JpZChudW1iZXI9ZmFjZWNhcmQsIHN1aXQ9c3VpdHMpDQpmYWNlY2FyZA0KYGBgDQpGb3JtYW1vcyBvIHZldG9yIGV4cGxpY2l0YW1lbnRlOg0KYGBge3J9DQpmYWNlY2FyZCA8LSBwYXN0ZShmYWNlY2FyZCRudW1iZXIsZmFjZWNhcmQkc3VpdCkNCmZhY2VjYXJkDQpgYGANCkNhbGN1bGFtb3MgdG9kYXMgYXMgY29tYmluYcOnw7VlcyBkZSAyIGNhcnRhcyBxdWUgcG9kZW0gc2VyIG9idGlkYXMgYSBwYXJ0aXIgZGFzIDUyIGNhcnRhczogDQpgYGB7cn0NCmhhbmRzIDwtIGNvbWJpbmF0aW9ucyg1MiwyLHYgPSBkZWNrMikNCm5yb3coaGFuZHMpDQpgYGANCk91IHNlamEsIHRlbW9zIDEzMjYgcGFyZXMgZGUgY2FydGFzLiANCmBgYHtyfQ0Kc3VtbWFyeShoYW5kcykNCmBgYA0KVGVtb3MgdW1hIG1hdHJpeiBjb20gZG9pcyDDrW5kaWNlczogbyBwcmltZWlybyAoMSBhIDEzMjYpIHNlIHJlZmVyZSBhbyBhbyBwYXIgbyBzZWd1bmRvICgxIGEgMikgw6AgY2FydGEgZG8gcGFyLiBWZWphbW9zIGFsZ3VtYXMgY2FydGFzOg0KYGBge3J9DQpoYW5kc1sxMzI2LDFdDQpoYW5kc1sxMzI2LDJdDQpoYW5kc1sxMzI1LDFdDQpoYW5kc1sxLDFdDQpoYW5kc1sxLDJdDQpgYGANClBvciBleGVtcGxvLCBvIHByaW1laXJvIHBhciDDqSANCmBgYHtyfQ0KaGFuZHNbMSxdDQpgYGANCmUgbyDDumx0aW1vIHBhciDDqTogDQpgYGB7cn0NCmhhbmRzWzEzMjYsXQ0KYGBgDQpDYWxjdWxlbW9zIGFnb3JhIGFzIHByb2JhYmlsaWRhZGVzOg0KYGBge3J9DQptZWFuKGhhbmRzWywxXSAlaW4lIGFjZXMgJiBoYW5kc1ssMl0gJWluJSBmYWNlY2FyZCkNCmBgYA0KTm90ZW1vcyBxdWUgZW1ib3JhIHRlbmhhbW9zIHN1cG9zdG8gYWNpbWEgcXVlIG8gKkEqIMOpIGEgcHJpbWVpcmEgY2FydGEsIGlzc28gbsOjbyDDqSBpbXBvcnRhbnRlLCBwb2lzIG5hcyBjb21iaW5hw6fDtWVzIGEgb3JkZW0gw6kgaXJyZWxldmFudGUuIE91dHJvIG1vZG8gZGUgY2FsY3VsYXIgZXN0YSBwcm9iYWJpbGlkYWRlIMOpIGNvbnNpZGVyYXIgYW1iYXMgYXMgcG9zc2liaWxpZGFkZXM6IA0KYGBge3J9DQptZWFuKChoYW5kc1ssMV0gJWluJSBhY2VzICYgaGFuZHNbLDJdICVpbiUgZmFjZWNhcmQpIHwgKGhhbmRzWywyXSAlaW4lIGFjZXMgJiBoYW5kc1ssMV0gJWluJSBmYWNlY2FyZCkpDQpgYGANCnF1ZSBkw6EgbyBtZXNtbyByZXN1bHRhZG8uIA0KDQo8aDM+IFNpbXVsYcOnw7VlcyBkZSBNb250ZSBDYXJsbyA8L2gzPg0KVW0gbW9kbyBkaWZlcmVudGUgZGUgY2FsY3VsYXIgcHJvYmFiaWxpZGFkZXMgw6kgcG9yIG1laW8gZGUgZXhwZXJpbWVudG9zIGNvbXB1dGFjaW9uYWlzLiBJbHVzdHJhcmVtb3MgZXN0YSBpZGVpYSB1c2FuZG8gbyBjaGFtYWRvIG3DqXRvZG8gZGUgc2ltdWxhw6fDo28gZGUgTW9udGUgQ2FybG8uIFZlamFtb3MgdW0gZXhlbXBsbyBzaW1wbGVzLiBTdXBvbmhhbW9zIHF1ZSB0ZW1vcyB1bSBjYWl4YSBjb20gMTAgYm9sYXMgaWd1YWlzLCBtYXMgY29tIGNvcmVzIGRpZmVyZW50ZXM6IDMgdmVybWVsaGFzLCA1IGF6dWlzIGUgMiBicmFuY2FzLiBWZWphbW9zIGNvbSBzaW11bGFyIGVzY29saGFzIGFsZWF0w7NyaWFzLCBzZW0gc3Vic3RpdHVpw6fDo28gZGUgNSBib2xhcyBkYSBjYWl4YS4gQSBjYWl4YSBjb20gYXMgYm9sYXMgcG9kZSBzZXIgcmVwcmVzZW50YWRhIGNvbSBhanVkYSBkbyBjb21hbmRvICA8c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6Q291cmFudDsgZm9udC1zaXplOjFlbTsiPnJlcDwvc3Bhbj4gc2VndWludGUgZG8gUjogDQpgYGB7cn0NCmJvbGFzIDwtIHJlcChjKCJyZWQiLCAiYmx1ZSIsICJ3aGl0ZSIpLHRpbWVzID0gYygzLDUsMikpDQpib2xhcw0KYGBgDQpTZWxlY2lvbmVtb3MgYWxlYXRvcmlhbWVudGUsIHNlbSBzdWJzdGl0dWnDp8OjbywgNSBib2xhczogDQpgYGB7cn0NCnNhbXBsZShib2xhcyw1KQ0KYGBgDQpTZSBvIGNvbWFuZG8gZm9yIHJlcGV0aWRvLCBvdXRyYSBjb25qdW50byBkZSBib2xhcyBzZXLDoSBvYnRpZG86IA0KYGBge3J9DQpzYW1wbGUoYm9sYXMsNSkNCmBgYA0KTyBleHBlcmltZW50byBwb2RlIHNlciByZXBsaWNhZG8gcXVhbnRhcyB2ZXplcyBxdWlzZXJtb3MgdXNhbmRvIG8gY29tYW5kbyA8c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6Q291cmFudDsgZm9udC1zaXplOjFlbTsiPnJlcGxpY2F0ZTwvc3Bhbj46DQpgYGB7cn0NCkIgPC0gNg0KZXZlbnRvcyA8LSByZXBsaWNhdGUoQiwgc2FtcGxlKGJvbGFzLDUpKQ0KZXZlbnRvcw0KYGBgDQpQb2RlbW9zIGNvbnRhciBhdXRvbWF0aWNhbWVudGUgbyBuw7ptZXJvIGRlIGJvbGFzIGRlIGNhZGEgdGlwbyBvYnRpZGFzIGRhIHNlZ3VpbnQgZm9ybWE6IA0KYGBge3J9DQp0YWIgPC0gdGFibGUoZXZlbnRvcykNCnRhYg0KYGBgDQpTZSBzZWxlY2lvbmFybW9zIDEwIGJvbGFzIG8gY29uanVudG8gb3JpZ2luYWwgw6kgb2J0aWRvOiANCmBgYHtyfQ0Kc2FtcGxlKGJvbGFzLDEwKQ0KYGBgDQplbWJvcmEgZW0gb3JkZW0gZGlmZXJlbnRlLiBTZSBzZWxlY2lvbmFybW9zIHNvbWVudGUgdW1hIGJvbGEsIMOpIGbDoWNpbCBlbnRlbmRlciBxdWUgYXMgcHJvYmFiaWxpZGFkZXMgUDEsIFAyIGUgUDMgZGUgb2J0ZXJtb3MgYm9sYXMgdmVybWVsaGFzLCBhenVpcyBlIGJyYW5jYXMgZGV2ZW0gc2VyIGRhZGFzLCBQMSA9IDAuMywgUDIgPSAwLjUsIFAzID0gMC4yLiBGYcOnYW1vcyB1bWEgc2ltdWxhw6fDo28gZGUgTW9udGUgQ2FybG8gY29tIDEwMDAwIGV4cGVyaW1lbnRvcywgc2VsZWNpb25hbmRvIHVtYSBib2xhIHBvciBleHBlcmltZW50byBlIGNvbnRhbmRvIHF1YW50YXMgc8OjbyBvYnRpZGFzOiANCmBgYHtyfQ0KQiA8LSAxMDAwMA0KZXZlbnRvcyA8LSByZXBsaWNhdGUoQixzYW1wbGUoYm9sYXMsMSkpDQp0YWIgPC0gdGFibGUoZXZlbnRvcykNCnRhYg0KYGBgDQpWZWphbW9zIGFzIHByb3BvcsOnw7VlczogDQpgYGB7cn0NCnByb3AudGFibGUodGFiKQ0KYGBgDQpxdWUgw6ksIGFwcm94aW1hZGFtZW50ZSwgbyByZXN1bHRhZG8gZXNwZXJhZG8uIA0KPGgzPiBFeGVtcGxvIDwvaDM+DQpWZWphbW9zIGFnb3JhIHF1YWwgw6kgYSBwcm9iYWJpbGlkYWRlIGRlIHF1ZSB0ZW5oYW1vcyBuYXMgZHVhcyBwcmltZWlyYXMgZXNjb2xoYXMsIHJlYWxpemFkYXMgc2VtIHN1YnN0aXR1acOnw6NvLCBvYnRlbmhhbW9zIGJvbGFzIGF6dWlzLiBEZW5vbWluZW1vcyB0YWwgcHJvYmFiaWxpZGFkZSBwb3IgJFByKEJCKSQuIMOJIGbDoWNpbCBtb3N0cmFyIHF1ZSANCiQkDQpQcihCQik9IFxmcmFjezV9ezEwfVxjZG90IFxmcmFjezR9ezl9ID1cZnJhY3syfXs5fSBcYXBwcm94IDAuMjIyDQokJA0KVmVqYW1vcyBjb21vIG9idGVyIGVzdGUgcmVzdWx0YWRvIGEgcGFydGlyIGRlIHVtYSBzaW11bGHDp8OjbyBkZSBNb250ZSBDYXJsby4gRGV2ZW1vcyByZXBldGlyIG8gc2VndWludGUgZXhwZXJpbWVudG8gZGl2ZXJzYXMgdmV6ZXMgZSBjb250YXIgbyBuw7ptZXJvIGRlIHZlemVzIHF1ZSBvYnRlbW9zICJibHVlIiAiYmx1ZSI6DQpgYGB7cn0NCmV4cGVyaW1lbnRvIDwtIHNhbXBsZShib2xhcywyKQ0KZXhwZXJpbWVudG8NCmBgYA0KRmHDp2Ftb3MgbyBleHBlcmltZW50byAxMCB2ZXplczogDQpgYGB7cn0NCkIgPC0xMA0KYm9sYXNhenVpcyA8LSByZXBsaWNhdGUoQix7ZXhwZXJpbWVudG8gPC0gc2FtcGxlKGJvbGFzLDIpIA0KKGV4cGVyaW1lbnRvWzFdPT0iYmx1ZSIgJiBleHBlcmltZW50b1syXT09ImJsdWUiKX0pDQpib2xhc2F6dWlzDQpgYGANCk8gZXZlbnRvIEJCIG9jb3JyZXUgMyB2ZXplcy4NCkNhbGN1bGVtb3MgYSBwcm9wb3LDp8OjbyBkZSBuw7ptZXJvIGRlIFRSVUUgZSBuw7ptZXJvIGRlIEZBTFNFOiANCmBgYHtyfQ0KbWVhbihib2xhc2F6dWlzKQ0KYGBgDQpGYcOnYW1vcyBhZ29yYSAxMDAwMDAgcmVwZXRpw6fDtWVzOiANCmBgYHtyfQ0KQiA8LTEwMDAwDQpib2xhc2F6dWlzIDwtIHJlcGxpY2F0ZShCLHtleHBlcmltZW50byA8LSBzYW1wbGUoYm9sYXMsMikgDQooZXhwZXJpbWVudG9bMV09PSJibHVlIiAmIGV4cGVyaW1lbnRvWzJdPT0iYmx1ZSIpfSkNCm1lYW4oYm9sYXNhenVpcykNCmBgYA0KZGUgbW9kbyBxdWUgcmVvYnRlbW9zLCBhcHJveGltYWRhbWVudGUsIG8gcmVzdWx0YWRvIGVzcGVyYWRvLiANCjxoMz4gRXhlbXBsbyA8L2gzPg0KU3Vwb25oYW1vcyBxdWUgcXVlcmVtb3Mgc2FiZXIgYWdvcmEgcXVhbCDDqSBhIHByb2JhYmlsaWRhZGUgZGUgb2J0ZXJtb3Mgb3MgZXZlbnRvcyAkUldCJCBhbyByZXRpcmFybW9zIDMgYm9sYXMsIHNlbSBzdWJzdGl0dWnDp8Ojby4gU2FiZW1vcyBxdWUgDQokJA0KUHIoUldCKT1cZnJhY3szfXsxMH1cZnJhY3syfXs5fVxmcmFjezV9ezh9PVxmcmFjezF9ezI0fVxhcHByb3ggMC4wNDE2N1wsLg0KJCQNClZlamFtb3MgY29tbyBvYnRlciBlc3RlIHJlc3VsdGFkbyBhIHBhcnRpciBkZSB1bWEgc2ltdWxhw6fDo28gZGUgTW9udGUgQ2FybG8sIGZhemVuZG8gODAwIDAwMCByZXBldGnDp8O1ZXM6IA0KYGBge3J9DQpCIDwtODAwMDAwDQpib2xhc2NvbG9yaWRhcyA8LSByZXBsaWNhdGUoQix7ZXhwZXJpbWVudG8gPC0gc2FtcGxlKGJvbGFzLDMpIA0KKGV4cGVyaW1lbnRvWzFdPT0icmVkIiAmIGV4cGVyaW1lbnRvWzJdPT0id2hpdGUiICYgZXhwZXJpbWVudG9bM109PSJibHVlIil9KQ0KbWVhbihib2xhc2NvbG9yaWRhcykNCmBgYA0KcXVlIMOpIG8gcmVzdWx0YWRvIGVzcGVyYWRvLiANCjxoMz4gRXhlbXBsbyA8L2gzPg0KU3Vwb25oYW1vcyBhZ29yYSBxdWUgc2VsZWNpb25hbW9zIGFsZWF0b3JpYW1lbnRlLCBzZW0gc3Vic3RpdHVpw6fDo28sIDUgYm9sYXMgZSBxdWVyZW1vcyBzYWJlciBxdWFsIMOpIGEgcHJvYmFiaWxpZGFkZSBkZSBxdWUgYW8gbWVub3MgMiBib2xhcyBzZWphbSB2ZXJtZWxoYXMuIFBhcmEgcmVzb2x2ZXIgZXN0ZSBwcm9ibGVtYSBwZWxvIG3DqXRvZG8gdHJhZGljaW9uYWwgYW50ZXJpb3IgdGVyw61hbW9zIHF1ZSBsaXN0YXIgbXVpdG9zIGV2ZW50b3MgJFJSQldXJCwgJFJXUlJCJCwgZXRjLiwgY2FsY3VsYXIgYSBwcm9iYWJpbGlkYWRlIGRlIGNhZGEgZXZlbnRvIGUgc29tYXIuIEZhw6dhbW9zIGxvZ28gdW1hIHNpbXVsYcOnw6NvIGRlIE1vbnRlIENhcmxvLCB1c2FuZG8gbyBjb21hbmRvIDxzcGFuIHN0eWxlPSJmb250LWZhbWlseTpDb3VyYW50OyBmb250LXNpemU6MWVtOyI+c3RyX2NvdW50PC9zcGFuPiAocGFjb3RlIHN0cmluZ3IpIHF1ZSBmdW5jaW9uYSBkbyBzZWd1aW50ZSBtb2RvOiANCmBgYHtyfQ0KcyA8LSBzYW1wbGUoYm9sYXMsNSkNCnMNCmBgYA0KQ29udGVtb3MgbyBuw7ptZXJvIGRlIGJvbGFzIHZlcm1lbGhhcyBuYSBhbW9zdHJhOiANCmBgYHtyfQ0Kc3RyX2NvdW50KHMsICJyZWQiKQ0KYGBgDQpPdSBzZWphLCBxdWFuZG8gbyBzdHJpbmcgw6kgZW5jb250cmFkbyBvIHZhbG9yIDEgw6kgYXRyaWJ1w61kbyDDoCByZXNwZWN0aXZhIGNvbXBvbmVudGUsIGNhc28gY29udHLDoXJpbyDDqSAwLiBQYXJhIGRldGVybWluYXIgbyBuw7ptZXJvIGRlIG9jb3Jyw6puY2lhcyBkZSAxIG5vIHZldG9yIHVzYW1vcyBvIGNvbWFuZG86DQpgYGB7cn0NCm4gPC0gc3RyX2NvdW50KHMsICJyZWQiKQ0KbGVuZ3RoKHdoaWNoKG49PTEpKQ0KYGBgDQpBcGxpY2FuZG8gZXN0ZSBjb21hbmRvIGFvIG5vc3NvIHByb2JsZW1hLCByZXBldGluZG8gbyBleHBlcmltZW50byAxMDAgMDAwIHZlemVzLCBhIHByb3BvcsOnw6NvIGRlIGNhc29zIG5vcyBxdWFpcyB0ZW1vcyBkdWFzIG91IG1haXMgYm9sYXMgdmVybWVsaGFzIMOpOg0KYGBge3J9DQpsaWJyYXJ5KHN0cmluZ3IpDQpCIDwtIDEwMDAwMA0KYm9sYXN2ZXJtZWxoYXM8LXJlcGxpY2F0ZShCLHtleHBlcmltZW50byA8LSBzYW1wbGUoYm9sYXMsNSkgDQpuIDwtIHN0cl9jb3VudChleHBlcmltZW50bywgInJlZCIpDQpsZW5ndGgod2hpY2gobj09MSkpID49Mn0pDQptZWFuKGJvbGFzdmVybWVsaGFzKQ0KYGBgDQpvdSBzZWphLCBhcHJveGltYWRhbWVudGUgMS8yLiANCg0KPGg0PkV4ZW1wbG88L2g0Pg0KRGUgdW1hIGNhaXhhIGNvbSAyMCBib2xhcywgc2VuZG8gNiBicmFuY2FzLCAgNCB2ZXJtZWxoYXMsICA3IGF6dWlzIGUgMyB2ZXJkZXMgc8OjbyBzZWxlY2lvbmFkYXMgNiwgc2VtIHN1YnN0aXR1acOnw6NvLiANCihpKSBRdWFsIMOpIGEgcHJvYmFiaWxpZGFkZSBkZSBxdWUgYSBwcmltZWlyYSBlIGEgw7psdGltYSBib2xhIGRhIHNlbGXDp8OjbyBzZWphbSBhenVpcz8gDQooaWkpIFF1YWwgw6kgYSBwcm9iYWJpbGlkYWRlIGRlIHF1ZSBhbyBtZW5vcyB0csOqcyBib2xhcyBzZWphbSBicmFuY2FzPyANCjxoND5Tb2x1w6fDo288L2g0Pg0KKGkpIERlZmluaW1vcyBhIGNhaXhhIGNvbSBib2xhczogDQpgYGB7cn0NCmJvbGFzIDwtIHJlcChjKCJyZWQiLCAiYmx1ZSIsICJ3aGl0ZSIsICJncmVlbiIpLHRpbWVzID0gYyg0LDcsNiwzKSkNCmJvbGFzDQpgYGANClNlbGVjaW9uYW1vcyA2IGJvbGFzIGUgcmVwZXRpbW9zIG8gZXhwZXJpbWVudG8gOTAwIDAwMCB2ZXplcywgY29udGFuZG8gbyBuw7ptZXJvIGRlIHZlemVzIGVtIHF1ZSBhIHByaW1laXJhIGUgYSBzZXh0YSBib2xhIHPDo28gYXp1aXM6DQpgYGB7cn0NCkIgPC05MDAwMDANCmJvbGFzYXp1aXMgPC0gcmVwbGljYXRlKEIse2V4cGVyaW1lbnRvIDwtIHNhbXBsZShib2xhcyw2KSANCihleHBlcmltZW50b1sxXT09ImJsdWUiICYgZXhwZXJpbWVudG9bNl09PSJibHVlIil9KQ0KbWVhbihib2xhc2F6dWlzKQ0KYGBgDQooaWkpIERldmVtb3MgYWdvcmEgY29udGFiaWxpemFyIHRvZG9zIG9zIGNhc29zIGVtIHF1ZSB0ZW1vcyAzIG91IG1haXMgYm9sYXMgYnJhbmNhczoNCmBgYHtyfQ0KQiA8LTkwMDAwMA0KQm9sYXNCcmFuY2FzIDwtIHJlcGxpY2F0ZShCLHtleHBlcmltZW50byA8LSBzYW1wbGUoYm9sYXMsNikgDQpuIDwtIHN0cl9jb3VudChleHBlcmltZW50bywgIndoaXRlIikNCmxlbmd0aCh3aGljaChuPT0xKSkgPj0zfSkNCm1lYW4oQm9sYXNCcmFuY2FzKQ0KYGBgDQoNClZvbHRhbmRvIGFvIHByb2JsZW1hIGRvIGpvZ28gYmxhY2tqYWNrLCBlbSAgdmV6IGRlIHVzYXIgY29tYmluYcOnw7VlcyBwYXJhIGRlZHV6aXIgYSBleGF0YSBwcm9iYWJpbGlkYWRlIGRvIDIxIG5hdHVyYWwsIHBvZGVtb3MgdXNhciBvIG3DqXRvZG8gZGUgTW9udGUgQ2FybG8gcGFyYSBlc3RpbWFyIGEgcHJvYmFiaWxpZGFkZS4gTmVzdGUgY2FzbyB0aXJhbW9zIGR1YXMgY2FydGFzIHJlcGV0aWRhbWVudGUgZSBjb250YW1vcyBxdWFudGFzIHZlemVzIG9idGVtb3MgMjEuIFBvZGVtb3MgdXNhciBvIGNvbWFuZG8gPHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OkNvdXJhbnQ7IGZvbnQtc2l6ZToxZW07Ij5zYW1wbGU8L3NwYW4+IHBhcmEgcmV0aXJhciB1bWEgY2FydGEgc2VtIHN1YnN0aXR1acOnw6NvOiANCmBgYHtyfQ0KaGFuZCA8LSBzYW1wbGUoZGVjazIsIDIpDQpoYW5kDQpgYGANCmUgY2hlY2FyIHNlIG9idGVtb3MgMjEuIEZhw6dhbW9zIGVzdGUgZXhwZXJpbWVudG8gMTAwIHZlemVzOg0KYGBge3J9DQpCIDwtIDEwMA0KcmVzdWx0YWRvcyA8LSByZXBsaWNhdGUoQix7aGFuZCA8LSBzYW1wbGUoZGVjazIsMikgDQooaGFuZFsxXSAlaW4lIGFjZXMgJiBoYW5kWzJdICVpbiUgZmFjZWNhcmQpIHwgKGhhbmRbMl0gJWluJSBhY2VzICYgaGFuZFsxXSAlaW4lIGZhY2VjYXJkKX0pDQpyZXN1bHRhZG9zDQpgYGANCg0KQ2FsY3VsZW1vcyBhIHByb3BvcsOnw6NvIGRlIG7Dum1lcm8gZGUgVFJVRSBlIG7Dum1lcm8gZGUgRkFMU0U6IA0KYGBge3J9DQptZWFuKHJlc3VsdGFkb3MpDQpgYGANCkZhw6dhbW9zIDEwMDAwMCBhbW9zdHJhZ2VuczoNCmBgYHtyfQ0KQiA8LSAxMDAwMDANCnJlc3VsdGFkb3MgPC0gcmVwbGljYXRlKEIse2hhbmQgPC0gc2FtcGxlKGRlY2syLDIpIA0KKGhhbmRbMV0gJWluJSBhY2VzICYgaGFuZFsyXSAlaW4lIGZhY2VjYXJkKSB8IChoYW5kWzJdICVpbiUgYWNlcyAmIGhhbmRbMV0gJWluJSBmYWNlY2FyZCl9KQ0KbWVhbihyZXN1bHRhZG9zKQ0KYGBgDQpxdWUgw6kgbyByZXN1bHRhZG8gZXNwZXJhZG8uIA0KPGg0PkV4ZW1wbG8gPC9oND4NClRlbW9zIGRvaXMgdGltZXMgZGUgdm9sZWksIEJyYXNpbCBlIEFyZ2VudGluYSwgcXVlIGVzdMOjbyBqb2dhbmRvIHVtYSBzw6lyaWVzIGRlIG1lbGhvciBkZSA3IGpvZ29zLiBPIEJyYXNpbCB0ZW0gdW1hIGVxdWlwZSBtZWxob3IgZSB0ZW0gNjAlIGRlIGNoYW5jZXMgZGUgdmVuY2VyIHVtIGRhZG8gam9nby4gPGJyPg0KKGkpIFF1YWwgw6kgYSBwcm9iYWJpbGlkYWRlIGRlIHF1ZSBhIEFyZ2VudGluYSB2ZW7Dp2EgYW8gbWVub3MgdW0gam9nbz8gPGJyPg0KKGlpKSBSZXNvbHZhIGVzdGUgcHJvYmxlbWEgdXNhbmRvIHNpbXVsYcOnw6NvIGRlIE1vbnRlIENhcmxvLiA8YnI+DQoqKlNvbHXDp8OjbyoqOiBOb3RlbW9zIHF1ZSBhIEFyZ2VudGluYSBwcmVjaXNhIHZlbmNlciBhbyBtZW5vcyB1bSBqb2dvIGRvcyBwcmltZWlyb3MgNCBwYXJhIHF1ZSBuw6NvIHNlamEgZWxpbWluYWRhIHNlbSB2aXTDs3JpYXMuIEEgcHJvYmFiaWxpbGlkYWRlIGRlIHF1ZSBpc3NvIG7Do28gYWNvbnRlw6dhIMOpIGlndWFsIMOgIHByb2JhYmlsaWRhZGUgZG8gQnJhc2lsIHZlbmNlciBvcyA0IHByaW1laXJvcyBqb2dvcywgb3Ugc2VqYSwgDQpgYGB7cn0NCnBfYnJhc2lsXzR2IDwtIDAuNl40DQpwX2JyYXNpbF80dg0KYGBgDQpQb3J0YW50bywgYSBwcm9iYWJpbGlkYWRlIGEgQXJnZW50aW5hIHZlbsOnYSBhbyBtZW5vcyB1bSBqb2dvIGVudHJlIG9zIDQgcHJpbWVpcm9zIMOpOg0KYGBge3J9DQoxLXBfYnJhc2lsXzR2DQpgYGANCihpaSkgRmHDp2Ftb3MgYSBzaW11bGHDp8OjbyBkbyBleHBlcmltZW50byAxMDAwMDAgdmV6ZXM6IA0KYGBge3J9DQpCID0gMTAwMDAwDQphcmdlbnRpbmFfdmVuY2UgPC0gcmVwbGljYXRlKEIse3Jlc3VsdGFkb3MgPC0gc2FtcGxlKGMoImxvc2UiLCJ3aW4iKSwgNCwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNiwwLjQpKSANCmFueShyZXN1bHRhZG9zPT0id2luIil9KQ0KbWVhbihhcmdlbnRpbmFfdmVuY2UpDQpgYGANCm8gcXVlIGVzdMOhIGRlIGFjb3JkbyBjb20gbyBjw6FsY3VsbyBleGF0by4gDQoNCjxoMz5PIFByb2JsZW1hIGRvcyBBbml2ZXJzw6FyaW9zPC9oMz4NClN1cG9uaGFtb3MgcXVlIHRlbW9zIHVtYSBzYWxhIGRlIGF1bGEgY29tIDUwIGFsdW5vcy4gUXVhbCDDqSBhIHByb2JhYmlsaWRhZGUgZGUgcXVlIGRvaXMgYWx1bm9zIGZhw6dhbSBhbml2ZXJzw6FyaW8gbm8gbWVzbW8gZGlhPyBVc2Vtb3Mgc2ltdWxhw6fDo28gZGUgTW9udGUgQ2FybG8gcGFyYSByZXNvbHZlciBlc3RlIHByb2JsZW1hLiBWYW1vcyBzdXBvciBxdWUgbmluZ3XDqW0gZmF6IGFuaXZlcnPDoXJpbyBubyBkaWEgMjkgZGUgZmV2ZXJlaXJvIChvIHF1ZSBuw6NvIG11ZGEgc2lnbmlmaWNhdGl2YW1lbnRlIG8gcmVzdWx0YWRvIGZpbmFsKS4gQW5pdmVyc8OhcmlvcyBwb2RlbSBzZXIgcmVwcmVzZW50YWRvcyBwb3IgbsO6bWVyb3MgZGUgMSBhIDM2NS4gUG9ydGFudG8sIHNlbGVjaW9uZW1vcyA1MCBkaWFzIGRlIDM2NSBhbGVhdG9yaWFtZW50ZSwgY29tIHN1YnN0aXR1acOnw6NvIHVtYSB2ZXogcXVlIGRpYXMgZGUgYW5pdmVyc8OhcmlvcyBuw6NvIHPDo28gZXhjbHVzaXZvczogDQpgYGB7cn0NCm4gPC0gNTANCmJkIDwtIHNhbXBsZSgxOjM2NSxuLHJlcGxhY2UgPSBUUlVFKQ0KYGBgDQpQYXJhIHZlcmlmaWNhciBzZSBuZXN0ZSBjb25qdW50byBkZSA1MCBkaWFzIGjDoSBhbyBtZW5vcyBkb2lzIHJlcGV0aWRvcyAoYW5pdmVyc8OhcmlvcyBubyBtZXNtbyBkaWEpLCB1c2FyZW1vcyBvIGNvbWFuZG8gPHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OkNvdXJhbnQ7IGZvbnQtc2l6ZToxZW07Ij5kdXBsaWNhdGVkPC9zcGFuPiwgcXVlIHJldG9ybmEgbyB2YWxvciBUUlVFIHNlbXByZSBxdWUgdW0gZWxlbWVudG8gZG8gdmV0b3IgasOhIGhvdXZlciBhcGFyZWNpZG8gYW50ZXMuIFBvciBleGVtcGxvLCANCmBgYHtyfQ0KZHVwIDwtIGR1cGxpY2F0ZWQoYygyLDMsNCwyLDIsNSwzLDIsMSkpDQpkdXANCmBgYA0KUG9ydGFudG8sIG9idGVtb3MgbyB2YWxvciBUUlVFIHBhcmEgbyBlbGVtZW50byAyIG5hIHF1YXJ0YSBlIHF1aW50YSBjb21wb25lbnRlcywgb25kZSBvIDIgc2UgcmVwZXRlLi4gQWzDqW0gZGlzc28sIG9idGVtb3MgVFJVRSBwYXJhIG9zIGVsZW1lbnRvcyAzIGUgMiBuYSBzw6l0aW1hIGUgb2l0YXZhIGNvbXBvbmVudGVzLCBvbmRlIGVsZXMgcmVwZXRlbS4gU2UgZXN0aXZlcm1vcyBpbnRlcmVzc2Fkb3Mgc29tZW50ZSBubyBjYXNvIGVtIHF1ZSBhIGR1cGxpY2HDp8OjbywgcG9kZW1vcyB1c2FyIG8gY29tYW5kbyAgPHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OkNvdXJhbnQ7IGZvbnQtc2l6ZToxZW07Ij5hbnk8L3NwYW4+Og0KYGBge3J9DQphbnkoZHVwKQ0KYGBgDQpBcGxpcXVlbW9zIGVzdGFzIGlkZWlhcyBhbyBwcm9ibGVtYSBkb3MgYW5pdmVyc8OhcmlvcywgZmF6ZW5kbyAxMCBhbW9zdHJhczoNCmBgYHtyfQ0KbiA8IC0gNTANCkIgPC0gMTANCnJlc3VsdGFkbyA8LSByZXBsaWNhdGUoQix7YmQgPC0gc2FtcGxlKDE6MzY1LG4scmVwbGFjZSA9IFRSVUUpIA0KYW55KGR1cGxpY2F0ZWQoYmQpKX0pDQpyZXN1bHRhZG8NCmBgYA0KTm90ZW1vcyBxdWUgZW0gMTAgZXhwZXJpbWVudG9zIG9idGl2ZW1vcyByZXBldGnDp8O1ZXMgZW0gdG9kb3MgZWxlcy4gRmHDp2Ftb3MgMTAwIDAwMCBleHBlcmltZW50b3MgZSBjYWxjdWxlbW9zIGEgcHJvcG9yw6fDo28gZGUgcmVwZXRpw6fDtWVzOiANCmBgYHtyfQ0KbiA8IC0gNTANCkIgPC0gMTAwMDAwDQptZXNtb19kaWEgPC0gcmVwbGljYXRlKEIse2JkIDwtIHNhbXBsZSgxOjM2NSxuLHJlcGxhY2UgPSBUUlVFKSANCmFueShkdXBsaWNhdGVkKGJkKSl9KQ0KbWVhbihtZXNtb19kaWEpDQpgYGANClBvcnRhbnRvLCBlbSB1bSBncnVwbyBkZSA1MCBwZXNzb2FzLCBhbml2ZXJzw6FyaW9zIG5vIG1lc21vIGRpYSBvY29ycmVtIGNvbSBwcm9iYWJpbGlkYWRlIGRlIGFwcm94aW1hZGFtZW50ZSA5NyUuIA0KDQpDb25zaWRlcmVtb3MgYWdvcmEgbyBwcm9ibGVtYSBkZSBjYWxjdWxhciwgcGFyYSB1bSBkYWRvIGdydXBvLCBhcyBjaGFuY2VzIGRlIGhhdmVyIGFuaXZlcnPDoXJpbyBubyBtZXNtbyBkaWEgY29tIGRpZmVyZW50ZXMgcHJvYmFiaWxpZGFkZXMuIENyaWFyZW1vcyB1bWEgdGFiZWxhIHBhcmEgZXhhbWluYXIgYXMgcG9zc2liaWxpZGFkZXMuDQoNCkluaWNpYWxtZW50ZSBjcmlhbW9zIHVtYSBmdW7Dp8OjbyBhIHBhcnRpciBkYSBzaW11bGHDp8OjbyBkZSBNb250ZSBDYXJsbyBkZWZpbmlkYSBhY2ltYToNCmBgYHtyfQ0KY29tcHV0ZV9wcm9iIDwtIGZ1bmN0aW9uKG4sDQpCPTEwMDAwMCkNCnttZXNtb19kaWEgPC0gcmVwbGljYXRlKEIse2JkIDwtIHNhbXBsZSgxOjM2NSxuLHJlcGxhY2UgPSBUUlVFKSANCmFueShkdXBsaWNhdGVkKGJkKSl9KQ0KbWVhbihtZXNtb19kaWEpDQp9DQpgYGANClRlc3RlbW9zIGEgZnVuw6fDo28gDQpgYGB7cn0NCmNvbXB1dGVfcHJvYig0MCkNCmBgYA0KRGVmaW5pbW9zIGFnb3JhIHVtIHZldG9yIGNvbSBkaXZlcnNvcyB2YWxvcmVzIHBhcmEgJG4kOiANCmBgYHtyfQ0KbiA8LSA0MDo2MA0KYGBgDQpOb3RlbW9zIHF1ZSBhIG5vc3NhIGZ1bsOnw6NvIG7Do28gZnVuY2lvbmEgY29tbyBlc3BlcmFkbzoNCmBgYHtyfQ0KY29tcHV0ZV9wcm9iKG4pDQpgYGANCk91IHNlamEsIGVtIHZleiBkZSBjYWxjdWxhciBhIHByb2JhYmlsaWRhZGUgcGFyYSB0b2RvcyBvcyBuIGEgZnVuw6fDo28gc29tZW50ZSB1c291IG8gcHJpbWVpcm8gdmFsb3IgKD0gNDApLiBJc3NvIMOpIHBvcnF1ZSBub3NzYSBmdW7Dp8OjbyBlc3BlcmEgdW0gZXNjYWxhciBjb21vIGVudHJhZGEgZSBuw6NvIHVtIHZldG9yLiBPdXRyYXMgZnVuw6fDtWVzIGVtIFIgbm9ybWFsbWVudGUgYWNlaXRhbSB2ZXRvcmVzIGNvbW8gYXJndW1lbnRvLiBQb3IgZXhlbXBsbzogDQpgYGB7cn0NCnNxcnQobikNCmBgYA0KRGV2ZW1vcyB1c2FyIGFxdWkgbyBjb21hbmRvIDxzcGFuIHN0eWxlPSJmb250LWZhbWlseTpDb3VyYW50OyBmb250LXNpemU6MWVtOyI+c2FwcGx5PC9zcGFuPiwgcXVlIHBlcm1pdGUgYSBxdWUgYSBhdmFsaWHDp8OjbyBkbyBmdW7Dp8OjbyBzZWphIGZlaXRhIGVtIHRvZGFzIGFzIGNvbXBvbmVudGVzIGRhIGVudHJhZGE6IA0KYGBge3J9DQpzYXBwbHkobixjb21wdXRlX3Byb2IpDQpgYGANCkZhw6dhbW9zIHVtIGdyw6FmaWNvIHBhcmEgKm4qIGRlIDIgYSA2MDoNCmBgYHtyfQ0KbiA8LSAyOjYwDQpwcm9iIDwtIHNhcHBseShuLGNvbXB1dGVfcHJvYikNCnBsb3Qobixwcm9iKQ0KYGBgDQpDYWxjdWxlbW9zIGFzIHByb2JhYmlsaWRhZGVzIGV4YXRhcyBlbSB2ZXogZGUgdXNhciBzaW11bGHDp8O1ZXMgZGUgTW9udGUgQ2FybG8uIE5lc3RlIGNhc28sIMOpIG1haXMgc2ltcGxlcyBjYWxjdWxhciBhIHByb2JhYmlsaWRhZGUgZGUgcXVlIG8gZXZlbnRvIChhbml2ZXJzw6FyaW9zIG5vIG1lc21vIGRpYSkgbsOjbyBvY29ycmEuIEV4YW1pbmVtb3MgYSBwcm9iYWJpbGlkYWRlICpQcihuKSogZGUgcXVlIHVtIG7Dum1lcm8gKm4qIGRlIHBlc3NvYXMgdGVuaGEgYW5pdmVyc8OhcmlvIG51bWEgZGF0YSDDum5pY2EuIFNlICpuPTEqIHRlcmVtb3Mgb2J2aWFtZW50ZSAqUHIoMSk9MSouIEEgcHJvYmFiaWxpZGFkZSBkZSBxdWUgYSBzZWd1bmRhIHBlc3NvYSB0ZW5oYSBhbml2ZXJzw6FyaW8gw7puaWNvLCBkYWRvIHF1ZSBhIHByaW1laXJhIHBlc3NvYSB0aW5oYSBhbml2ZXJzw6FyaW8gw7puaWNvIMOpIDM2My8zNjUuIEEgcHJvYmFiaWxpZGFkZSBkZSBxdWUgYSB0ZXJjZWlyYSBwZXNzb2EgdGVuaGEgYW5pdmVyc8OhcmlvIMO6bmljbywgZGFkbyBxdWUgYXMgZHVhcyBwcmltZWlyYXMgdGluaGFtIGFuaXZlcnPDoXJpbyDDum5pY28gw6kgMzYzLzM2NS4gQXNzaW0sIGFzIHByb2JhYmlsaWRhZGVzIDIgZSAzIHBlc3NvYXMgdGVuaGFtIGFuaXZlcnPDoXJpbyDDum5pY28gc8OjbyBkYWRhIHBvcg0KJCQNClByKDIpID0gMSBcdGltZXMgXGZyYWN7MzY0fXszNjV9XCwsIFxxdWFkICBQcigzKSA9IDEgXHRpbWVzIFxmcmFjezM2NH17MzY1fSBcdGltZXMgXGZyYWN7MzYzfXszNjV9XCwuDQokJA0KRGUgbW9kbyBnZXJhbCwNCiQkDQogUHIobikgPSAxIFx0aW1lcyBcZnJhY3szNjR9ezM2NX0gXHRpbWVzIFxmcmFjezM2M317MzY1fSBcdGltZXMgXGNkb3RzIFx0aW1lcyBcZnJhY3szNjUtbisxfXszNjV9XCwuDQokJA0KRmHDp2Ftb3MgYSBpbXBsZW1lbnRhw6fDo28gZW0gUjogDQpgYGB7cn0gDQpwX2V4YXRhIDwtIGZ1bmN0aW9uKG4pew0KICBwX3VuaWNvIDwtIHNlcSgzNjUsIDM2NS1uKzEpLzM2NQ0KICAxIC0gcHJvZChwX3VuaWNvKQ0KfQ0KYGBgDQpGYcOnYW1vcyB1bSB0ZXN0ZTogDQpgYGB7cn0NCnBfZXhhdGEoNDApDQpgYGANClBvZGVtb3MgYWdvcmEgYXZhbGlhciBlc3RhIGZ1bsOnw6NvIG5vcyB2w6FyaW9zIHZhbG9yZXMgZGUgKm4qOg0KYGBge3J9DQplcHJvYiA8LSBzYXBwbHkobixwX2V4YXRhKQ0KcGxvdChuLCBlcHJvYikNCmBgYA0KQ29tcGFyZW1vcyBlc3RlIHJlc3VsdGFkbyBncsOhZmljbyBjb20gYXF1ZWxlIG9idGlkbyBjb20gbyBtw6l0b2RvIGRlIE1vbnRlIENhcmxvLCB1c2FuZG8gdW0gY3VydmEgY29udMOtbnVhIHBhcmEgbyByZXN1bHRhZG8gZXhhdG86IA0KYGBge3J9DQpwbG90KG4sIHByb2IpDQpsaW5lcyhuLCBlcHJvYiwgY29sPSJibHVlIikNCmBgYA0KVGFsIHJlc3VsdGFkbyBtb3N0cmEgdW1hIGJvYSBjb25jb3Jkw6JuY2lhIGVudHJlIG9zIG3DqXRvZG9zLiANCg0KPGgzPk7Dum1lcm8gZGUgQW1vc3RyYXM8L2gzPg0KVW1hIHF1ZXN0w6NvIGNydWNpYWwgZW0gc2ltdWxhw6fDtWVzIGRlIE1vbnRlIENhcmxvIGVudm9sdmUgYSBlc2NvbGhhIGRvIG7Dum1lcm8gZGUgZXhwZXJpbWVudG9zIGEgc2VyZW0gZmVpdG9zLiANCkRlZmluaW1vcyB1bSBpbnRlcnZhbG8gZGUgdmFyaWHDp8OjbyBkZSAqQio6IA0KYGBge3J9DQpCIDwtIDEwXnNlcSgxLCA1LCBsZW4gPSAxMDApDQpgYGANCmUgYWdvcmEgdW1hIGZ1bsOnw6NvIHF1ZSBjYWxjdWxhIGFzIHByb2JhYmlsaWRhZGVzIHBhcmEgY2FkYSBzaW11bGHDp8Ojby4gRml4ZW1vcyAqbj0zMCouDQpgYGB7cn0NCmNvbXB1dGVfcHJvYiA8LSBmdW5jdGlvbihCLCBuID0gMzApew0KICBzYW1lX2RheSA8LSByZXBsaWNhdGUgKEIsIHsNCiAgICBiZGF5cyA8LSBzYW1wbGUoMTozNjUsIG4sIHJlcGxhY2U9VFJVRSkNCiAgICBhbnkoZHVwbGljYXRlZChiZGF5cykpDQogIH0pDQogIG1lYW4oc2FtZV9kYXkpDQp9DQpgYGANCkZhw6dhbW9zIGFnb3JhIGEgYXZhbGlhw6fDo28gZGEgZnVuw6fDo28gcGFyYSB0b2RvcyBvcyB2YWxvcmVzIGRlICpCKiBlIHBsb3RlbW9zIG8gcmVzdWx0YWRvOiANCmBgYHtyfQ0KcHJvYiA8LSBzYXBwbHkoQiwgY29tcHV0ZV9wcm9iKQ0KcGxvdChsb2cxMChCKSwgcHJvYiwgdHlwZSA9ImwiKQ0KYGBgDQogTm90ZW1vcyBxdWUgYSBwYXJ0aXIgZGUgJEIgPSAxMF4zJCBvcyByZXN1bHRhZG9zIGNvbWXDp2FtIGEgZXN0YWJpbGl6YXIuIA0KIA0KPGgzPiBFeGVyY8OtY2lvcyA8L2gzPg0KDQoxLiBSZXRpcmFtb3MsIGNvbSBzdWJzdGl0dWnDp8OjbywgIDUgYm9sYXMgZGUgdW1hIGNhaXhhIHF1ZSBjb250w6ltIDQgYm9sYXMgYnJhbmNhcywgNiBhenVpcyBlIDcgYW1hcmVsYXMuIFN1cG9uZG8gcXVlIGFzIDUgcHJpbWVpcmFzIGJvbGFzIGZvcmFtIHRvZGFzIGFtYXJlbGFzLCBxdWFsIMOpIGEgcHJvYmFiaWxpZGFkZSBkZSBxdWUgYW8gcmV0aXJhciBhIHNleHRhIGJvbGEgZW5jb250cmVtb3Mgbm92YW1lbnRlIHVtYSBib2xhIGFtYXJlbGE/IFI6IDAuNDcNCg0KMi4gSm9nYW1vcyB1bSBkYWRvIGhvbmVzdG8gNiB2ZXplcy4gUXVhbCDDqSBhIHByb2JhYmlsaWRhZGUgZGUgbsOjbyBzYWlyIHVtIDYgZW0gbmVuaHVtYSBqb2dhZGE/IFI6IDAuMzMNCg0KMy4gVW0gdGltZSBkZSBmdXRlYm9sIHByZWNpc2EgZmF6ZXIgNyBwb250b3MgZW0gNSBqb2dvcyBwYXJhIG7Do28gc2VyIHJlYmFpeGFkbyBwYXJhIGEgbGlnYSBpbmZlcmlvci4gTm9zIGpvZ29zIHF1ZSBmYXLDoSBlc3RpbWEtc2UgcXVlIGVsZSB0ZW0gMTAlIGRlIGNoYW5jZXMgZGUgdmVuY2VyLCA1MCUgZGUgZW1wYXRhciBlIDQwJSBkZSBwZXJkZXIuIFF1YWwgw6kgYSBwcm9iYWJpbGlkYWRlIGRvIHRpbWUgbsOjbyBzZXIgcmViYWl4YWRvLiBDYWxjdWxlIGV4YXRhbWVudGUgZSB1c2FuZG8gdW1hIHNpbXVsYcOnw6NvIGRlIE1vbnRlIENhcmxvLiANCg0KIA0K