Domanda

Ho questo complesso programma di iterazioni che ho scritto in TI Basic per eseguire un'iterazione di base su un numero complesso e quindi dare la grandezza del risultato:

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

Quello che vorrei fare è fare una versione di Haskell per stupire il mio insegnante in un compito. Sto ancora imparando e sono arrivato così lontano:

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

Quello che non so come fare è come farlo iterare solo n volte, quindi volevo che contasse a e poi confrontarlo con n per vedere se era finito.

Come potrei farlo?

È stato utile?

Soluzione

La risposta di Newacct mostra il modo:

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

Iterate genera l'elenco infinito di applicazioni ripetute. Es:

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

Per quanto riguarda l'IO, dovrai fare alcuni calcoli monadici.

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)

Poiché Complex è convertibile da e in stringhe per impostazione predefinita, è possibile utilizzare readLn per leggerli dalla console (il formato è Re: + Im ).

Modifica: solo per divertimento, si potrebbe desugar la sintassi monadica e digitare le firme che comprimerebbero l'intero programma a questo:

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)

Modifica n. 2: alcuni link relativi alla trama e ai set di Mandelbrot.

Altri suggerimenti

Beh, puoi sempre generare un elenco infinito di risultati di applicazioni ripetute e prenderne il primo n usando take . E la funzione iterate è utile per generare un elenco infinito di risultati di applicazioni ripetute.

Se desideri un elenco di valori:

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 ti interessa solo l'ultimo risultato:

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

Fondamentalmente, in entrambi i casi è necessaria una funzione di supporto per il conteggio e l'accumulo. Ora sono sicuro che ci sia un modo migliore / meno prolisso per farlo, ma sono praticamente un neofita di Haskell da solo.

Modifica: solo per i calci, un foldr one-liner:

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

(anche se la cosa (take n (repeat c)) sembra un po 'superflua, deve esserci un modo ancora migliore)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top