【3日目】KaggleでPythonの勉強してみた【独学】
KaggleのCourseタブからPythonの勉強ができるのでそのノートを取ります
Lesson:Booleans<Exercise>
勉強時間:120分以上
Lesson:Booleans<Exercise>
Q1:入力値が正であれば1、負であれば-1、0であれば0を変えすsign関数を作成せよ。
Q2:入力値が1の場合はprintの内容を単数形、複数の場合はprintの内容を複数形で返す関数を作成せよ。
Q3:定義されている関数のバグを探せ。
当たりはつけてたけど、特定に時間をかけてしまった。
Q4:負の数だけTrueを返す関数を作成せよ
Q5:ホットドッグの3つのトッピングが下記の場合にTrueを返す関数を作成せよ。
①オニオン抜き
②すべてのトッピングなし
③ケチャップ・マスタードどちらかを選んだ場合
問題を勘違いして、めちゃくちゃ難しく考えてしまった…。
無駄な時間…。
ベン図を使うとすぐわかる。
Q6:④一つのトッピングのみをオーダーした場合。
bool()に対してint()を呼ぶとどうなるだろうか?またそれを利用して簡潔な関数を書くこと。
bool(int())はTutorialで行っている通り、0以外はFalseで返す。
int(bool())にするとどうなるか?
これは、関数外で、やってみるとすぐわかるけど、True=1, False=0になる。
ベン図じゃなくて、一覧表を書くと容易に四則演算で何とかなることわかる。
Q7:(選択問題)ブラックジャックでプレイヤーになってコントロールする関数を作る。
- プレイヤーは2枚のカードをもち、ディーラーは1枚のカードを持つ。
- プレイヤーは何回でも”ヒット”によってカードを受け取ることができるが、カードの合計が21を超えるとラウンドは終了し、負ける
- ディーラーは以下を満たすまでカードを配り続ける。
- ディーラーのカード合計が21を越したとき。(プレイヤーの勝ち)
- ディーラーのカード合計が17を超え、かつ、プレイヤーのカード合計がディーラーのカードより大きい場合。(プレイヤーの勝ち)
- それ以外の場合はディーラーの勝利
合計の計算
ジャック・クイーン・キングは10
エースは合計が21を超えないように、1または11として数える。
ゲームで勝率を上げられるか。これは正解も何もないんだけど、条件式の練習です。
ちなみに結果(デフォルト)は勝率38.3%(5万回試行、以下すべて)で、ブラックジャックはディーラーの勝率の方が高いといわれているそうなので、50%を超えれれば万々歳です。
一応ルール的に17以上はヒットしない方がよいようにみえたので、17あればヒットしない関数を作りました。
if player_total<=17:
return True
else:
return False
結果(条件1つ追加)は勝率39.4%
あんまり変わらないですね。
条件式の練習なので、戦略は下記のベーシックストラテジーを参照にしてみます。
ここではスタンドとヒットしかできないので、Rはヒット、Dはヒット、Dはスタンドとします。
スプリットは今回のルールではできない…。ので、スプリットは一回無視します。
=ハードハンドとソフトハンドのみ
ちょっと面倒くさくなってるところは、ちょっと省く感じで笑
関数のきれいさは置いておいて、愚直にコーディングしていきます。
if player_high_aces == 0:
if 8<=player_total<=11:
return True
elif (13<=player_total<=16) and (7<=dealer_total<=10):
return True
elif player_total == 12 and *1:
return True
elif (13<=player_total<=16) and (2<=dealer_total<=6):
return False
elif player_total == 12 and (4<=dealer_total<=6):
return False
elif player_total == 17:
return False
elif player_high_aces ==1:
if 13<=player_total<=17:
return True
if 18<=player_total<=19:
return False
そして結果は…
結果(ベーシックストラテジー)は 勝率42.3%
確かに、勝率上がったものの、+3%かーーーー!
こういうたぐいの勝率を上げるのは、大変なんですよね。
ちなみに一般的な勝率は47~48%らしいので、全然届いていません。
勝率を出すのは5万回試行ですが、1回のみ試すという関数もあって実行してみました。
------------------------------------------------
Player starts with 2 and A (total = 13)
Dealer starts with K
__Player's turn__
Player hits and receives 3. (total = 16)
Player hits and receives 8. (total = 14)
Player hits and receives 10. (total = 24)
Player busts! Dealer wins.
------------------------------------------------
Player turnの2列目(赤字)ところ、なんでこうなるんだろう。
ここで14になる理由がわかってないので、多分相変わらずここの英語が読めてないのかなー笑
------------------------------------------------
Player starts with 3 and 3 (total = 6)
Dealer starts with 8
__Player's turn__
Player stays
__Dealer's turn__
Dealer hits and receives 3. (total = 11)
Dealer hits and receives 5. (total = 16)
Dealer hits and receives 6. (total = 22)
Dealer busts! Player wins.
------------------------------------------------
ステイをとるとこういう挙動
DealerのTurnになるとPlayerは動かないのか。
したら、確かにデフォルトの「Stayしかとらない」という戦略はDealerの自爆を誘発するだけだから、ある程度ありうる戦略なのかも
もう少し勝率をあげに行きたいところだけど、この関数は仕組みがブラックボックスになっているし、試行の中身がわからない=何が敗因だったかわからないので、以上でやめることにしました。
この設問に関しては解がないので、残念ながら参照することもできず。
奥が深いよなー
ブラックジャックの他の人の回答はこんな感じ。
42%を引っ提げていくとあまり悪くはない気がする。
一つだけ面白そうなのを見つけたので、真似してみました。
結果は見事!
Player won 50000 out of 50000 games (win rate = 100.0%)
関数の裏を突いたのかなあ。追加行はたった3行だけでした。すごい笑
<新出単語>
get credit:面目を施す
verbose:くどい、冗長な
*1:2<=dealer_total<=3)or (7<=dealer_total<=10