Pergunta

Eu tenho esse complexo programa de iterações que escrevi no TI Basic para realizar uma iteração básica em um número complexo e depois dar a magnitude do resultado:

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

O que eu gostaria de fazer é fazer uma versão Haskell disso para impressionar meu professor em uma tarefa. Ainda estou apenas aprendendo e cheguei até aqui:

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

O que eu não sei como fazer é como fazê -lo apenas iterado n vezes, então eu queria ter isso contando a e então compare com n Para ver se havia terminado.

Como eu iria fazer isso?

Foi útil?

Solução

A resposta de NewAcct mostra o caminho:

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

Iterate Gera a lista infinita de aplicativos repetidos. Ex:

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

Em relação à IO, você terá que fazer alguns cálculos monádicos.

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)

Como o complexo é conversível de e para strings por padrão, você pode usar readLn para lê -los no console (o formato é Re :+ Im).

EDIT: Apenas por diversão, alguém poderia desugar a sintaxe monádica e as assinaturas de tipo que comprimiriam todo o programa para isso:

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: Alguns links relacionados à plotagem e conjuntos de Mandelbrot.

Outras dicas

Bem, você sempre pode gerar uma lista infinita de resultados de aplicativos repetidos e tomar o primeiro n deles usando take. E a iterate A função é útil para gerar uma lista infinita de resultados de aplicativos repetidos.

Se você quiser uma lista de valores:

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

Se você se preocupa apenas com o último resultado:

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

Basicamente, em ambos os casos, você precisa de uma função auxiliar para a contagem e acumulação. Agora tenho certeza de que há uma maneira melhor/menos detalhada de fazer isso, mas eu sou um novato em Haskell.

Edit: Just for Kicks, uma liner-liner:

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

(Embora a coisa (Take n (repetir c)) pareça meio desnecessária, deve haver uma maneira ainda melhor)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top