Hatena::ブログ(Diary)

Windows より Mac より Linux がいい

2011-06-05

FizzBuzz ジェネレータ

と勉で、FizzBuzz 知らないよって人が数人いたので、どうしてプログラマに・・・プログラムが書けないのか? に有名な和訳があるので読んでみてください。

問題は

1から100までの数をプリントするプログラムを書け。ただし3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」とプリントし、3と5両方の倍数の場合には「FizzBuzz」とプリントすること。

です。まだ、if文を習っていない1年生は分からないと思います(次回説明します)が、2年生以上には、スラスラと書けて欲しいです。

それだけのための記事にするのはもったいないので、OCaml, Scala, Python, Hakell で書きました。

OCamlFizzBuzz

let iota n m =
  let rec loop a i =
    if i > 0  then loop (i::a) (i-1) else a
  in loop [] (n-m+1)

let genFizzBuzz n =
  List.map
    (fun x -> 
       match (x mod 3, x mod 5) with
           (0, 0) -> "FizzBuzz"
         | (0, _) -> "Fizz"
         | (_, 0) -> "Buzz"
         | _ -> string_of_int x)
    (iota n 1)

let _ =
  List.iter (fun x -> print_endline x) (genFizzBuzz 100)

(* 古いバージョン *)
let _genFizzBuzz n =
  List.map
    (fun x -> 
       match x with
           x when x mod 15 == 0 -> "FizzBuzz"
         | x when x mod  3 == 0 -> "Fizz"
         | x when x mod  5 == 0 -> "Buzz"
         | x -> string_of_int x)
    (iota n 1)

ScalaFizzBuzz

object FizzBuzz {
  def genFizzBuzz(n: Int) = {
    for(x <- 1 to n) yield {
      (x % 3, x % 5) match {
        case (0, 0) => "FizzBuzz"
        case (0, _) => "Fizz"
        case (_, 0) => "Buzz"
        case _ => x.toString
      }
    }
  }

  def main(args: Array[String]) = {
    for(x <- genFizzBuzz(100)) {
      println(x)
    }
  }

  // 古いバージョン
  def _genFizzBuzz(n: Int) = {
    for(i <- 1 to n) yield {
      i match {
        case x if x % 15 == 0 => "FizzBuzz"
        case x if x %  3 == 0 => "Fizz"
        case x if x %  5 == 0 => "Buzz"
        case x => x.toString
      }
    }
  }
}

PythonFizzBuzz

def genFizzBuzz(n):
    def f(i):
        if i % 15 == 0:
            return "FizzBuzz"
        elif i % 3 == 0:
            return "Fizz"
        elif i % 5 == 0:
            return "Buzz"
        else:
            return str(i)
            
    for i in range(1,n+1):
        yield f(i)

for a in [x for x in genFizzBuzz(100)]:
    print a

無駄に 内包記法で書いてあるけど、よく忘れるから。


HaskellFizzBuzz

module Main where

genFizzBuzz =  map f [x | x <- [1..]]
  where f n = case (n `mod` 3, n `mod` 5) of
      (0, 0) -> "FizzBuzz"
      (0, _) -> "Fizz"
      (_, 0) -> "Buzz"
      _      -> show(n)

main =  do
  putStrLn $ foldr (\ x y -> x ++ ('\n':y)) "" (take 100 genFizzBuzz)

-- 古いバージョン
_genFizzBuzz =  map f [x | x <- [1..]]
  where
    f n = case n of
      n | n `mod` 15 == 0 -> "FizzBuzz"
      n | n `mod`  3 == 0 -> "Fizz"
      n | n `mod`  5 == 0 -> "Buzz"
      n -> show n

camlspotter さんにご指摘いただいたので、ちょっと修正しました。