トラック
/
R
R
/
演習
/
ブラックジャック
ブラックジャック

ブラックジャック

学習演習

はじめに

switch()関数は、長いif ... else ifのテストの連続を簡潔に置き換えてくれます。 切り替えの対象になる変数はたいてい文字列で、その場合はセレクターから引用符を省略できます。

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"

上の例のMのように、値が空のままの場合にのみ、選択肢は次の値へフォールスルーする点に注意してください。 他の言語のようにbreak文を書く必要はありません。

character型を切り替える場合、ここでのように最後の値がデフォルトになります。 整数型の場合、デフォルトは指定できません。

dplyrの関数

Rの基本機能にあるswitchはかなり限定的で、1つの入力に対する完全一致しか行えません。 1993年にRが最初にリリースされた当時は合理的でしたが、現代の使い方には改善が必要です。

Note

Conditionalsのコンセプトで触れたように、tidyverseはパッケージを集めたもので、後方互換性に影響を与えずにRの基本機能を補完する(ときに置き換える)ように設計されています。

dplyrパッケージをスコープに入れるには、コードの先頭にlibrary(dplyr)(1つのパッケージだけを使う場合)かlibrary(tidyverse)(コレクション全体を使う場合)のどちらかを追加します。

dplyrライブラリには、switchに関連する2つの追加関数があります。

recode_values関数とreplace_values関数

これら2つのよく似た関数は、古い値から新しい値への、ベクトル化されたswitchに似た対応付けを可能にします。

両者の主な違いは、recode_values()がまったく新しいベクトルを作るのに対し、replace_values()は既存のベクトルを部分的に更新できる点です。

一致はやはり完全一致ですが、次の点が異なります。

  • 左側の選択肢はベクトルにでき、いずれかの要素が一致すれば入力が一致したとみなされます。
  • 左側の選択肢と右側の結果は、=ではなくチルダ~で結びます。
  • どの場合でもデフォルトを指定できます。
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

case_when関数

case_whenはcase_matchの構文をさらに一歩進め、~の左側に任意の論理式を書けるようにします。

入力のベクトル(下の例ではx)は引数として渡す必要はなく、すでに定義されていればよいだけです。

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?"

between()関数もdplyrの一部です。

説明

この演習では、ブラックジャックのゲームの最初のターンをシミュレートします。

2枚のカードを受け取り、ディーラーの表向きのカードを見ることができます。カードはすべて、"ace"、"king"、"three"、"two"などの文字列で表されます。各カードの値は次のとおりです。

カード 値 カード 値
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 other 0

注意:一般的に、エースは1または11の値を取ることができますが、簡単にするために、ここでは11の値しか取らないものとします。

手元の2枚のカードとディーラーのカードに応じて、ゲームの最初のターンで取るべき戦略が決まります。選択肢は次のとおりです。

  • スタンド(S)
  • ヒット(H)
  • スプリット(P)
  • 自動的に勝利(W)

まだ最適とは言えませんが、ここでは友人のAlexが開発を進めてきた戦略に従います。それは次のとおりです。

  • エースのペアがある場合は、必ずスプリットしなければなりません。
  • ブラックジャック(合計が21になる2枚のカード)で、ディーラーがエース、絵札、または10を持っていない場合は、自動的に勝利します。ディーラーがこれらのカードのいずれかを持っている場合は、スタンドして、もう1枚のカードが公開されるのを待たなければなりません。
  • カードの合計が[17, 20]の範囲内であれば、必ずスタンドします。
  • カードの合計が[12, 16]の範囲内であれば、ディーラーが7以上を持っていない限り、必ずスタンドします。ディーラーが7以上を持っている場合は、必ずヒットします。
  • カードの合計が11以下であれば、必ずヒットします。

1. 任意のカードの数値を計算する

カードの数値を計算する関数parse_cardを実装してください。

parse_card("ace")
# => 11

2. 最初のターンの判断ロジックを実装する

上で説明した判断ロジックを実装する関数first_turnを書いてください。

first_turn(card1, card2, dealer_card)

期待される結果の例をいくつか示します。

first_turn("ace", "ace", "jack") == "P"
first_turn("ace", "king", "ace") == "S"
first_turn("five", "queen", "ace") == "H"
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
R Exercism

ブラックジャックを始める準備はできましたか?

Exercismに登録すれば、21個のコンセプト111個の演習、そして本物の人間によるメンタリングとともに、Rを学んでマスターできます。すべて無料です。