Trilhas
/
R
R
/
Exercícios
/
Blackjack
Blackjack

Blackjack

Exercício de aprendizagem

Introdução

A função switch() pode ser uma substituição concisa para uma longa série de testes if ... else if. A variável sobre a qual se faz o switch geralmente é uma string e, nesse caso, as aspas podem ser omitidas do seletor.

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"

Repare que as opções só passam para a próxima se o valor for deixado em branco, como acontece com M no exemplo acima. Não é preciso incluir instruções break, como acontece em algumas outras linguagens.

Ao fazer switch sobre tipos character, o valor final é um padrão, como aqui. Com tipos inteiros, não é possível definir um padrão.

Funções no dplyr

O switch do R base é bastante limitado: ele só faz uma correspondência exata com uma única entrada. Isso parecia razoável quando o R foi lançado, em 1993, mas precisa melhorar para o uso moderno.

Note

Como mencionado no Conceito Conditionals, a coleção de pacotes tidyverse foi projetada para complementar (e às vezes substituir) a funcionalidade do R base sem prejudicar a compatibilidade com versões anteriores.

O pacote dplyr pode ser trazido para o escopo adicionando library(dplyr) (para o pacote isolado) ou library(tidyverse) (para a coleção inteira) ao topo do seu código.

A biblioteca dplyr oferece duas funções extras relacionadas ao switch.

As funções recode_values e replace_values

Essas duas funções relacionadas permitem um mapeamento vetorizado, parecido com o switch, de valores antigos para valores novos.

A principal diferença entre elas é que recode_values() cria um vetor totalmente novo, enquanto replace_values() permite atualizações parciais de um vetor existente.

A correspondência ainda é exata, mas:

  • As opções à esquerda podem ser vetores, e a entrada corresponde se qualquer elemento corresponder.
  • As opções à esquerda e os resultados à direita são ligados com um til ~ em vez de =.
  • Um padrão pode ser especificado em todos os casos.
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

A função case_when

O case_when leva a sintaxe do case_match um passo adiante, ao permitir qualquer expressão lógica à esquerda do ~.

O vetor de entrada (x no exemplo abaixo) não é fornecido como argumento, ele só precisa já estar 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?"

A função between() também faz parte do dplyr.

Instruções

Neste exercício, vamos simular a primeira rodada de um jogo de Blackjack.

Você vai receber duas cartas e poderá ver a carta aberta do dealer. Todas as cartas são representadas por uma string, como "ace", "king", "three", "two", etc. Os valores de cada carta são:

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 outra 0

Observação: Normalmente, os ases podem valer 1 ou 11, mas, para simplificar, vamos assumir que só podem valer 11.

Dependendo das suas duas cartas e da carta do dealer, existe uma estratégia para a primeira rodada do jogo, na qual você tem as seguintes opções:

  • Parar (S)
  • Pedir carta (H)
  • Dividir (P)
  • Vitória automática (W)

Embora ainda não seja ideal, você vai seguir a estratégia que seu amigo Alex vem desenvolvendo, que é a seguinte:

  • Se você tiver um par de ases, deve sempre dividi-los.
  • Se você tiver um Blackjack (duas cartas que somam 21) e o dealer não tiver um ás, uma figura ou um dez, você ganha automaticamente. Se o dealer tiver qualquer uma dessas cartas, você vai ter que parar e esperar que a outra carta seja revelada.
  • Se a soma das suas cartas estiver no intervalo [17, 20], você deve sempre parar.
  • Se a soma das suas cartas estiver no intervalo [12, 16], você deve sempre parar, a menos que o dealer tenha um 7 ou mais, e nesse caso você deve sempre pedir carta.
  • Se a soma das suas cartas for 11 ou menos, você deve sempre pedir carta.

1. Calcule o valor de qualquer carta.

Implemente uma função parse_card para calcular o valor numérico de uma carta:

parse_card("ace")
# => 11

2. Implemente a lógica de decisão para a primeira rodada.

Escreva uma função first_turn que implemente a lógica de decisão descrita acima:

first_turn(card1, card2, dealer_card)

Aqui estão alguns exemplos dos resultados esperados:

first_turn("ace", "ace", "jack") == "P"
first_turn("ace", "king", "ace") == "S"
first_turn("five", "queen", "ace") == "H"
Editar via GitHub O link abre em uma nova janela ou aba
R Exercism

Tudo pronto para começar Blackjack?

Crie sua conta no Exercism para aprender e dominar R com 21 conceitos111 exercícios e mentoria humana de verdade, tudo de graça.