Probelm51
30分プログラム、その327。Problem51 - Project Euler。
ちょっと方針を変えて、適当な素数を1つ選んで、それを置き換えて素数かどうか確認する方法にしてみた。とりあえず、計算は進んでるみたいだけれども、まだ答えはでてない。
追記: 2時間ほどかけて、答えがでた。まあ、これでいいや。
使い方
$ time ./problem51 ..... 121313 [[1,2,1,3,1,3],[2,2,2,3,2,3],[3,2,3,3,3,3],[4,2,4,3,4,3],[5,2,5,3,5,3],[6,2,6,3,6,3],[8,2,8,3,8,3],[9,2,9,3,9,3]] ./problem51 9413.65s user 81.08s system 99% cpu 2:39:30.06 total
ソースコード
import Control.Monad.List import Data.Char import Data.List import Debug.Trace sieve (x:xs) = x:sieve [y | y <- xs, y `mod` x /= 0] primes = sieve [2..] isPrime n = n == (head $ dropWhile (< n) primes) splitInt :: Int -> [Int] splitInt n = unfoldr f n where f 0 = Nothing f n = Just (n `mod` 10,n `div` 10) uniqC :: Num a => [a] -> [(a,Int)] uniqC [] = [] uniqC [x] = [(x,1)] uniqC (x:xs) = let yss@((y,n):ys) = uniqC xs in if x == y then (y,n+1):ys else (x,1):yss replace :: [Int] -> Int -> Int -> [Bool] -> [Int] replace [] _ _ [] = [] replace [] _ _ _ = error "invalid mask" replace x _ _ [] = x replace (x:xs) old new mask@(y:ys)= case (x == old,y) of (True,True) -> new:(replace xs old new ys) (True,False) -> old:(replace xs old new ys) (_,_) -> x:(replace xs old new mask) perm [] = [[]] perm xs = nub $ do x <- xs ys <- perm $ delete x xs return (x:ys) primesN n = let min = 10^(n-1) max = 10^n in takeWhile (< max) $ dropWhile (<min) primes makeInt xs = foldl1 (\x y->10*x+y) xs replacedInt p = do let p' = reverse $ splitInt p (old,count) <- uniqC $ sort $ p' count' <- [1..count] mask <- perm $ take count $ (replicate count' True) ++ (cycle [False]) return $ filter check $ map (\new -> replace p' old new mask) [0..9] where check (0:_) = False check xs = isPrime $ makeInt xs solveN n = do p <- primes sameGroup <- replacedInt (trace (show p) p) guard $ length sameGroup == n return sameGroup answer = head $ solveN 8 main = print answer