Problem51 - Project Euler
30分プログラム、その326。Problem51 - Project Euler。
*57の第1桁を置き換えることで, 157, 257, 457, 557, 757, 857という6つの素数が得られる.
56**3の第3桁と第4桁を同じ数で置き換ることを考えよう. この5桁の数は7つの素数をもつ最初の例である: 56003, 56113, 56333, 56443, 56663, 56773, 56993. よって, この族の最初の数である56003は, このような性質を持つ最小の素数である.
桁を同じ数で置き換えることで8つの素数が得られる最小の素数を求めよ. (注:連続した桁でなくても良い)
例えば、*57を置き換えたやつは、全部差が100nになることを用いて計算しようとした。でも、繰り下りがあることを忘れていた。続きはまた明日。
使い方
# 3桁で、6つの素数が得られるやつの取得 Main> solveN 3 6
ソースコード
import Control.Monad.List import Data.List sieve (x:xs) = x:sieve [y | y <- xs, y `mod` x /= 0] primes = sieve [2..] splitInt :: Int -> [Int] splitInt n = map (\x-> read [x]) $ show n isTimes x y = x < y*10 && x `mod` y == 0 solve3 = do p <- primes3 let first = filter (\n -> isTimes (n - p) 100) primes3 let second = filter (\n -> isTimes (n - p) 10) primes3 let third = filter (\n -> isTimes (n - p) 1) primes3 guard $ (length first) == 6 || (length second) == 6 || (length third) == 6 return p where primes3 = takeWhile (< 1000) $ dropWhile (<100) primes 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->x*10+y) xs solveN n m = do p <- primes' repCount <- [1..n-1] mask <- map makeInt $ perm $ take n $ (replicate repCount 1)++[0,0..] let xs = filter (\n -> isTimes (n - p) mask) primes' guard $ length xs == m return (p,mask,xs) where primes' = primesN n answer = head $ concatMap (\n -> solveN n 8) [2..] main = print answer