2009-09-12 6 views
2

Je possède ce programme complexe itérations je l'ai écrit dans TI de base pour effectuer une itération de base sur un nombre complexe et donnent l'ampleur du résultat:itérations complexes dans haskell

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 

Ce que je voudrais faire est faire une version Haskell de cela pour impressionner mon professeur dans une tâche. Je suis encore à apprendre seulement et obtenu jusqu'ici:

fractal ::(RealFloat a) => 
      (Complex a) -> (Integer a) -> [Complex a] 
fractal c n | n == a = z : fractal (z^2 + c) 
    | otherwise = error "Finished" 

Ce que je ne sais pas comment faire est de savoir comment faire que itérer n fois, donc je voulais avoir compter jusqu'à a puis comparer à n pour voir si elle avait fini.

Comment procéder?

Répondre

4

réponse de Newacct montre le chemin:

fractal c n = take n $ iterate (\z -> z^2 + c) c 

Iterate génère la liste infinie des applications répétées. Ex:

iterate (2*) 1 == [1, 2, 4, 8, 16, 32, ...] 

En ce qui concerne l'IO, vous devrez faire quelques calculs monades.

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) 

Depuis complexe est convertible à partir et à des chaînes par défaut, vous pouvez utiliser readLn pour les lire à partir de la console (format est Re :+ Im).

Edit: Juste pour le plaisir, on pourrait desugar la syntaxe monadiques et les signatures de type qui compriment l'ensemble programm à ceci:

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: Quelques liens liés à comploter et les ensembles de Mandelbrot.

+0

Merci, y a-t-il un moyen d'obtenir ceci dessiné sur un graphique avec des couleurs folles si les résultats apparaissent dans l'ensemble mandlebrot (quand magnitude <2)? –

+0

Edited mon post - Quelques liens très intéressants ;-) – Dario

+0

Je compile tout cela et le traceur de fractales et envoie à mon professeur un exécutable. –

3

Eh bien, vous pouvez toujours générer une liste infinie des résultats des applications répétées et prendre le premier n d'entre eux en utilisant take. Et la fonction iterate est utile pour générer une liste infinie de résultats d'applications répétées.

2

Si vous souhaitez une liste de valeurs:

fractalList c n = fractalListHelper c c n 
        where 
        fractalListHelper z c 0 = [] 
        fractalListHelper z c n = z : fractalListHelper (z^2 + c) c (n-1) 

Si vous ne vous préoccupez le dernier résultat:

fractal c n = fractalHelper c c n 
        where 
        fractalHelper z c 0 = z 
        fractalHelper z c n = fractalHelper (z^2 + c) c (n-1) 

En fait, dans les deux cas vous avez besoin d'une fonction d'assistance au comptage et l'accumulation. Maintenant, je suis sûr qu'il y a une façon meilleure/moins verbeuse de le faire, mais je suis à peu près un newbie Haskell moi-même.

Edit: juste pour le plaisir, un foldr un paquebot:

fractalFold c n = foldr (\c z -> z^2 + c) c (take n (repeat c)) 

(bien que, le (prendre n (répétition c)) chose sorte de superflu, il semble doit être une meilleure façon)

+0

je pense qu'il est préférable d'utiliser 'foldl'' au lieu de' 'foldr' comme fractalFold cn = foldl » (\ ZC -> z^2 + c) c (prenez n (répétez c)) '. Parce que 'foldr' est paresseux. Cela signifie qu'il crée des thunks comme la longueur de la liste donnée, mais le type de retour de 'fractalFold' n'a pas besoin d'être paresseux. – nonowarn