Rutas
/
R
R
/
Ejercicios
/
Blackjack
Blackjack

Blackjack

Ejercicio de aprendizaje

Introducción

La función switch() puede ser un reemplazo conciso de una larga serie de comprobaciones if ... else if. La variable sobre la que se hace el switch suele ser un string y, en ese caso, las comillas pueden omitirse del selector.

star <- function(type) {
  switch(type,
    M = , # will "fall through" if no value given
    K = "red dwarf",
    G = "Earth-like",
    "bigger star" # only correct for O,B,A,F
  )
}

> star("M")
[1] "red dwarf"

Ten en cuenta que las opciones solo pasan a la siguiente si el valor se deja en blanco, como ocurre con M en el ejemplo anterior. No es necesario incluir instrucciones break, como sí se hace en otros lenguajes.

Cuando se hace el switch sobre tipos character, el valor final es un valor por defecto, como aquí. Con los tipos enteros, no se puede indicar ningún valor por defecto.

Funciones en dplyr

El switch de R base es bastante limitado: solo hace una coincidencia exacta con una única entrada. Esto parecía razonable cuando R se lanzó por primera vez en 1993, pero necesita mejoras para el uso moderno.

Note

Como se mencionó en el concepto Conditionals, la colección de paquetes tidyverse está diseñada para complementar (y a veces reemplazar) la funcionalidad de R base sin afectar a la retrocompatibilidad.

Puedes incorporar el paquete dplyr al scope añadiendo al principio de tu código library(dplyr) (para el paquete individual) o library(tidyverse) (para toda la colección).

La biblioteca dplyr proporciona dos funciones adicionales relacionadas con switch.

Las funciones recode_values y replace_values

Estas dos funciones relacionadas permiten un mapeo vectorizado, similar a switch, de valores antiguos a valores nuevos.

La principal diferencia entre ambas es que recode_values() crea un vector completamente nuevo, mientras que replace_values() permite actualizaciones parciales de un vector existente.

La coincidencia sigue siendo exacta, pero:

  • Las opciones de la izquierda pueden ser vectores, y la entrada coincide si coincide algún elemento.
  • Las opciones de la izquierda y los resultados de la derecha se vinculan con una tilde ~ en lugar de =.
  • En todos los casos se puede especificar un valor por defecto.
library(dplyr)

x <- c("a", "b", "a", "d", "b", NA, "c", "e", "z")
recode_values(
  x,
  "a" ~ 1,
  "b" ~ 2,
  "c" ~ 3,
  c("d", "e") ~ 4, # either "d' or "e" will match
  NA ~ 0,          # matches missing values
  default = 100   # note the different syntax for the default
)
#> [1]   1   2   1   4   2   0   3   4 100

La función case_when

case_when lleva la sintaxis de case_match un paso más allá, ya que permite cualquier expresión lógica a la izquierda del ~.

El vector de entrada (x en el ejemplo siguiente) no se pasa como argumento; simplemente tiene que estar ya definido.

x <- 1:10
case_when(
  x < 3 ~ "low",
  between(x, 3, 5) ~ "mid",
  between(x, 6, 8) ~ "high",
  .default = "what?"
)
#>  [1] "low"   "low"   "mid"   "mid"   "mid"   "high"  "high"  "high"  "what?" "what?"

La función between() también forma parte de dplyr.

Instrucciones

En este ejercicio vamos a simular el primer turno de una partida de Blackjack.

Recibirás dos cartas y podrás ver la carta descubierta del crupier. Todas las cartas se representan con un string como «ace», «king», «three», «two», etc. Los valores de cada carta son:

carta valor carta valor
ace 11 eight 8
two 2 nine 9
three 3 ten 10
four 4 jack 10
five 5 queen 10
six 6 king 10
seven 7 otra 0

Nota: Normalmente, los ases pueden tener el valor de 1 o 11, pero por simplificar supondremos que solo pueden tener el valor de 11.

Dependiendo de tus dos cartas y de la carta del crupier, existe una estrategia para el primer turno de la partida, en la que tienes las siguientes opciones:

  • Plantarse (S)
  • Pedir (H)
  • Dividir (P)
  • Ganar automáticamente (W)

Aunque todavía no es óptima, seguirás la estrategia que tu amigo Alex ha estado desarrollando, que es la siguiente:

  • Si tienes una pareja de ases, siempre debes dividirlos.
  • Si tienes un Blackjack (dos cartas que suman un valor de 21) y el crupier no tiene un as, una figura o un diez, ganas automáticamente. Si el crupier tiene alguna de esas cartas, tendrás que plantearte y esperar a que se revele la otra carta.
  • Si tus cartas suman un valor dentro del intervalo [17, 20], siempre debes plantearte.
  • Si tus cartas suman un valor dentro del intervalo [12, 16], siempre debes plantearte a menos que el crupier tenga un 7 o más, en cuyo caso siempre debes pedir.
  • Si tus cartas suman 11 o menos, siempre debes pedir.

1. Calcula el valor de cualquier carta.

Implementa una función parse_card para calcular el valor numérico de una carta:

parse_card("ace")
# => 11

2. Implementa la lógica de decisión para el primer turno.

Escribe una función first_turn que implemente la lógica de decisión como se describe arriba:

first_turn(card1, card2, dealer_card)

Aquí tienes algunos ejemplos de los resultados esperados:

first_turn("ace", "ace", "jack") == "P"
first_turn("ace", "king", "ace") == "S"
first_turn("five", "queen", "ace") == "H"
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
R Exercism

¿Listo para empezar Blackjack?

Regístrate en Exercism para aprender y dominar R con 21 conceptos111 ejercicios y mentoría humana real, todo gratis.