3の倍数と3のつく数

昔、3の倍数と3のつく数を数えるとアホになる芸人さんがいたが、Haskell に数えさせるとどうなるだろう。

まずは、3の倍数。
Hugs> filter (\x -> mod x 3 == 0) [1..10]
[3,6,9]

これは簡単だった。次に3のつく数字だが、最初に数値を文字列に変える必要がある。
Hugs> map show [1..10]
["1","2","3","4","5","6","7","8","9","10"]

そのなかから、3のつく数字を取り出すが、List モジュールの elem という関数を使うのでモジュールをロードしておく。
Hugs> :l List
List> filter (\x -> elem '3' x) $ map show [1..10]
["3"]

得られたのは数字のリストなのでこれを数値に変える。
List> map (read :: String -> Int) $ filter (\x -> elem '3' x) $ map show [1..10]
[3]

倍数の出し方と3のつく数の作り方が分かったので、それを multiples と threes に束縛すると、求める関数は、 
getThree xs = union multiples threes

となる。List モジュールにはリストを集合のように扱って演算できる関数が用意されているが、先ほどの elem も union もその一つ。union は二つのリストの和集合を作成する。

以上の実験から3の倍数と3のつく数を計算するプログラム three.hs ができた。

import List

getThree xs = sort $ union multiples threes
  where
    multiples = filter (\x -> mod x 3 == 0) xs
    threes = map (read :: String -> Int) $ filter (\x -> elem '3' x) $ map show xs

実行例
Main> getThree [1..30]
[3,6,9,12,13,15,18,21,23,24,27,30]

実は、3の倍数と3のつく数をもとめるプログラムは以前のエントリーで紹介している。こちらの方は上の例よりもっとプログラムらしくみえる気がする。一方、上の例は自然言語で記述した問題を逐語的にプログラムに落とし込んだような感じになっている。その分動作のオーバーヘッドが多いかもしれないが、プロトタイプの作成や、思考実験には便利だ。どうすれば、Haskell を効率的に思考実験に使えるようにするか興味のあるところだ。


今日の Haskell
リストの集合演算。List モジュールに定義されている。
Hugs> :l List
List> nub [1,3,1,4,3,3] --重複要素を削除
[1,3,4]
List> delete 'a' "banana" -- リストに現れた 'a' にマッチする最初の要素を削除
"bnana"
List> [1,2,3,4] \\ [3,4,5,6] -- A - B
[1,2]
List> union [1,2,3,4] [3,4,5,6] -- A ∪ B
[1,2,3,4,5,6]
List> intersect [1,2,3,4] [3,4,5,6] -- A ∩ B
[3,4]
List> [x|x <- [1..10], x < 5] -- {x| x ∈ {1,2,..,10}, x < 5 }
[1,2,3,4]
List> elem 3 [1,2,3,4] -- 3 ∈{1,2,3,4}
True
[PR]
by tnomura9 | 2010-11-22 13:57 | Haskell | Comments(0)
<< 素因数分解 Haskell と数学パズル >>