1
0
Fork 0

Euler Question 10 - Whole lotta primes

main
Bill Ewanick 2023-09-14 23:46:15 -04:00
parent 1b689521c1
commit 83ff425eb4
2 changed files with 125 additions and 0 deletions

View File

@ -46,6 +46,10 @@
random
neat-interpolation
# maths
primes
arithmoi
# graphing libraries!
Chart
Chart-cairo

View File

@ -0,0 +1,121 @@
{-
Summation of Primes
Problem 10
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
https://wiki.haskell.org/Prime_numbers
Compile with `ghc -O3 src/projectEuler/question10.hs`
Run with `time src/projectEuler/question10`
-}
{-# OPTIONS_GHC -O2 #-}
import Control.Monad (forM_, when)
import Data.Array.Base (IArray (unsafeAt),
MArray (unsafeWrite),
UArray (UArray),
unsafeFreezeSTUArray)
import Data.Array.ST (MArray (newArray), readArray,
runSTUArray, writeArray)
import Data.Array.Unboxed (UArray, assocs)
import Data.Bits (Bits (shiftL, shiftR))
import Data.Int (Int64)
import Data.List (genericIndex, genericTake)
import Data.Word (Word64)
-- https://hackage.haskell.org/package/arithmoi-0.13.0.0
import Math.NumberTheory.Primes (Prime (unPrime), primes)
main :: IO ()
main = do
print "Hello! Welcome to the prime number generator."
-- print "Please enter which nth prime you'd like: "
-- n <- getLine
-- let n' = read n :: Integer
-- print $ "Finding the " ++ n ++ "th prime."
-- print $ primes() `genericIndex` (10^ (10 :: Int))
print $ last $ take (10^ (10 :: Int)) primes
ans :: Integer
ans = sum $ takeWhile (< 2_000_000) $ map unPrime primes
primes1 :: [Integer]
primes1 = sieve [2..]
where
sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0]
primes2 :: [Integer]
primes2 = 2:([3..] `minus` composites)
where
composites = union [multiples p | p <- primes2]
multiples n = map (n*) [n..]
(x:xs) `minus` (y:ys) | x < y = x:(xs `minus` (y:ys))
| x == y = xs `minus` ys
| x > y = (x:xs) `minus` ys
union = foldr merge [ ]
where
merge (x:xs) ys = x:merge' xs ys
merge' (x:xs) (y:ys) | x < y = x:merge' xs (y:ys)
| x == y = x:merge' xs ys
| x > y = y:merge' (x:xs) ys
{-
https://wiki.haskell.org/Prime_numbers
Using Page-Segmented ST-Mutable Unboxed Array
-}
-- type Prime = Word64
-- cSieveBufferLimit :: Int
-- cSieveBufferLimit = 2^17 * 8 - 1 -- CPU L2 cache in bits
-- primes :: () -> [Prime]
-- primes() = 2 : _Y (listPagePrms . pagesFrom 0) where
-- _Y g = g (_Y g) -- non-sharing multi-stage fixpoint combinator
-- listPagePrms pgs@(hdpg@(UArray lwi _ rng _) : tlpgs) =
-- let loop i | i >= fromIntegral rng = listPagePrms tlpgs
-- | unsafeAt hdpg i = loop (i + 1)
-- | otherwise = let ii = lwi + fromIntegral i in
-- case fromIntegral $ 3 + ii + ii of
-- p -> p `seq` p : loop (i + 1) in loop 0
-- makePg lwi bps = runSTUArray $ do
-- let limi = lwi + fromIntegral cSieveBufferLimit
-- bplmt = floor $ sqrt $ fromIntegral $ limi + limi + 3
-- strta bp = let si = fromIntegral $ (bp * bp - 3) `shiftR` 1
-- in if si >= lwi then fromIntegral $ si - lwi else
-- let r = fromIntegral (lwi - si) `mod` bp
-- in if r == 0 then 0 else fromIntegral $ bp - r
-- cmpsts <- newArray (lwi, limi) False
-- fcmpsts <- unsafeFreezeSTUArray cmpsts
-- let cbps = if lwi == 0 then listPagePrms [fcmpsts] else bps
-- forM_ (takeWhile (<= bplmt) cbps) $ \ bp ->
-- forM_ (let sp = fromIntegral $ strta bp
-- in [ sp, sp + fromIntegral bp .. cSieveBufferLimit ]) $ \c ->
-- unsafeWrite cmpsts c True
-- return cmpsts
-- pagesFrom lwi bps = map (`makePg` bps)
-- [ lwi, lwi + fromIntegral cSieveBufferLimit + 1 .. ]
-- sieveUA :: Int -> UArray Int Bool
-- sieveUA top = runSTUArray $ do
-- let m = (top-1) `div` 2
-- r = floor . sqrt $ fromIntegral top + 1
-- sieve <- newArray (1,m) True -- :: ST s (STUArray s Int Bool)
-- forM_ [1..r `div` 2] $ \i -> do
-- isPrime <- readArray sieve i
-- when isPrime $ do -- ((2*i+1)^2-1)`div`2 == 2*i*(i+1)
-- forM_ [2*i*(i+1), 2*i*(i+2)+1..m] $ \j -> do
-- writeArray sieve j False
-- return sieve
-- primesToUA :: Int -> [Int]
-- primesToUA top = 2 : [i*2+1 | (i,True) <- assocs $ sieveUA top]