У меня есть последовательность делителей простых чисел, которую я хочу перебрать для каждого кандидата на простые числа. Я использую GetEnumerator (), MoveNext () и Current. Я не могу повторно инициализировать перечислитель, чтобы он начал с самого начала. Я попробовал Reset (), который скомпилирован, но выдает ошибку выполнения: не реализовано.
Я использую F # 2.0 Interactive build 4.0.40219.1
Какие-либо предложения?
С уважением, Дуг
Чтобы прояснить проблему: для каждого основного кандидата N я хочу перебрать последовательность простых делителей (примерно до sqrt N) и полностью разложить N на множители или определить, является ли оно простым. Используя GetEnumerator, MoveNext, подход Current работает для первого основного кандидата, но для второго основного кандидата я хочу повторить свою последовательность делителей с самого начала. Похоже, что единственный способ сделать это - создать новый итератор (что неудобно для большого числа основных кандидатов) или создать новую последовательность простых чисел (чего я не хочу делать).
Предложение использовать что-то вроде «divisors in seqPrimes», кажется, исчерпывает все делители перед остановкой, но я хочу остановиться, как только простой делитель делит первого кандидата.
Если в приведенных выше утверждениях есть ошибка в моей логике, пожалуйста, дайте мне знать.
Я исследовал Seq.cache, и у меня это сработало. Полученный код выглядит следующим образом:
// Recursive isprime function (modified from MSDN)
let isPrime n =
let rec check i =
i > n/2 || (n % i <> 0 && check (i + 2))
if n = 2 then true
elif (n%2) = 0 then false
else check 3
let seqPrimes = seq { for n in 2 .. 100000 do if isPrime n then yield n }
// Cache the sequence to avoid recomputing the sequence elements.
let cachedSeq = Seq.cache seqPrimes
// find the divisors of n (or determine prime) using the seqEnum enumerator
let rec testPrime n (seqEnum:System.Collections.Generic.IEnumerator<int>) =
if n = 1 then printfn "completely factored"
else
let nref = ref n
if seqEnum.MoveNext() then
let divisor = seqEnum.Current
//printfn "trial divisor %A" divisor
if divisor*divisor > n then printfn "prime %A" !nref
else
while ((!nref % divisor) = 0) do
printfn "divisor %A" divisor
nref := !nref / divisor
testPrime !nref seqEnum
// test
for x = 1000000 to 1000010 do
printfn "\ndivisors of %d = " x
let seqEnum = cachedSeq.GetEnumerator()
testPrime x seqEnum
seqEnum.Dispose() // not needed
IEnumerator
, когда можно просто использовать синтаксисfor x in y
. Если вам нужно; просто создайте новый перечислитель. Публикация кода будет полезна, потому что я думаю, что мы сможем найти лучшую альтернативу. - person vcsjones   schedule 16.01.2012