My Weblog

Blog about programming and math

Sieve of eratosthenes using Haskell IOArray

More about Haskell array . This one is simple Haskell code for Sieve of eratosthenes and Euler’s totient function . This is first time i played with mutable array. Also posted this code on ideone.

import Data.Array
import Data.Array.IO
--start of prime

loopB :: Int -> Int -> Int ->  IOArray Int Int -> IO ( IOArray Int Int )
loopB st a b arr
        | st > b = return arr
	| otherwise = 
	    do
		writeArray arr st 0 
		loopB ( st + a ) a b arr 


loopA :: Int -> Int ->  IOArray Int Int -> IO ( IOArray Int Int ) 
loopA a b arr 
	| a ^ 2 > b = return arr
	| otherwise = 
	   do
		t <- readArray arr a 
		arr' <- if t /= 0 then loopB ( a ^ 2 ) a  b arr else return arr 
		loopA ( a + 1 ) b arr' 

printerA :: Int -> Int -> IOArray Int Int -> IO ( )
printerA a b arr 
	| a > b = return ()
	| otherwise = do 
		t <- readArray arr a 
		print ( a , if t == 0 then "composite" else "prime" ) 
		printerA ( a + 1 ) b arr 

--end of prime generation
--start of euler phi function

helpEuler :: Int -> Int -> IOArray Int Int -> IO ( IOArray Int Int ) 
helpEuler a b phi 
	| a > b = return phi
	| otherwise = 
	   do 
		writeArray phi a a 
		helpEuler ( a + 1 ) b phi

loopInner :: Int -> Int -> Int -> IOArray Int Int -> IO ( IOArray Int Int ) 
loopInner st a b phi 
	| st > b = return phi
	| otherwise = 
	   do 
		t <- readArray phi st 
		let k = div ( t * ( a - 1 ) ) a 
		writeArray phi st k 
		loopInner ( st + a ) a b phi

loopOuter :: Int -> Int -> IOArray Int Int -> IO ( IOArray Int Int ) 
loopOuter a b phi
	| a > b = return phi
	| otherwise = 
	   do 
	     t <- readArray phi a 
	     phi' <- if t == a then loopInner (  2 * a ) a b phi else return phi
	     loopOuter ( a + 1 ) b phi' 
 
modifyValue :: Int -> Int -> IOArray Int Int -> IO ( IOArray Int Int ) 
modifyValue a b phi 
	| a > b = return phi
	| otherwise = 
	   do 
	      t <- readArray phi a 
	      if t == a then writeArray phi a ( a - 1 ) else writeArray phi a t 
	      modifyValue ( succ a ) b phi 


printerB :: Int -> Int -> IOArray Int Int -> IO (  )
printerB a b phi
       | a > b = return ()
       | otherwise = 
	   do 
		t <- readArray phi a 
		print ( a , t ) 
		printerB ( a + 1 ) b phi

--end of euler phi function


main = do
	{-- 
	arr <- newArray ( 2 , 1000 ) 1 :: IO ( IOArray Int Int ) 
	arr' <- loopA  2 1000 arr
	printerA 2 1000 arr'
	--}
	
	phi <- newArray ( 1 , 100 ) 1 :: IO ( IOArray Int Int ) 
	tmp <- helpEuler  2 100 phi
	phi' <- loopOuter 2 100 tmp	
	phi'' <- modifyValue 2 100 phi'
	printerB 1 100 phi''
	
	{--
	a <- readArray arr 1
	writeArray arr 1 64 
	b <- readArray arr 1
	print ( a , b ) 
	--}

Couple of more compact code to compute prime , totient , divisor sum and mobius of number.

import Control.Monad.ST
import Data.Array.ST
import Data.Array.Unboxed
import Control.Monad

prime :: Int -> UArray Int Int 
prime n = runSTUArray $ do 
	arr <- newArray ( 2 , n ) 1 :: ST s ( STUArray s Int Int ) 
	forM_ ( takeWhile ( \x -> x*x <= n ) [ 2 .. n ] ) $ \i -> do 
		ai <- readArray arr i 
		when ( ai == 1 ) $ forM_ [ i^2 , i^2 + i .. n ] $ \j -> do 
			writeArray arr j 0 

	return arr 

totient :: Int -> UArray Int Int 
totient n = runSTUArray $ do 
	arr <- newListArray ( 1 , n ) [ 0 .. pred n ] :: ST s (STUArray s Int Int ) 
	forM_ [ 2 .. n ] $ \i -> do 
		ai <- readArray arr i
		when ( ai == pred i ) $ forM_ [ 2*i , 3*i .. n ] $ \j -> do 
			aj <- readArray arr j 
			writeArray arr j ( aj - div aj i )
	writeArray arr 1 1  
	return arr

divisorSum :: Int -> UArray Int Int
divisorSum n = runSTUArray $ do
	arr <- newArray ( 1 , n ) 0 :: ST s ( STUArray s Int Int ) 
	forM_ [ 1 .. n ] $ \i-> do 
	  forM_ [ i , 2 * i .. n ] $ \j -> do
		aj <- readArray arr j 
		writeArray arr j ( aj + i ) 
	return arr


mobius :: Int -> UArray Int Int 
mobius n = runSTUArray $ do
	arr <- newArray ( 1 , n ) 0 :: ST s ( STUArray s Int Int ) 
	writeArray arr 1 1
	forM_ [ 1 .. n ] $ \i -> do
	  forM_ [ 2*i , 3*i .. n ] $ \j -> do
	    ai <- readArray arr i
	    aj <- readArray arr j
	    writeArray arr j ( aj - ai )
	return arr 	 


main = do
	
	print $ ( prime 100 ) ! 37
	print $ ( totient 100  ) ! 50
	print $ ( divisorSum 100 ) ! 50
	print $ ( mobius 100 ) ! 50
Advertisements

September 9, 2011 - Posted by | Programming | , , ,

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: