Haskellに興味を持って調べてたら夜が明けちまった。
とりあえず開発環境をインストールして勉強も兼ねて「ブラックジャックのディーラーのアップカードとバースト率」を計算してみた。
結果は↓ まぁネットで調べたら似たような数値が出るはず。
UpCard 1 : 0.1152862703011695
UpCard 2 : 0.35360813639536126
UpCard 3 : 0.3738748853821433
UpCard 4 : 0.39446844550254284
UpCard 5 : 0.4164036695822623
UpCard 6 : 0.42315049208499766
UpCard 7 : 0.2623124083615333
UpCard 8 : 0.2447412422511914
UpCard 9 : 0.2284251594344453
UpCard 10 : 0.2121090766176992
UpCard 11 : 0.2121090766176992
UpCard 12 : 0.2121090766176992
UpCard 13 : 0.2121090766176992
で、問題のプログラム
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
module Main where
--カードをゲーム内の強さに変換
toValue x | x > 10 = 10
| x == 1 = 11
| otherwise = x
--ブラックジャックかどうか
isBlackJack x = bj_sum(x) == 21
--バーストかどうか
isBurst x = x > 21
--エースカード(A)かどうか
isAce x = x == 1
--かならず1を返す
const1 x = 1
--エースカードの枚数を数える
bj_count_ace x = sum (map const1 (filter (isAce) x))
--エースカードを除く合計を出す
bj_sum_not_ace x = sum (map toValue (filter (not . isAce) x))
--カードを渡してゲームとしての手の強さを返す
bj_sum :: [Integer] -> Integer
bj_sum x = bj_sum_ace(bj_sum_not_ace x, bj_count_ace x)
--x=Aを除くカードの合計 y=Aの枚数
--ゲームとしての手の強さを返す
bj_sum_ace(x,0) = x
bj_sum_ace(x,y) = if isBurst(x+y+10) then x+y else x+y+10
--デバッグ用 カードの状態表示
showState :: [Integer] -> IO()
showState x = do print x
putStr "SUM = "
print (bj_sum x)
putStr "Burst = "
print (isBurst (bj_sum x))
putStr "BlackJack = "
print (isBlackJack x)
--ディーラーのカードがxだった場合のバースト率
odds :: [Integer] -> Double
odds x = if isBurst(bj_sum x) then 1.0
else if (bj_sum x < 17) then
hit_odds(x)
else 0.0
--カード配列
cardArray = map (:[]) [1..13]
--ディーラーのカードがxだった場合にディーラーがヒットした時のバースト率
hit_odds :: [Integer] -> Double
hit_odds x = sum(map odds (map (x++) cardArray))/13.0
--バースト率表示
showOdds x = do putStr "UpCard ";
putStr (show x)
putStr " : "
print (odds (x:[]))
--各カードのバースト率を表示(エントリポイント)
main = sequence_ (map showOdds [1..13])
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
こんなのやってたら1日休みが終わってしまったorz
純関数型言語というらしくて今までと作り方が全然違う。
感覚的にはエクセル表のセルに式を次々埋めていって答えを求める感じか
ちょっといじってて連想したのがC#3.0のLINQ
あれも、LINQで記述したところが評価されるのって実際に値を使うところだったような
そういう意味では関数型言語の概念を取り入れてるのかなぁ
でもまぁ、なれてないせいかすげー組みにくい。
とりあえず触りだけやって雰囲気を掴んだので終了。
あとは、もっとはやりだしたら本気でやろう