OCamlでFizz Buzz
今日はOCamlの勉強をした。それで、Fizz Buzzなるプログラミング問題があるらしいので早速OCamlで書いてみた。
Fizz Buzzは、数字をカウントアップしながら言って、
- 数字が3の倍数なら、数字の代わりに"Fizz"と言う
- 5の倍数なら"Buzz"と言う
- 3の倍数で5の倍数でもあるなら"Fizz Buzz"と言う
というゲームらしい。これ、おもしろいのかなあ?
let fizzbuzz n = let rec iter i n = if i > n then () else if i == 1 then begin print_string "1"; iter 2 n end else begin print_string ", "; if i mod 15 == 0 then begin print_string "Fizz Buzz"; iter (i + 1) n end else if i mod 3 == 0 then begin print_string "Fizz"; iter (i + 1) n end else if i mod 5 == 0 then begin print_string "Buzz"; iter (i + 1) n end else begin print_int i; iter (i + 1) n end end in iter 1 n;; fizzbuzz (int_of_string Sys.argv.(1));; print_string "\n";;
$ ./fizzbuzz 36 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, Fizz Buzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, Fizz Buzz, 31, 32, Fizz, 34, Buzz, Fizz
一応作れたんだけど、ダサいコードなので以下のページを参考にして改良。
let rec p x = match x with [] -> () | x :: [] -> print_string(x ^ "\n") | x :: xs -> begin print_string(x ^ ", "); p xs end let fizzbuzz n = let rec iter i ans = if i == 0 then ans else if i mod 15 == 0 then iter (i - 1) ("Fizz Buzz" :: ans) else if i mod 3 == 0 then iter (i - 1) ("Fizz" :: ans) else if i mod 5 == 0 then iter (i - 1) ("Buzz" :: ans) else iter (i - 1) ((string_of_int i) :: ans) in iter n [];; p (fizzbuzz (int_of_string Sys.argv.(1)));;
本当は、fizzbuzz関数を最後に評価して返り値を表示してくれれば良かったんだけど、何も出してくれなかったので表示関数を自作。たぶん車輪の再発明になってる。リストを表示する関数があったら教えてください。
それにしてもパターンマッチングはかっこいいな!