Conociendo dplyr

Vamos a trabajar con los datos de las características físicas de pinguinos que están en el paquete palmerpenguins. El paquete se puede instalar con install.packages("palmerpenguins"). Toda la documentación sobre estos datos está acá. El paquete fue desarrollado por Allison Horst, Alison Hill, Kristen Gorman. En particular, Allison Horst es la responsable de los dibujos de los pinguinos y de hacer un gran tutorial de dplyr usando este dataset.

El objetivo de estos ejercicios es familiarizarse con las siguientes funciones de dplyr:

  • filter(): quedarse con las filas que satisfacen ciertas condiciones.
  • select(): quedarse o excluir algunas columnas del dataset.
  • relocate()`: mover columnas de lugar.
  • rename()`: renombrar columnas.
  • mutate(): crear una nueva variable (columna) operando con las demás.
  • group_by() + summarize(): obtener medidas resumen de los datos por grupos.
  • across(): aplicar una función a varias columnas.
  • count(): contar rápidamente cuántas observaciones hay por grupo.
  • case_when(): una forma de hacer “if-else”.

Pueden cargar la librería tidyverse completa (library(tidyverse)) pero por ahora sólo vamos a usar funciones del paquete dplyr.

require(palmerpenguins)
require(dplyr)
1

Usar filter() para crear un subconjunto de datos que contenga sólo pinguinos de la isla Biscoe y que tengan un pico de 48 mm de largo o más.

2

Crear otro dataset con la información de pinguinos Adelie machos que no hayan sido vistos en el año 2008.

3

Del dataset penguins quedarse con todas las variables excepto year, sex y body_mass_g.

4

Crear un subconjunto de los datos de penguins sólo con las obsevaciones de pinguinos machos con aletas de más de 200 mm de largo y quedarse con todas las columnas que terminan con “mm”. (usar la función ends_with()).

5

Empezando con penguins, hacer un pipe (%>%) que:

  • se quede sólo con las observaciones de la isla Dream.
  • se quede con las variables species y todas las que empiece con bill.
6

Mover todas las variables factor después de las columnas integer. Se puede usar relocate() junto con is.integer y is.factor.

7

Convertir todas las variables que empiezan con bill a mayúsculas.

penguins %>%
  rename_with(____, starts_with("____"))
8

Empezando con penguins hacer lo siguiente con un único llamado a la función mutate():

  • Convertir la variable species a character.
  • Crear una nueva variable que tenga el peso en Kg.
  • Convertir la variable island a minúscula.
9

Empezando con penguins crear una tabla resumen que contenga para el largo mínimo y máximo de las aletas de los pinguinos chinstrap, agrupados por isla.

10

Empezando con penguins, agrupar los datos por especie y año, luego crear una tabla de resumen que contenga el ancho del pico (llamarla bill_depth_mean) y el largo del pico (llamarla bill_length_mean) para cada grupo

penguins %>%
  group_by(_____, _____) %>%
  summarize(
    _________ = mean(______, na.rm = TRUE),
    _________ = mean(______, na.rm = TRUE)
  )
11

Empezando con penguins, hacer una secuencia de operaciones %>% que:

  • Agregue una nueva columna llamada bill_ratio que sea el cociente entre el largo y el ancho del pico.
  • Quedarse sólo con las columnas species y bill_ratio.
  • Agrupar los datos por especie.
  • Crear una tabla de resumen que contenga el promedio de la variable bill_ratio por especie y que el nombre de la columna en la tabla sea bill_ratio_mean)
penguins %>%
  mutate(bill_ratio = ______ / ______) %>%
  select(______, ______) %>%
  group_by(______) %>%
  summarize(______ = mean(______, na.rm = TRUE))
12

Empezando con penguins, agrupar los datos por isla y después usar across() para encontrar la mediana de los grupos para todas las columnas que contengan el string “mm”. El nombre de las variables tiene que ser el nombre original seguido de un guión bajo y la palabra “median” (o sea, nombredelacolumna_median)

penguins %>%
  group_by(______) %>%
  summarize(across(contains("______"),
                   median,
                   na.rm = TRUE,
                   .names = "_______")
            )
13

Empezando con penguins, quedarse con las observaciones correspondientes a los pinguinos Adelie y luego usar across() para encontrar el valor máximo de todas las variables numéricas para cada isla.

penguins %>%
  filter(species == "______") %>%
  group_by(______) %>%
  summarize(across(where(_____), _____, na.rm = TRUE))
14

Empezando con penguins, escribir una secuencia de operaciones %>% que:

  • Excluya a los pinguinos observados en la isla Biscoe.
  • Sólo se quede con las variables que están entre species y body_mass_g inclusive.
  • Renombrar la variable species a especie_pinguino.
  • Agrupar los datos por la variable especie_pinguino.
  • Encontrar el valor medio de las variables que contienen el string “length”, separando por la especie del pinguino, y llamando a las columnas como las originales pero agregando "_mean" al final.
penguins %>%
  filter(island != "_____") %>%
  select(_____:_____) %>%
  rename(_____ = _____) %>%
  group_by(_____) %>%
  summarize(across(contains("_____"), mean, na.rm = TRUE, .names = "{.col}_avg"))
15

Empezando con penguins, contar cuántas observaciones hay por especie, isla y año.

16

Empezando con penguins, quedarse sólo con los pinguinos Adelie y gentoo penguins. Luego contar cuántos hay por cada especie y sexo.

17

Agregar una nueva columna a la base de datos llamada campaña que contenga:

  • “c1” si el año 2007
  • “c2” si el año 2008
  • “c3” si el año 2009
18

Empezando con penguins quedarse sólo con las observaciones correspondientes a pinguinos chinstrap. Luego, quedarse sólo con las variables flipper_length_mm y body_mass_g. Agregar una nueva columna llamada fm_ratio que contenga el cociente entre el largo de la aleta y el peso del pinguino. Luego agregar otra columna llamada ratio_bin que contenga la palabra “alto” si fm_ratio es mayor o igual que 0.05, “bajo” si el cociente es menor que 0.05 y “no hay registro” en cualquier otro caso (como por ejemplo si el cociente es un NA)

penguins %>%
  filter(species == "_____") %>%
  select(_____, _____) %>%
  mutate(fm_ratio = _____ / _____) %>%
  mutate(ratio_bin = case_when(
    fm_ratio >= 0.05 ~ "_____",
    fm_ratio < 0.05 ~ "_____",
    TRUE ~ "_____"
  ))
LS0tCnRpdGxlOiAiVHJhbnNmb3JtYW5kbyBkYXRvcyBjb24gZHBseXIiCmF1dGhvcjogIkd1aWxsZXJtbyBTb2xvdmV5IgpkYXRlOiAiOS8yNy8yMDIxIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB5ZXMKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGx1bWVuCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKc3VidGl0bGU6ICJMYWJvcmF0b3JpbyBkZSBEYXRvcyIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIyBDb25vY2llbmRvIGRwbHlyCgpWYW1vcyBhIHRyYWJhamFyIGNvbiBsb3MgZGF0b3MgZGUgbGFzIGNhcmFjdGVyw61zdGljYXMgZsOtc2ljYXMgZGUgcGluZ3Vpbm9zIHF1ZSBlc3TDoW4gZW4gZWwgCnBhcXVldGUgYHBhbG1lcnBlbmd1aW5zYC4gRWwgcGFxdWV0ZSAgc2UgcHVlZGUgaW5zdGFsYXIgY29uIApgaW5zdGFsbC5wYWNrYWdlcygicGFsbWVycGVuZ3VpbnMiKWAuIFRvZGEgbGEgZG9jdW1lbnRhY2nDs24gc29icmUgZXN0b3MgZGF0b3MgZXN0w6EKW2Fjw6FdKGh0dHBzOi8vYWxsaXNvbmhvcnN0LmdpdGh1Yi5pby9wYWxtZXJwZW5ndWlucy8pLiBFbCBwYXF1ZXRlIGZ1ZSBkZXNhcnJvbGxhZG8gcG9yIApBbGxpc29uIEhvcnN0LCBBbGlzb24gSGlsbCwgS3Jpc3RlbiBHb3JtYW4uIEVuIHBhcnRpY3VsYXIsIEFsbGlzb24gSG9yc3QgZXMgbGEgcmVzcG9uc2FibGUKZGUgbG9zIGRpYnVqb3MgZGUgbG9zIHBpbmd1aW5vcyB5IGRlIGhhY2VyIHVuIGdyYW4gW3R1dG9yaWFsXShodHRwczovL2FsbGlzb25ob3JzdC5zaGlueWFwcHMuaW8vZHBseXItbGVhcm5yLyNzZWN0aW9uLXdlbGNvbWUpIGRlIGRwbHlyIHVzYW5kbyBlc3RlIGRhdGFzZXQuCgpFbCBvYmpldGl2byBkZSBlc3RvcyBlamVyY2ljaW9zIGVzIGZhbWlsaWFyaXphcnNlIGNvbiBsYXMgc2lndWllbnRlcyBmdW5jaW9uZXMgZGUgYGRwbHlyYDoKCiogYGZpbHRlcigpYDogcXVlZGFyc2UgY29uIGxhcyBmaWxhcyBxdWUgc2F0aXNmYWNlbiBjaWVydGFzIGNvbmRpY2lvbmVzLgoqIGBzZWxlY3QoKWA6IHF1ZWRhcnNlIG8gZXhjbHVpciBhbGd1bmFzIGNvbHVtbmFzIGRlbCBkYXRhc2V0LgoqIGByZWxvY2F0ZWAoKWA6IG1vdmVyIGNvbHVtbmFzIGRlIGx1Z2FyLgoqIGByZW5hbWVgKClgOiByZW5vbWJyYXIgY29sdW1uYXMuIAoqIGBtdXRhdGUoKWA6IGNyZWFyIHVuYSBudWV2YSB2YXJpYWJsZSAoY29sdW1uYSkgb3BlcmFuZG8gY29uIGxhcyBkZW3DoXMuCiogYGdyb3VwX2J5KClgICsgYHN1bW1hcml6ZSgpYDogb2J0ZW5lciBtZWRpZGFzIHJlc3VtZW4gZGUgbG9zIGRhdG9zIHBvciBncnVwb3MuCiogYGFjcm9zcygpYDogYXBsaWNhciB1bmEgZnVuY2nDs24gYSB2YXJpYXMgY29sdW1uYXMuCiogYGNvdW50KClgOiBjb250YXIgcsOhcGlkYW1lbnRlIGN1w6FudGFzIG9ic2VydmFjaW9uZXMgaGF5IHBvciBncnVwby4KKiBgY2FzZV93aGVuKClgOiB1bmEgZm9ybWEgZGUgaGFjZXIgImlmLWVsc2UiLgogCgpQdWVkZW4gY2FyZ2FyIGxhIGxpYnJlcsOtYSBgdGlkeXZlcnNlYCBjb21wbGV0YSAoYGxpYnJhcnkodGlkeXZlcnNlKWApIHBlcm8gcG9yIGFob3JhIHPDs2xvIAp2YW1vcyBhIHVzYXIgZnVuY2lvbmVzIGRlbCBwYXF1ZXRlIGBkcGx5cmAuCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQpyZXF1aXJlKHBhbG1lcnBlbmd1aW5zKQpyZXF1aXJlKGRwbHlyKQpgYGAKCgojIyMjIyAxClVzYXIgYGZpbHRlcigpYCBwYXJhIGNyZWFyIHVuIHN1YmNvbmp1bnRvIGRlIGRhdG9zIHF1ZSBjb250ZW5nYSBzw7NsbyBwaW5ndWlub3MKZGUgbGEgaXNsYSBCaXNjb2UgeSBxdWUgdGVuZ2FuIHVuIHBpY28gZGUgNDggbW0gZGUgbGFyZ28gbyBtw6FzLgoKIyMjIyMgMgpDcmVhciBvdHJvIGRhdGFzZXQgY29uIGxhIGluZm9ybWFjacOzbiBkZSBwaW5ndWlub3MgQWRlbGllIG1hY2hvcyBxdWUgbm8gaGF5YW4Kc2lkbyB2aXN0b3MgZW4gZWwgYcOxbyAyMDA4LgoKIyMjIyMgMwpEZWwgZGF0YXNldCBgcGVuZ3VpbnNgIHF1ZWRhcnNlIGNvbiB0b2RhcyBsYXMgdmFyaWFibGVzIGV4Y2VwdG8gYHllYXJgLCBgc2V4YCB5IApgYm9keV9tYXNzX2dgLiAKCiMjIyMjIDQKQ3JlYXIgdW4gc3ViY29uanVudG8gZGUgbG9zIGRhdG9zIGRlIGBwZW5ndWluc2Agc8OzbG8gY29uIGxhcyBvYnNldmFjaW9uZXMgZGUgCnBpbmd1aW5vcyBtYWNob3MgY29uIGFsZXRhcyBkZSBtw6FzIGRlIDIwMCBtbSBkZSBsYXJnbyB5IHF1ZWRhcnNlIGNvbiB0b2RhcyBsYXMKY29sdW1uYXMgcXVlIHRlcm1pbmFuIGNvbiAibW0iLiAodXNhciBsYSBmdW5jacOzbiBgZW5kc193aXRoKClgKS4KCiMjIyMjIDUKRW1wZXphbmRvIGNvbiBgcGVuZ3VpbnNgLCBoYWNlciB1biBgcGlwZWAgKGAlPiVgKSBxdWU6CgoqIHNlIHF1ZWRlIHPDs2xvIGNvbiBsYXMgb2JzZXJ2YWNpb25lcyBkZSBsYSBpc2xhIERyZWFtLgoqIHNlIHF1ZWRlIGNvbiBsYXMgdmFyaWFibGVzIGBzcGVjaWVzYCB5IHRvZGFzIGxhcyBxdWUgZW1waWVjZSBjb24gYGJpbGxgLiAKCiMjIyMjIDYKTW92ZXIgdG9kYXMgbGFzIHZhcmlhYmxlcyBgZmFjdG9yYCBkZXNwdcOpcyBkZSBsYXMgY29sdW1uYXMgYGludGVnZXJgLgpTZSBwdWVkZSB1c2FyIGByZWxvY2F0ZSgpYCBqdW50byBjb24gYGlzLmludGVnZXJgIHkgYGlzLmZhY3RvcmAuCgojIyMjIyA3CkNvbnZlcnRpciB0b2RhcyBsYXMgdmFyaWFibGVzIHF1ZSBlbXBpZXphbiBjb24gYGJpbGxgIGEgbWF5w7pzY3VsYXMuCmBgYHtyIGV2YWw9RkFMU0V9CnBlbmd1aW5zICU+JQogIHJlbmFtZV93aXRoKF9fX18sIHN0YXJ0c193aXRoKCJfX19fIikpCmBgYAoKIyMjIyMgOApFbXBlemFuZG8gY29uIGBwZW5ndWluc2AgaGFjZXIgbG8gc2lndWllbnRlIGNvbiB1biDDum5pY28gbGxhbWFkbyBhIGxhIGZ1bmNpw7NuCmBtdXRhdGUoKWA6CgoqIENvbnZlcnRpciBsYSB2YXJpYWJsZSBgc3BlY2llc2AgYSBgY2hhcmFjdGVyYC4KKiBDcmVhciB1bmEgbnVldmEgdmFyaWFibGUgcXVlIHRlbmdhIGVsIHBlc28gZW4gS2cuCiogQ29udmVydGlyIGxhIHZhcmlhYmxlIGBpc2xhbmRgIGEgbWluw7pzY3VsYS4KCiMjIyMjIDkKRW1wZXphbmRvIGNvbiBgcGVuZ3VpbnNgIGNyZWFyIHVuYSB0YWJsYSByZXN1bWVuIHF1ZSBjb250ZW5nYSBwYXJhIGVsIApsYXJnbyBtw61uaW1vIHkgbcOheGltbyBkZSBsYXMgYWxldGFzIGRlIGxvcyBwaW5ndWlub3MgY2hpbnN0cmFwLCBhZ3J1cGFkb3MKcG9yIGlzbGEuIAoKIyMjIyMgMTAKRW1wZXphbmRvIGNvbiBgcGVuZ3VpbnNgLCBhZ3J1cGFyIGxvcyBkYXRvcyBwb3IgZXNwZWNpZSB5IGHDsW8sIGx1ZWdvIGNyZWFyIHVuYSB0YWJsYSAKZGUgcmVzdW1lbiBxdWUgY29udGVuZ2EgZWwgYW5jaG8gZGVsIHBpY28gKGxsYW1hcmxhIGBiaWxsX2RlcHRoX21lYW5gKSB5IGVsIGxhcmdvIApkZWwgcGljbyAobGxhbWFybGEgYGJpbGxfbGVuZ3RoX21lYW5gKSBwYXJhIGNhZGEgZ3J1cG8KCmBgYHtyLCBldmFsPUZBTFNFfQpwZW5ndWlucyAlPiUKICBncm91cF9ieShfX19fXywgX19fX18pICU+JQogIHN1bW1hcml6ZSgKICAgIF9fX19fX19fXyA9IG1lYW4oX19fX19fLCBuYS5ybSA9IFRSVUUpLAogICAgX19fX19fX19fID0gbWVhbihfX19fX18sIG5hLnJtID0gVFJVRSkKICApCmBgYAoKCiMjIyMjIDExCkVtcGV6YW5kbyBjb24gYHBlbmd1aW5zYCwgaGFjZXIgdW5hIHNlY3VlbmNpYSBkZSBvcGVyYWNpb25lcyBgICU+JWAgcXVlOgoKKiBBZ3JlZ3VlIHVuYSBudWV2YSBjb2x1bW5hIGxsYW1hZGEgYGJpbGxfcmF0aW9gIHF1ZSBzZWEgZWwgY29jaWVudGUgZW50cmUgZWwgbGFyZ28geSBlbCAKYW5jaG8gZGVsIHBpY28uCiogUXVlZGFyc2Ugc8OzbG8gY29uIGxhcyBjb2x1bW5hcyBgc3BlY2llc2AgeSBgYmlsbF9yYXRpb2AuCiogQWdydXBhciBsb3MgZGF0b3MgcG9yIGVzcGVjaWUuCiogQ3JlYXIgdW5hIHRhYmxhIGRlIHJlc3VtZW4gcXVlIGNvbnRlbmdhIGVsIHByb21lZGlvIGRlIGxhIHZhcmlhYmxlIGBiaWxsX3JhdGlvYCBwb3IgZXNwZWNpZQp5IHF1ZSBlbCBub21icmUgZGUgbGEgY29sdW1uYSBlbiBsYSB0YWJsYSBzZWEgYGJpbGxfcmF0aW9fbWVhbmApCgpgYGB7ciwgZXZhbD1GQUxTRX0KcGVuZ3VpbnMgJT4lCiAgbXV0YXRlKGJpbGxfcmF0aW8gPSBfX19fX18gLyBfX19fX18pICU+JQogIHNlbGVjdChfX19fX18sIF9fX19fXykgJT4lCiAgZ3JvdXBfYnkoX19fX19fKSAlPiUKICBzdW1tYXJpemUoX19fX19fID0gbWVhbihfX19fX18sIG5hLnJtID0gVFJVRSkpCmBgYAoKCiMjIyMjIDEyCkVtcGV6YW5kbyBjb24gYHBlbmd1aW5zYCwgYWdydXBhciBsb3MgZGF0b3MgcG9yIGlzbGEgeSBkZXNwdcOpcyB1c2FyIGBhY3Jvc3MoKWAgcGFyYSBlbmNvbnRyYXIKbGEgbWVkaWFuYSBkZSBsb3MgZ3J1cG9zIHBhcmEgdG9kYXMgbGFzIGNvbHVtbmFzIHF1ZSBjb250ZW5nYW4gZWwgc3RyaW5nICJtbSIuIEVsIG5vbWJyZSAKZGUgbGFzIHZhcmlhYmxlcyB0aWVuZSBxdWUgc2VyIGVsIG5vbWJyZSBvcmlnaW5hbCBzZWd1aWRvIGRlIHVuIGd1acOzbiBiYWpvIHkgbGEgcGFsYWJyYSAKIm1lZGlhbiIgKG8gc2VhLCBgbm9tYnJlZGVsYWNvbHVtbmFfbWVkaWFuYCkKYGBge3IsIGV2YWw9RkFMU0V9CnBlbmd1aW5zICU+JQogIGdyb3VwX2J5KF9fX19fXykgJT4lCiAgc3VtbWFyaXplKGFjcm9zcyhjb250YWlucygiX19fX19fIiksCiAgICAgICAgICAgICAgICAgICBtZWRpYW4sCiAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAubmFtZXMgPSAiX19fX19fXyIpCiAgICAgICAgICAgICkKYGBgCgoKIyMjIyMgMTMKRW1wZXphbmRvIGNvbiBgcGVuZ3VpbnNgLCBxdWVkYXJzZSBjb24gbGFzIG9ic2VydmFjaW9uZXMgY29ycmVzcG9uZGllbnRlcyBhIGxvcyBwaW5ndWlub3MKQWRlbGllIHkgbHVlZ28gdXNhciBgYWNyb3NzKClgIHBhcmEgZW5jb250cmFyIGVsIHZhbG9yIG3DoXhpbW8gZGUgdG9kYXMgbGFzIHZhcmlhYmxlcyAKbnVtw6lyaWNhcyBwYXJhIGNhZGEgaXNsYS4KYGBge3IsIGV2YWw9RkFMU0V9CnBlbmd1aW5zICU+JQogIGZpbHRlcihzcGVjaWVzID09ICJfX19fX18iKSAlPiUKICBncm91cF9ieShfX19fX18pICU+JQogIHN1bW1hcml6ZShhY3Jvc3Mod2hlcmUoX19fX18pLCBfX19fXywgbmEucm0gPSBUUlVFKSkKYGBgCgoKIyMjIyMgMTQKRW1wZXphbmRvIGNvbiBgcGVuZ3VpbnNgLCBlc2NyaWJpciB1bmEgc2VjdWVuY2lhIGRlIG9wZXJhY2lvbmVzIGAgJT4lIGAgcXVlOgoKKiBFeGNsdXlhIGEgbG9zIHBpbmd1aW5vcyBvYnNlcnZhZG9zIGVuIGxhIGlzbGEgQmlzY29lLgoqIFPDs2xvIHNlIHF1ZWRlIGNvbiBsYXMgdmFyaWFibGVzIHF1ZSBlc3TDoW4gZW50cmUgYHNwZWNpZXNgIHkgYGJvZHlfbWFzc19nYCBpbmNsdXNpdmUuCiogUmVub21icmFyIGxhIHZhcmlhYmxlIGBzcGVjaWVzYCBhIGBlc3BlY2llX3Bpbmd1aW5vYC4KKiBBZ3J1cGFyIGxvcyBkYXRvcyBwb3IgbGEgdmFyaWFibGUgYGVzcGVjaWVfcGluZ3Vpbm9gLgoqIEVuY29udHJhciBlbCB2YWxvciBtZWRpbyBkZSBsYXMgdmFyaWFibGVzIHF1ZSBjb250aWVuZW4gZWwgc3RyaW5nIOKAnGxlbmd0aOKAnSwgCnNlcGFyYW5kbyBwb3IgbGEgZXNwZWNpZSBkZWwgcGluZ3Vpbm8sIHkgbGxhbWFuZG8gYSBsYXMgY29sdW1uYXMgY29tbyBsYXMgb3JpZ2luYWxlcwpwZXJvIGFncmVnYW5kbyAiX21lYW4iIGFsIGZpbmFsLgoKYGBge3IsIGV2YWw9RkFMU0V9CnBlbmd1aW5zICU+JQogIGZpbHRlcihpc2xhbmQgIT0gIl9fX19fIikgJT4lCiAgc2VsZWN0KF9fX19fOl9fX19fKSAlPiUKICByZW5hbWUoX19fX18gPSBfX19fXykgJT4lCiAgZ3JvdXBfYnkoX19fX18pICU+JQogIHN1bW1hcml6ZShhY3Jvc3MoY29udGFpbnMoIl9fX19fIiksIG1lYW4sIG5hLnJtID0gVFJVRSwgLm5hbWVzID0gInsuY29sfV9hdmciKSkKYGBgCgoKIyMjIyMgMTUKRW1wZXphbmRvIGNvbiBgcGVuZ3VpbnNgLCBjb250YXIgY3XDoW50YXMgb2JzZXJ2YWNpb25lcyBoYXkgcG9yIGVzcGVjaWUsIGlzbGEgeSBhw7FvLgoKIyMjIyMgMTYKRW1wZXphbmRvIGNvbiBgcGVuZ3VpbnNgLCBxdWVkYXJzZSBzw7NsbyBjb24gbG9zIHBpbmd1aW5vcyBBZGVsaWUgeSBnZW50b28gcGVuZ3VpbnMuIEx1ZWdvCmNvbnRhciBjdcOhbnRvcyBoYXkgcG9yIGNhZGEgZXNwZWNpZSB5IHNleG8uCgojIyMjIyAxNwpBZ3JlZ2FyIHVuYSBudWV2YSBjb2x1bW5hIGEgbGEgYmFzZSBkZSBkYXRvcyBsbGFtYWRhIGBjYW1wYcOxYWAgcXVlIGNvbnRlbmdhOgoKKiDigJxjMeKAnSBzaSBlbCBhw7FvIDIwMDcKKiDigJxjMuKAnSBzaSBlbCBhw7FvIDIwMDgKKiDigJxjM+KAnSBzaSBlbCBhw7FvIDIwMDkKCiMjIyMjIDE4CkVtcGV6YW5kbyBjb24gYHBlbmd1aW5zYCBxdWVkYXJzZSBzw7NsbyBjb24gbGFzIG9ic2VydmFjaW9uZXMgY29ycmVzcG9uZGllbnRlcyBhIHBpbmd1aW5vcwpjaGluc3RyYXAuIEx1ZWdvLCBxdWVkYXJzZSBzw7NsbyBjb24gbGFzIHZhcmlhYmxlcyBgZmxpcHBlcl9sZW5ndGhfbW1gIHkgYGJvZHlfbWFzc19nYC4gCkFncmVnYXIgdW5hIG51ZXZhIGNvbHVtbmEgbGxhbWFkYSBgZm1fcmF0aW9gIHF1ZSBjb250ZW5nYSBlbCBjb2NpZW50ZSBlbnRyZSBlbCBsYXJnbyBkZSBsYSAKYWxldGEgeSBlbCBwZXNvIGRlbCBwaW5ndWluby4gTHVlZ28gYWdyZWdhciBvdHJhIGNvbHVtbmEgbGxhbWFkYSBgcmF0aW9fYmluYCBxdWUgY29udGVuZ2EKbGEgcGFsYWJyYSAiYWx0byIgc2kgYGZtX3JhdGlvYCBlcyBtYXlvciBvIGlndWFsIHF1ZSAwLjA1LCAiYmFqbyIgc2kgZWwgY29jaWVudGUgZXMgbWVub3IKcXVlIDAuMDUgeSAibm8gaGF5IHJlZ2lzdHJvIiBlbiBjdWFscXVpZXIgb3RybyBjYXNvIChjb21vIHBvciBlamVtcGxvIHNpIGVsIGNvY2llbnRlIGVzCnVuIE5BKQoKYGBge3IsIGV2YWw9RkFMU0V9CnBlbmd1aW5zICU+JQogIGZpbHRlcihzcGVjaWVzID09ICJfX19fXyIpICU+JQogIHNlbGVjdChfX19fXywgX19fX18pICU+JQogIG11dGF0ZShmbV9yYXRpbyA9IF9fX19fIC8gX19fX18pICU+JQogIG11dGF0ZShyYXRpb19iaW4gPSBjYXNlX3doZW4oCiAgICBmbV9yYXRpbyA+PSAwLjA1IH4gIl9fX19fIiwKICAgIGZtX3JhdGlvIDwgMC4wNSB+ICJfX19fXyIsCiAgICBUUlVFIH4gIl9fX19fIgogICkpCmBgYAoK