Life Goes On

まあまあだけど楽しんでる方です

47問目

http://projecteuler.net/index.php?section=problems&id=47
2つの素因数を持つ数が最初に2つ連続するのは14 = 2 × 7、15 = 3 × 5のときである。4つの素因数を持つ数が最初に4つ連続するとき、その最初の値を求める。
素因数分解を行うのですが、そのときn1/2以下の素数で割っていくことで高速化を図っています。
もともとはこのコメントを参考にしました。
他にも同じように悩んだ人がいたみたいです。

import Data.List

main = print $ euler047 4

euler047 :: Int -> Int
euler047 n = head $ head $ filter (all ((== n) . len) . take n) $ tails [1..]

len :: Int -> Int
len n = length $ nub $ factors primes n

factors :: [Int] -> Int -> [Int]
factors (p:ps) n
    | q < p = [n]
    | r == 0 = p : factors (p:ps) q 
    | otherwise = factors ps n
    where (q, r) = divMod n p

primes :: [Int]
primes = 2 : filter isPrime [3..]

isPrime :: Int -> Bool
isPrime x = all ((/= 0) . mod x) $ 
    takeWhile (<= (floor $ sqrt $ fromIntegral x)) primes