200 Find the 200th prime-proof sqube containing the contiguous sub-string “200”

Problem 200 – Project Euler

2、5が含まれていれば、prime-proofだということはすぐに分かる。

つまり、prime-proofの十分条件。気になるのは必要条件だが…

ちょっと調べてみると(狭い範囲では)、2、5以外にprime-proofはでてこない。

ということで、必要十分条件なんだろうと勝手に仮定して解いた。

import Number (primes,isPrime')
import Data.List (isInfixOf)
sqube25 :: [Integer]
sqube25 = foldl1 merge.zipWith map [s 2,s 5,`s` 2,`s` 5] .repeat.drop 3 $ primes
where s p q = p^2*q^3
merge :: Ord a => [a] -> [a] -> [a]
merge xs@(x:xt) ys@(y:yt) = case compare x y of
LT -> x : merge xt ys
EQ -> x : merge xt yt
GT -> y : merge xs yt
primeProof :: Integer -> Bool
primeProof x = all (not.isPrime'.read) [change i d (show x) | i <- [1..length.show $ x], d <- ['0'..'9']]
where change i d xs = let (a,b) = splitAt i xs
in init a ++ d:b
p200 :: Int -> Integer
p200 (n+2) = (!!n).filter primeProof.filter contain200 $ sqube25
where contain200 = isInfixOf "200".show
main :: IO ()
main = print $ p200 200

とりあえず、答は正しいらしい。

追記

仮定は間違いだった。

105200812888979987 = 2011^2 * 2963^3

これが反例。

まぁ、ラッキーだった、ということで。

追記

ちゃんと、探すほうのコード。

import Number (primes, isPrime')
import Data.List (sort, delete, isInfixOf)
squbes :: Integer -> [Integer]
squbes u = do let u_q = floor.(**(1/3)).fromIntegral.div u $ 4
q <- takeWhile (< u_q) primes
let u_p = floor.sqrt.fromIntegral.div u $ q^3
p <- takeWhile (< u_p).delete q $ primes
return $ p*p*q*q*q
primeProof :: Integer -> Bool
primeProof x = all (not.isPrime'.read) [change i d (show x) | i <- [1..length.show $ x], d <- ['0'..'9']]
where change i d xs = let (a,b) = splitAt i xs
in init a ++ d:b
p200 :: Int -> Int -> Integer
p200 (m+2) n = (!!m).sort.filter primeProof.filter contain200 $ squbes (10^n)
where contain200 = isInfixOf "200".show
main :: IO ()
main = print $ p200 200 12