Question

J'ai ce programme d'itérations complexes que j'ai écrit dans TI Basic pour effectuer une itération de base sur un nombre complexe, puis donner l'ampleur du résultat:

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, c’est d’en faire une version Haskell pour épater mon enseignant dans une tâche. Je suis encore en train d'apprendre et je suis si loin:

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 faire, c'est comment faire en sorte qu'il ne fasse qu'itérer n fois. Je voulais donc qu'il compte a et le compare ensuite à n pour voir s'il est terminé.

Comment pourrais-je m'y prendre?

Était-ce utile?

La solution

La réponse de Newacct montre la voie:

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

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

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

En ce qui concerne l'IO, vous devrez faire des calculs monadiques.

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)

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

Éditer: Juste pour le plaisir, on pourrait désagarer la syntaxe monadique et taper des signatures qui compresseraient tout le programme à 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)

Éditer # 2: Quelques liens liés au tracé et aux sets de Mandelbrot.

Autres conseils

Vous pouvez toujours générer une liste infinie de résultats d'applications répétées et en prendre le premier n à l'aide de prendre . Et la fonction iterate est utile pour générer une liste infinie de résultats d'applications répétées.

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 souciez que du 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)

Dans les deux cas, vous avez besoin d’une fonction d’aide pour le comptage et l’accumulation. Maintenant, je suis sûr qu'il existe un moyen meilleur / moins verbeux de faire cela, mais je suis moi-même un novice Haskell.

Edit: juste pour le plaisir, un fold-one-liner:

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

(bien que la chose (prendre n (répéter c)) semble un peu inutile, il doit y avoir un moyen encore meilleur)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top