« 2012年7月 | トップページ | 2012年10月 »

2012年8月

2012年8月 7日 (火)

数当て問題 - Hit & Blow -

またしても人様のブログからネタを拝借。

こちらのブログに Haskell で書かれた「数当てゲーム」のコードがありました。
ルールは

  • コンピュータが生成した、重複のない 4 桁の数字を当てる。
  • コンピュータは、予想した数に対して、以下のヒントを返す。
    • Hit: 数字はあっているが、場所が異なる数字の数
    • Blow:数字も場所もあっている数字の数

というものです。

私も自分なりに考えてみました。

コンソールから数字を入力して、その度に Hit と Blow の数を返すようにしたのですが、入力が「文字列」になるので、Hit も Blow も文字列同士を比較することにしました。それによってコードが簡単になったと思います。

入力された文字列に対するエラーチェックはしていない、かなり手抜きのコードですが…。

import Data.List
import Random

countTrue :: [Bool] -> Int
countTrue = length . filter (== True)

countHit :: String -> String -> Int
countHit target = countTrue . map (`elem` target)

countBlow :: String -> String -> Int
countBlow target = countTrue . zipWith (==) target

checkNum :: String -> IO ()
checkNum target = do
  putStrLn "input number : "  
  input <- getLine
  let b = countBlow target input
  if b == 4
    then print "good !!"
    else do let h = countHit target input
            putStrLn $ show h ++ " hit(s), " ++ show b ++ "blow(s)\n"
            checkNum target

-- xs からランダムに重複しない n 個の要素を取り出す
randomPicUp :: Eq a => Int -> [a] -> IO [a]
randomPicUp n xs = loop n (length xs - 1) xs []
  where
    loop 0 _ _ prd = return prd
    loop c m xs prd = do
      g <- newStdGen
      let (i, _) = randomR (0, m) g
      let x = xs !! i
      loop (c - 1) (m - 1) (delete x xs) (x : prd)

main :: IO ()
main = do
  target <- randomPicUp 4 ['0'..'9']
  print target                  -- カンニング
  checkNum target

HTML generated by org-mode 6.33x in emacs 23

« 2012年7月 | トップページ | 2012年10月 »

2016年7月
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
フォト

最近のトラックバック

無料ブログはココログ