ハンミング数に挑戦して失敗した
30分プログラム、その574。エロと風俗情報満載 どう抜く?にチャレンジしたけど、失敗した。
2^i * 3^j * 5^k の形で表される整数を小さい方から順に 100 個列挙するプログラムを書いてください。 i,
j, k は 0 以上の整数です。アルゴリズムのオーダーについても考えてみてください。例えば最初の 10 個は次のようになります:
1 = 2^0 * 3^0 * 5^0
2 = 2^1 * 3^0 * 5^0
3 = 2^0 * 3^1 * 5^0
4 = 2^2 * 3^0 * 5^0
5 = 2^0 * 3^0 * 5^1
6 = 2^1 * 3^1 * 5^0
8 = 2^3 * 3^0 * 5^0
9 = 2^0 * 3^2 * 5^0
10 = 2^1 * 3^0 * 5^1
12 = 2^2 * 3^1 * 5^0※解答では i, j, k の各値を示す必要はありません。
[2,4..]と[3,6..]と[5,10..]の3つの無限リストを作ってやって、そこから小さい順に選んでやればいいに違いない!と思ってやってみた。でも、それだと2^i*3^j*5^k*xみたいに余計な数字が入ってしまってうまくいかなかった。
ちなみに
hamming = [x| x <- [1..], (30^x) `mod` x == 0]
で計算できるらしいよ。
失敗したソースコード
import Data.List two :: [Int] three :: [Int] five :: [Int] two = 1:[2,4..] three = [x | x<- [3,6..] , x `mod` 2 /= 0 ] five = [x | x<- [5,10..], x `mod` 2 /= 0, x `mod` 3 /= 0 ] choice :: ([Int],[Int],[Int]) -> (Int,([Int],[Int],[Int])) choice (xss@(x:xs),yss@(y:ys),zss@(z:zs)) = let m = minimum [x,y,z] in if m == x then (x,(xs,yss,zss)) else if m == y then (y,(xss,ys,zss)) else (z,(xss,yss,zs)) hammings = unfoldr (Just . choice) (two,three,five) --- ans = take 100 [x| x <- [1..], mod (30^x) x == 0]