Complex iteration in haskell
I have this complex iteration program I wrote in TI Basic to do basic iteration on a complex number and then give the magnitude of the result:
INPUT "SEED?", C
INPUT "ITERATIONS?", N
CāZ
For (I,1,N)
Z^2 + C ā Z
DISP Z
DISP "MAGNITUDE", sqrt ((real(Z)^2 + imag(Z)^2))
PAUSE
END
What I would like to do is make a version of Haskell in order to fire my teacher on the assignment. I am still just learning and got to this:
fractal ::(RealFloat a) =>
(Complex a) -> (Integer a) -> [Complex a]
fractal c n | n == a = z : fractal (z^2 + c)
| otherwise = error "Finished"
What I dont know how to do is to do it only repetition n
times, so I wanted it to count a
and then compare it with n
to see if it ended.
How can i do this?
source to share
Newacct's answer shows a way:
fractal c n = take n $ iterate (\z -> z^2 + c) c
Iterate
generates an endless list of duplicate applications. Example:
iterate (2*) 1 == [1, 2, 4, 8, 16, 32, ...]
As far as IO goes, you will need to do some monadic computation.
import Data.Complex
import Control.Monad
fractal c n = take n $ iterate (\z -> z^2 + c) c
main :: IO ()
main = do
-- Print and read (you could even omit the type signatures here)
putStr "Seed: "
c <- readLn :: IO (Complex Double)
putStr "Number of iterations: "
n <- readLn :: IO Int
-- Working with each element the result list
forM_ (fractal c n) $ \current -> do
putStrLn $ show current
putStrLn $ "Magnitude: " ++ (show $ magnitude current)
Since Complex is converted to and from strings by default, you can use readLn
(format Re :+ Im
) to read them from the console .
Editing: just for fun, we can drop the monadic syntax and tick signatures that would compress the entire program before:
main =
(putStr "Seed: ") >> readLn >>= \c ->
(putStr "Number of iterations: ") >> readLn >>= \n ->
forM_ (take n $ iterate (\z -> z^2 + c) c) $ \current ->
putStrLn $ show current ++ "\nMagnitude: " ++ (show $ magnitude current)
Edit # 2: Some links related to construction and Mandelbrot sets.
source to share
If you want a list of values:
fractalList c n = fractalListHelper c c n
where
fractalListHelper z c 0 = []
fractalListHelper z c n = z : fractalListHelper (z^2 + c) c (n-1)
If you only care about the last result:
fractal c n = fractalHelper c c n
where
fractalHelper z c 0 = z
fractalHelper z c n = fractalHelper (z^2 + c) c (n-1)
Basically, in both cases, you need a helper function to count and accumulate. Now I'm sure there is a better / less surefire way to do this, but I'm pretty much a Haskell newbie.
Edit: for kicks only, one-line warehouse:
fractalFold c n = foldr (\c z -> z^2 + c) c (take n (repeat c))
(although, (take n (repeat c)) thing seems unnecessary, there must be an even better way)
source to share