나는 STArray가 어떻게 작동하는지 배우려고했으나 할 수 없었다. (의사는 가난하거나 적어도 내가 찾은 사람이 아닙니다.)1) 배열을 사용하여 2) 목록 연결을 피하십시오 (지연 목록?)?
어쨌든 나는 다음 알고리즘을 가지고 있지만 많이 사용합니다!는 느립니다. 어떻게 STArray 모나드를 사용하도록 변환 할 수 있습니까?
-- The Algorithm prints the primes present in [1 .. n]
main :: IO()
main = print $ primesUpTo 100
type Nat = Int
primesUpTo :: Nat -> [Nat]
primesUpTo n = primesUpToAux n 2 [1]
primesUpToAux :: Nat -> Nat -> [Nat] -> [Nat]
primesUpToAux n current primes =
if current > n
then primes
else primesUpToAux n (current + 1) newAcum
where newAcum = case isPrime current primes of
True -> primes++[current]
False -> primes
isPrime :: Nat -> [Nat] -> Bool
isPrime 1 _ = True
isPrime 2 _ = True
isPrime x neededPrimes = isPrimeAux x neededPrimes 1
isPrimeAux x neededPrimes currentPrimeIndex =
if sqrtOfX < currentPrime
then True
else if mod x currentPrime == 0
then False
else isPrimeAux x neededPrimes (currentPrimeIndex + 1)
where
sqrtOfX = sqrtNat x
currentPrime = neededPrimes !! currentPrimeIndex
sqrtNat :: Nat -> Nat
sqrtNat = floor . sqrt . fromIntegral
편집
아차는! 문제가 아니었다. 다음 버전의 알고리즘 (아래)에서 나는 !!의 사용을 제거했습니다; 또한, 나는 @pedrorodrigues
main :: IO()
main = print $ primesUpTo 20000
type Nat = Int
primesUpTo :: Nat -> [Nat]
primesUpTo n = primesUpToAux n 1 []
primesUpToAux :: Nat -> Nat -> [Nat] -> [Nat]
primesUpToAux n current primesAcum =
if current > n
then primesAcum
else primesUpToAux n (current + 1) newPrimesAcum
where newPrimesAcum = case isPrime current primesAcum of
True -> primesAcum++[current]
False -> primesAcum
isPrime :: Nat -> [Nat] -> Bool
isPrime 1 _ = False
isPrime 2 _ = True
isPrime x neededPrimes =
if sqrtOfX < currentPrime
then True
else if mod x currentPrime == 0
then False
else isPrime x restOfPrimes
where
sqrtOfX = sqrtNat x
currentPrime:restOfPrimes = neededPrimes
sqrtNat :: Nat -> Nat
sqrtNat = floor . sqrt . fromIntegral
에 의해 지적, 아닌 프라임 지금이 질문은 정말 약 2 질문입니다 인 1 고정 : 배열을 사용하려면이 알고리즘을 변형하는 방법
1 .- 목록 대신? (하스켈에서 상태와 배열을 다루는 법을 배우기위한 것입니다.) 누군가 이미 코멘트에 답변했지만,별로 좋지 않은 설명이있는 예를 가리키고 있습니다.
2.- 새로운 소수가 발견 될 때마다 목록의 연결을 제거하는 방법은 무엇입니까?
진정한 ->은 [전류]
여기에서는 알고리즘의 단순한 평가판 인 STArray가 필요하지 않습니다. 여러분은 다른 것들보다 먼저 표준 목록 조작 함수 ('filter','takeWhile','all','any' 등)를보아야합니다, 왜냐하면 문제는 그것들을 사용하여 최적으로 그리고 관용적으로 해결 될 수 있기 때문입니다. 꽤 우회로를 만들고있어. –
기능적 스타일에서 빠른 구현을 원하십니까? 이전의 코멘트를보고 (그리고 목록에 의해 맹목적으로 표현 세트의 잘못을 피하십시오). 또는 STArray를 사용하는 방법을 배우고 싶다면 - STArray의 문제점을 정확하게 설명하십시오. 그렇다면 "필수"코드를 작성해야한다는 것을 알고 있습니다 (모든 것이 ST 모나드에 있음). – d8d0d65b3f7cf42
1 그런데, 소수되지 않습니다. –