Life Goes On

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

49問目

http://projecteuler.net/index.php?section=problems&id=49
1487, 4817, 8147のように、(i)どれも素数で、(ii)それぞれの数が他の数の並べ替えとなっている、4桁の等差数列を見つけ、それを繋げた12桁の数を求める。
手順は↓の通り。間違ってはいませんが、もう少し端折ってもよかったみたいです。(各グループで3つの数の組合せを律儀に求めず、小さい順に並べて等差数列になるものを抽出しても、答えは求まる)

  1. まず4桁の素数を抽出
  2. 構成する数字でグループ化
  3. 各グループで3つの数の組合せを全て求め
  4. 等差数列となる組合せを抽出
import Data.List
import Data.Ord

main = print $ euler049

euler049 :: [String]
euler049 = map concat $ filter arithmetic $ concatMap (comb 3) $
    groupBy (\ a b -> sort a == sort b) $ sortBy (comparing sort) $
    map show $ takeWhile (< 10000) $ dropWhile (< 1000) primes

arithmetic :: [String] -> Bool
arithmetic [] = False
arithmetic [a, b, c] = read c - read b == read b - read a

comb :: Eq a => Int -> [a] -> [[a]]
comb n s
    | (n > length s) = [[]]
    | (n == 0) = [[]]
    | otherwise = [x : xs |
        x <- take ((length s) - n + 1) s,
        xs <- comb (n - 1) (tail $ dropWhile (/= x) s)]

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

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