Permalink
Browse files

refactored 3 and 12 for speed and readability

  • Loading branch information...
1 parent 29a929a commit 08b6f9aa07b9e647382a72863bf0f3fef65ef506 Eric Wilson committed Jan 12, 2011
Showing with 46 additions and 51 deletions.
  1. +12 −20 003.hs
  2. +10 −6 012.hs
  3. +14 −15 EulerMath/Divisors.hs
  4. +1 −1 EulerMath/Fib.hs
  5. +9 −9 EulerMath/Primes.hs
View
32 003.hs
@@ -1,27 +1,19 @@
-{--
- There must be a better way.
- Sorry this is unreadable, and resorts to using Integer.
---}
+import EulerMath.Primes
+import EulerMath.Divisors
-isPrime :: Integer -> Bool
-isPrime = null . smallFactors
+firstPrimeFactor :: Integer -> Integer
+firstPrimeFactor n = head [ d | d <- primesUpTo n, mod n d == 0]
-smallFactors :: Integer -> [Integer]
-smallFactors n = takeWhile (\d -> d*d <= n) $ factors n
- where factors n = [ d | d <- [2..n-1], mod n d == 0]
-
-smallPrimeFactors :: Integer -> [Integer]
-smallPrimeFactors = filter isPrime . smallFactors
-
-reduceByList :: Integer -> [Integer] -> Integer
-reduceByList big [] = big
-reduceByList big (div:divs) = reduceByList (reduce big div) divs
+reduceByNextPrime :: Integer -> Integer
+reduceByNextPrime n = reduce n (firstPrimeFactor n)
where reduce num div =
if mod num div /= 0
then num
else reduce (quot num div) div
-
+
euler3 :: Integer -> Integer
-euler3 n = if reduceByList n (smallPrimeFactors n) == 1
- then last (smallPrimeFactors n)
- else reduceByList n (smallPrimeFactors n)
+euler3 n =
+ if reduced == 1
+ then n
+ else euler3' reduced
+ where reduced = reduceByNextPrime n
View
16 012.hs
@@ -9,14 +9,18 @@ triDivs n = if (even n)
then numDivs (quot n 2) * numDivs (n+1)
else numDivs n * numDivs (quot (n+1) 2)
-euler12 :: Int -> (Int, Int, Int)
-euler12 n = head $ filter (tripleAbove n) $ map triDivTriple [1..]
+numDivs :: Int -> Int
+numDivs n = product $ map (+1) $ primeFactorMultiplicity n
+
+primeFactorMultiplicity :: Int -> [Int]
+primeFactorMultiplicity = map snd . primeFactorizationFS primes1000
+ where primes1000 = primesUpTo 1000
+
+euler12 :: Int -> Int
+euler12 n = (\ (_, t, _) -> t) . head $ filter (tripleAbove n) $ map triDivTriple [1..]
where
triDivTriple m = (m, tri m, triDivs m)
tripleAbove n (_, _, m) = (m > n)
-primeFactorsWithMult :: Int -> [Int]
-primeFactorsWithMult = map snd . primeFactorization
-numDivs :: Int -> Int
-numDivs n = product $ map (+1) $ primeFactorsWithMult n
+
View
@@ -1,33 +1,32 @@
module EulerMath.Divisors
( divisors
, primeFactorization
+, primeFactorizationFS
+, primeFactors
) where
import EulerMath.Primes
-{--
-This is good for primes under 1000 currently.
-A more general primeFactorization, both fast and
-sufficient for larger numbers would be nice.
---}
-
-divisors :: Integer -> [Integer]
+divisors :: (Integral a) => a -> [a]
divisors n = [ d | d <- [1..n], mod n d == 0 ]
-primes1000 :: [Int]
-primes1000 = primesUpTo 1000
+primeFactors :: (Integral a) => a -> [a]
+primeFactors n = [ d | d <- primesUpTo n, mod n d == 0 ]
+
+primeFactorsFS :: (Integral a) => [a] -> a -> [a]
+primeFactorsFS smallPrimes n = [ d | d <- smallPrimes, mod n d == 0 ]
--- replacing primes1000 with primesUpTo n kills performance.
-primeFactors :: Int -> [Int]
-primeFactors n = [ d | d <- primes1000, mod n d == 0 ]
-timesDivides :: Int -> Int -> Int
+timesDivides :: (Integral a) => a -> a -> a
timesDivides d n = timesDividesIt d n 0
where
timesDividesIt d n i =
if (mod n d /= 0)
then i
else timesDividesIt d (quot n d) (i+1)
-primeFactorization :: Int -> [(Int, Int)]
-primeFactorization n = map (\p -> (p, timesDivides p n)) $ primeFactors n
+primeFactorization :: (Integral a) => a -> [(a, a)]
+primeFactorization n = map (\p -> (p, timesDivides p n)) $ primeFactors n
+
+primeFactorizationFS :: (Integral a) => [a] -> a -> [(a, a)]
+primeFactorizationFS smallPrimes n = map (\p -> (p, timesDivides p n)) $ primeFactorsFS smallPrimes n
View
@@ -2,7 +2,7 @@ module EulerMath.Fib
( fib
) where
-fib :: Int -> Int
+fib :: (Integral a) => a -> a
fib n = fst $ fibPair n
where
fibPair 1 = (1,1)
View
@@ -1,32 +1,32 @@
module EulerMath.Primes
( nPrimes
, primesUpTo
-, primesBelowRoot
+, primesUpToRoot
, isPrime
) where
-divides :: Int -> Int -> Bool
+divides :: (Integral a) => a -> a -> Bool
divides d n = mod n d == 0
-sieve :: [Int] -> [Int] -> [Int]
+sieve :: (Integral a) => [a] -> [a] -> [a]
sieve [] ys = ys
sieve (x:xs) ys = x : sieve xs (filter (not . divides x) ys)
-genPrimes :: Int -> [Int]
+genPrimes :: (Integral a) => a -> [a]
genPrimes n = iterSieve [2,3] n
where
iterSieve xs 0 = xs
iterSieve xs n = iterSieve (sieveRange xs (last xs) ((last xs)^2)) (n-1)
sieveRange xs n m = sieve xs [n..m]
-nPrimes :: Int -> [Int]
+nPrimes :: (Integral a) => Int -> [a]
nPrimes n = take n $ genPrimes 4
-primesUpTo :: Int -> [Int]
+primesUpTo :: (Integral a) => a -> [a]
primesUpTo n = takeWhile (<=n) $ genPrimes 4
-primesBelowRoot :: Int -> [Int]
-primesBelowRoot n = takeWhile (\d -> d^2 <= n) $ genPrimes 4
+primesUpToRoot :: (Integral a) => a -> [a]
+primesUpToRoot n = takeWhile (\d -> d^2 <= n) $ genPrimes 4
-isPrime :: Int -> Bool
+isPrime :: (Integral a) => a -> Bool
isPrime n = any (==n) $ primesUpTo (n+1)

0 comments on commit 08b6f9a

Please sign in to comment.