Я работаю над созданием метода, зазора (g, m, n).ruby - Быстрый поиск пробела
Все 3 параметра являются целыми числами.
Зазор обнаруживает первые два последовательных простых числа между m и n, которые имеют разность g.
Например, зазор (2, 1, 10) => [3, 5]
В диапазоне от т до п, 1..10, первые 2 последовательных простых чисел с зазором 2 - [3,5].
Если вместо этого, он был зазор (1, 1, 10) => [2,3]
и если это был зазор (6, 1, 10) => NIL
# method to check if a number is prime
def prime?(num)
(2..Math.sqrt(num).floor).each do |m|
if num % m == 0
return false
end
end
true
end
этот метод работает путем перебора каждого числа от 2, наименьшее простое число, к корню квадратному из параметра, проверяя, если параметр нацело на что-нибудь в этом диапазоне. Если это так, метод возвращает false.
# gap method
def gap(g, m, n)
if g.odd? && g > 1
return nil
end
primes = (m..n).select do |num|
num.odd? && prime?(num)
end
first = primes[0..-2].find_index do |x|
primes[primes.index(x) + 1] - x == g
end
[
primes[first],
primes[first+1]
] unless first.nil?
end
gap(2, 10000000, 11000000)
Все простые числа имеют разрыв либо 2, 4, или номер, состоящий из 2 и 4-х вместе добавил. Единственным исключением является разрыв с 2-3.
Таким образом, если аргумент gap, g, задан как 3, который является нечетным и больше 1, метод автоматически возвращает nil, потому что такой простой разрыв отсутствует.
Проблема
Моя проблема заключается в том, что метод является слишком медленным. Используя ссылку на реплику выше, вы получаете время около 20 секунд. По-видимому, его можно получить примерно на 1 секунду.
Я попытался оптимизировать, отфильтровывая четные числа уже с m..n, что помогло. Но я просто не уверен, как я могу добиться этого еще быстрее.
Я думаю, что прежде чем обнаруживать каждое простое число в m..n, я должен проверять каждую итерацию, если пробел правильный, поэтому, как только я нахожу это, я могу просто прекратить метод, не глядя на ненужные простые числа , но я не уверен, как это реализовать.
Спасибо за помощь, и любая общая критика моего кода также приветствуется.
Вы пытались описать свой код? Трудно оптимизировать без профилирования в первую очередь, но моя ставка заключается в том, что вы должны использовать более быстрый метод нахождения простых чисел, например, решета Эратосфена? – cthulhu
Я не слишком уверен, как полностью профиль, но я знаю, что узким местом кода является эта часть primes = (m..n) .select {| num | num.odd? && prime? (num)} –
Я думаю, что ваша идея («Что я думаю ...») будет значительным ускорением. Подумайте о том, как вы это сделаете, если будете работать на бумаге. Вероятно, вы могли бы записать самый последний премьер и текущий премьер где-нибудь и проверить пробел, прежде чем перейти к следующему премьеру. Для этого вам нужен только один цикл. –