Project Euler 50,51

Problem 50

http://projecteuler.net/index.php?section=problems&id=50


2から始まる系列、3から始まる系列、をリストにして、長いものから調べていく。遅い。

import Data.Array

sieve a p | a!p == True = sieve (a // [ (m, False) | m <- b, a!m ]) (p + 1)
          | p * p > n = a
          | otherwise  = sieve a (p + 1)
                where b = if p == 2 then [p*2,p*3..n] else [p*3,p*5..n]

n = 10^6
is_prime = sieve (array (2, n) [ (k, True) | k <- [2..n] ]) 2
primes = filter (is_prime!) [2..n]

que :: [Int] -> [Int]
que (p:ps) = p:[ q + r | (q, r) <- zip ps (que (p:ps)) ]
queue ps = reverse (takeWhile (\(_,m) -> (m < n)) (zip [1..] (que ps)))
queues (p:ps) = (queue (p:ps)):(queues ps)
a = queues primes
max_n = fst (head (head a))

h [] n = (0, 0)
h (p:ps) n | fst p == n = p
           | fst p > n  = h ps n
           | otherwise  = (-1, -1)
g (x:xs) n | fst m == n = m:(g xs n)
           | otherwise  = []
        where m = h x n
f :: Int -> [[(Int,Int)]]
f n = (g a n):(f (n - 1))

main = print(head (filter (\a -> length a > 0)
        (map (filter (\p -> is_prime!(snd p))) (f max_n))))

Problem 51

http://projecteuler.net/index.php?section=problems&id=51


0,1,2のどれかが3個以上の数について調べる。ややこしい。

is_prime n = all (\p -> mod n p /= 0) (takeWhile (\p -> p * p <= n) primes)
primes = 2:(filter is_prime [3..])

digits 0 = []
digits n = (digits (div n 10)) ++ [mod n 10]
numerize a = foldl (\x y -> x * 10 + y) 0 a

count [] e = 0
count (p:ps) e = if p == e then 1 + n else n where n = (count ps e)

base :: Int -> [(Int,Int)]
base n = f n 0 where
    a = digits n
    f n 3 = []
    f n d = (if count a d >= 3 then g a d else []) ++ (f n (d + 1)) where
            h [] d = [[]]
            h (p:ps) d = [ [a] ++ b |
                a <- (if p == d then [0,1] else [0]), b <- (h ps d) ]
            g a d = map (\n-> (d, n)) (filter (\n -> mod n 10 == 0)
                (map numerize (filter (\b -> div3 (count b 1)) (h a d))))
                        where div3 n = n > 0 && mod n 3 == 0

is_valid (n,(d,b)) = length (filter is_prime [n,n+b..n+b*(9-d)]) == 8
a = filter is_valid (concat (map (\n -> map (\b -> (n, b)) (base n)) [1..]))
main = print(fst (head a))