Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

damn, problem 60 is hard... making progress though

  • Loading branch information...
commit f8b6145c90dbdaa1e5dd7477ddb1da0623a614af 1 parent f694a4f
@eklitzke authored
Showing with 81 additions and 27 deletions.
  1. +4 −0 .gitignore
  2. +68 −25 60/EulerProblem.hs
  3. +9 −2 polyomino/Primes.hs
View
4 .gitignore
@@ -0,0 +1,4 @@
+*.hi
+*.o
+*.prof
+EulerProblem
View
93 60/EulerProblem.hs
@@ -1,34 +1,77 @@
-import Primes (isTrialDivisionPrime)
+import Prelude hiding (lookup)
+import Primes (isTrialDivisionPrime, primesTo100, trialDivision)
+import Data.Set (fromDistinctAscList, Set, member, size, fromList)
-primes :: [Int]
-primes = sieve [2..]
- where sieve (p:ns) = p : sieve (filter (notdiv p) ns)
- notdiv p n = n `mod` p /= 0
+import Data.HashTable
+import Control.Monad
-concatInts :: Int -> Int -> Int
-concatInts x y = read (show x ++ show y)
+import Data.Bits
-concatPairs :: [Int] -> [Int]
-concatPairs [x] = []
-concatPairs (x:xs) = [concatInts x y | y <- xs] ++ [concatInts y x | y <- xs] ++ (concatPairs xs)
+import Data.Int
-hasProp :: [Int] -> Bool
-hasProp = (all isTrialDivisionPrime) . concatPairs
+import System.IO.Unsafe
-smallSums :: Int -> Int -> [[Int]]
-smallSums n t = filter (/= []) (ss n t primes)
+type PrimePairHash = HashTable (Int, Int) Bool
+
+primeList :: [Int]
+primeList = primesTo100 ++ filter (trialDivision primesTo100) [101,103..]
+
+myPrimeTest = isTrialDivisionPrime
+
+-- Checks the property that writing the concatenated number ab is prime, also
+-- ba is prime.
+hasProp :: Int -> Int -> Bool
+hasProp a b = (myPrimeTest (read $ sa ++ sb)) && (myPrimeTest (read $ sb ++ sa))
+ where (sa, sb) = (show a, show b)
+
+-- Check if a pair of primes have the concatenation property we are
+-- looking for (namely, hasProp). The function is memoized with a
+-- PrimePairHash. The caller should make sure a, b are ordered.
+checkHt :: PrimePairHash -> Int -> Int -> IO Bool
+checkHt ht a b = do
+ t <- lookup ht (a, b)
+ case t of
+ Just x -> return x
+ Nothing -> do let x = hasProp a b
+ insert ht (a, b) x
+ return x
+
+-- Like all from the Prelude, shortcuts on the first False encountered
+allM :: (a -> IO Bool) -> [a] -> IO Bool
+allM _ [] = return True
+allM f (x:xs) = do v <- f x
+ case v of
+ True -> allM f xs
+ False -> return False
+
+-- remember can just do odds or evens based on n, handle 2 separately
+smallSums :: PrimePairHash -> Int -> Int -> IO [Int]
+smallSums _ _ 2010 = return []
+smallSums ht n t = do
+ print t
+ rslt <- ss n t primeList
+ case rslt of
+ [] -> smallSums ht n (t + 1)
+ (x:xs) -> return x
where
ss 1 targ (x:xs)
| x < targ = ss 1 targ xs
- | x == targ = [[x]]
- | otherwise = [[]]
+ | x == targ = return [[x]]
+ | otherwise = return []
ss n targ (x:xs)
- | x > targ = [[]]
- | otherwise = (myMap (x:) (ss n' t' xs)) ++ (ss n targ xs)
- where
- t' = targ - x
- n' = n - 1
- myMap f ls = map f [y | y <- ls, length y == n']
-
-main = print $ sum $ head $ filter hasProp $ concatMap (smallSums 5) [2..]
---main = print $ [(x, y) | x <- [2..100], let y = smallSums 3 x, y /= []]
+ | x >= targ = return []
+ | otherwise = foo
+ where foo = {-# SCC "memoized_check" #-}
+ do t2 <- ss n targ xs
+ withX <- ss (n - 1) (targ - x) xs
+ f <- filterM (allM $ checkHt ht x) withX
+ let t1 = map (x:) f
+ return $ t1 ++ t2
+
+-- hmm, another hash function might be \(a, b) -> (hashInt a) `xor` (hashInt b)
+mkHash :: IO PrimePairHash
+mkHash = new (==) (hashInt . (uncurry xor))
+
+main = do ht <- mkHash
+ ss <- smallSums ht 5 2000
+ print ss
View
11 polyomino/Primes.hs
@@ -2,8 +2,9 @@
module Primes (primesTo100, primesTo10000, isPrime, nextPrime,
primePowerFactors, -- primeFactors,
- fromPrimePowerFactors, isMillerRabinPrime, isTrialDivisionPrime,
- isSquareFree, isPrimePower, primes) where
+ trialDivision,
+ fromPrimePowerFactors, isMillerRabinPrime, isTrialDivisionPrime,
+ isMillerRabinPrime', isSquareFree, isPrimePower, primes) where
import NumberTheoryFundamentals (divides, splitWith, power)
@@ -75,6 +76,12 @@ isMillerRabinPrime n
| otherwise = all (isStrongPseudoPrime n (s,t)) primesTo100
where (s,t) = (n-1) `splitWith` 2 -- so n-1 == 2^s * t
+isMillerRabinPrime' :: [Int] -> Int -> Bool
+isMillerRabinPrime' plist n
+ | n < 100 = n `elem` primesTo100
+ | otherwise = all (isStrongPseudoPrime n (s,t)) plist
+ where (s,t) = (n-1) `splitWith` 2 -- so n-1 == 2^s * t
+
-- to test the algorithm, following set should be empty (replace numbers as required)
-- [n | n<-[100000..101000], isTrialDivisionPrime n /= isMillerRabinPrime n]
Please sign in to comment.
Something went wrong with that request. Please try again.