Haskell で FibBuzz

元ネタ: C++ で FibBuzz
元凶: 钱柜娱乐_钱柜娱乐平台_钱柜娱乐777(唯一)官方网站
関連: Haskell で FizzBuzz

追記( 23:50 ): otherwise を間違って使っていたのを _ に修正 http://d.hatena.ne.jp/gintenlabo/20111015/1318689620


この程度,とても簡単です. そう, Haskell ならね.

import System
import Data.List

isMultOf :: Integral a => a -> a -> Bool
x `isMultOf` n = ( x `rem` n == 0 )

fizzBuzz :: Integral a => a -> String
fizzBuzz n = fizzBuzz' ( n `isMultOf` 3 ) ( n `isMultOf` 5 ) where
  fizzBuzz' False False = show n
  fizzBuzz' True  False = "Fizz"
  fizzBuzz' False True  = "Buzz"
  fizzBuzz' True  True  = "FizzBuzz"

fibs :: Integral a => [a]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

main = do
  args <- System.getArgs
  
  let n = case args of
            []  -> 30  -- Ideone にうpするので無引数にも対応
            [x] -> read x
            _   -> error "Invalid Program Option"
  
  putStrLn $ intercalate ", " $ map fizzBuzz $ take n fibs

http://ideone.com/zA0SX


改行区切りだと味気ないので, intercalate を使ってカンマ区切りにしてみました.
フィボナッチ数列は,よくある定義なので,わかりますよね?
分からない方は「Haskell Fib」辺りで ぐぐる先生に訊いてみるといいと思います.


// たぶん,というか,間違いなく既出.

追記( 22:30 )

上記の定義のフィボナッチ数列だと,最適化無しの場合に遅いので,そこを改良しつつ,
オプション解析もちょっと真面目に行う感じで, fibBuzz を書き直してみました.

import System
import System.IO
import Data.List
import Text.Printf

isMultOf :: Integral a => a -> a -> Bool
x `isMultOf` n = ( x `rem` n == 0 )

fizzBuzz :: Integral a => a -> String
fizzBuzz n = fizzBuzz' ( n `isMultOf` 3 ) ( n `isMultOf` 5 ) where
  fizzBuzz' False False = show n
  fizzBuzz' True  False = "Fizz"
  fizzBuzz' False True  = "Buzz"
  fizzBuzz' True  True  = "FizzBuzz"

fibs :: Num a => [a]
fibs = fibs' 1 1 where
  fibs' a b = a : fibs' b (a+b)

getN :: IO Int
getN = do
  args <- System.getArgs
  case args of
    []  -> return 30
    [x] -> readIO x
      `catch` (\_ -> do
        argv0 <- getProgName
        hPrintf stderr "%s: error: Cannot interpret `%s' as an integer\n" argv0 x
        exitWith $ ExitFailure 2
      )
    _ -> do
      argv0 <- getProgName
      hPrintf stderr "%s: error: Too many arguments passed\n" argv0
      exitWith $ ExitFailure 2

main = do
  n <- getN
  putStrLn $ intercalate ", " $ take n $ map fizzBuzz fibs

http://ideone.com/Q1P0Z


hPrintf さんが いい味出してます.