Pregunta

Tengo este programa de iteraciones complejas que escribí en TI Basic para realizar una iteración básica en un número complejo y luego dar la magnitud del 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

Lo que me gustaría hacer es hacer una versión de Haskell para impresionar a mi maestro en una tarea. Todavía estoy aprendiendo y llegué hasta aquí:

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

Lo que no sé hacer es cómo hacerlo solo iterar n veces, así que quería que cuente a y luego compararlo con n para ver si había terminado.

¿Cómo haría esto?

¿Fue útil?

Solución

La respuesta de Newacct muestra el camino:

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

Iterate genera la lista infinita de aplicaciones repetidas. Ej:

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

Con respecto al IO, tendrá que hacer algunos 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)

Dado que Complex es convertible desde y hacia cadenas de forma predeterminada, puede usar readLn para leerlos desde la consola (el formato es Re: + Im ).

Editar: solo por diversión, uno podría desugar la sintaxis monádica y las firmas de tipo que comprimirían todo el programa para esto:

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)

Editar # 2: algunos enlaces relacionados con el trazado y los conjuntos de Mandelbrot.

Otros consejos

Bueno, siempre puede generar una lista infinita de resultados de aplicaciones repetidas y tomar el primer n de ellos usando take . Y la función iterate es útil para generar una lista infinita de resultados de aplicaciones repetidas.

Si desea una 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)

Si solo te importa el ú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)

Básicamente, en ambos casos necesita una función auxiliar para el conteo y la acumulación. Ahora estoy seguro de que hay una manera mejor / menos detallada de hacer esto, pero yo mismo soy un novato de Haskell.

Editar: solo por diversión, un pliegue de una sola línea:

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

(aunque, lo (tomar n (repetir c)) parece un poco innecesario, tiene que haber una forma aún mejor)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top