Finding nth Prime using Python and Sieve of Eratosthenes

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
8
down vote

favorite
2












I'm currently working through the Project Euler Problems using HackerRank to evaluate the code and I'm stuck on the 7th Problem.



"""
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

What is the 10 001st prime number?

"""
import pytest

def find_primes(limit):
nums = [True] * (limit+1)
nums[0] = nums[1] = False

for (i, is_prime) in enumerate(nums):
if is_prime:
yield i
for n in range(i*i, limit+1, i):
nums[n] = False

def find_n_prime(n):
for i in range(n, (n*n)+1, n):
primes = list(find_primes(i))
if len(primes) >= n:
return primes[n-1]

def test_find_n_primes():
assert find_n_prime(2) == 3
assert find_n_prime(3) == 5

assert find_n_prime(10) == 29
assert find_n_prime(15) == 47
assert find_n_prime(81) == 419

assert find_n_prime(941) == 7417
assert find_n_prime(1000) == 7919

assert find_n_prime(10001) == 104743


The code only completes the first test case on hackerRank and fails for #2 test case and times out for the rest.



How can I improve the Code ?







share|improve this question



























    up vote
    8
    down vote

    favorite
    2












    I'm currently working through the Project Euler Problems using HackerRank to evaluate the code and I'm stuck on the 7th Problem.



    """
    By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

    What is the 10 001st prime number?

    """
    import pytest

    def find_primes(limit):
    nums = [True] * (limit+1)
    nums[0] = nums[1] = False

    for (i, is_prime) in enumerate(nums):
    if is_prime:
    yield i
    for n in range(i*i, limit+1, i):
    nums[n] = False

    def find_n_prime(n):
    for i in range(n, (n*n)+1, n):
    primes = list(find_primes(i))
    if len(primes) >= n:
    return primes[n-1]

    def test_find_n_primes():
    assert find_n_prime(2) == 3
    assert find_n_prime(3) == 5

    assert find_n_prime(10) == 29
    assert find_n_prime(15) == 47
    assert find_n_prime(81) == 419

    assert find_n_prime(941) == 7417
    assert find_n_prime(1000) == 7919

    assert find_n_prime(10001) == 104743


    The code only completes the first test case on hackerRank and fails for #2 test case and times out for the rest.



    How can I improve the Code ?







    share|improve this question























      up vote
      8
      down vote

      favorite
      2









      up vote
      8
      down vote

      favorite
      2






      2





      I'm currently working through the Project Euler Problems using HackerRank to evaluate the code and I'm stuck on the 7th Problem.



      """
      By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

      What is the 10 001st prime number?

      """
      import pytest

      def find_primes(limit):
      nums = [True] * (limit+1)
      nums[0] = nums[1] = False

      for (i, is_prime) in enumerate(nums):
      if is_prime:
      yield i
      for n in range(i*i, limit+1, i):
      nums[n] = False

      def find_n_prime(n):
      for i in range(n, (n*n)+1, n):
      primes = list(find_primes(i))
      if len(primes) >= n:
      return primes[n-1]

      def test_find_n_primes():
      assert find_n_prime(2) == 3
      assert find_n_prime(3) == 5

      assert find_n_prime(10) == 29
      assert find_n_prime(15) == 47
      assert find_n_prime(81) == 419

      assert find_n_prime(941) == 7417
      assert find_n_prime(1000) == 7919

      assert find_n_prime(10001) == 104743


      The code only completes the first test case on hackerRank and fails for #2 test case and times out for the rest.



      How can I improve the Code ?







      share|improve this question













      I'm currently working through the Project Euler Problems using HackerRank to evaluate the code and I'm stuck on the 7th Problem.



      """
      By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

      What is the 10 001st prime number?

      """
      import pytest

      def find_primes(limit):
      nums = [True] * (limit+1)
      nums[0] = nums[1] = False

      for (i, is_prime) in enumerate(nums):
      if is_prime:
      yield i
      for n in range(i*i, limit+1, i):
      nums[n] = False

      def find_n_prime(n):
      for i in range(n, (n*n)+1, n):
      primes = list(find_primes(i))
      if len(primes) >= n:
      return primes[n-1]

      def test_find_n_primes():
      assert find_n_prime(2) == 3
      assert find_n_prime(3) == 5

      assert find_n_prime(10) == 29
      assert find_n_prime(15) == 47
      assert find_n_prime(81) == 419

      assert find_n_prime(941) == 7417
      assert find_n_prime(1000) == 7919

      assert find_n_prime(10001) == 104743


      The code only completes the first test case on hackerRank and fails for #2 test case and times out for the rest.



      How can I improve the Code ?









      share|improve this question












      share|improve this question




      share|improve this question








      edited Apr 4 at 16:26









      Grant Miller

      2202416




      2202416









      asked Jan 16 at 13:47









      Aswin Mohan

      1459




      1459




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          10
          down vote



          accepted










          Upper bound for p_n



          There is a known upper bound for the n-th prime.



          It means that you don't need any loop inside find_n_prime, and you don't need to check if len(primes) >= n either.



          import pytest
          from math import log, ceil

          def find_primes(limit):
          nums = [True] * (limit + 1)
          nums[0] = nums[1] = False

          for (i, is_prime) in enumerate(nums):
          if is_prime:
          yield i
          for n in range(i * i, limit + 1, i):
          nums[n] = False

          def upper_bound_for_p_n(n):
          if n < 6:
          return 100
          return ceil(n * (log(n) + log(log(n))))

          def find_n_prime(n):
          primes = list(find_primes(upper_bound_for_p_n(n)))
          return primes[n - 1]


          It calculates the 100000th prime in less than 230ms on my computer, compared to 1.5s for your code.



          itertools.islice



          Another possible optimization would be to use itertools.isclice to get the n-th prime out of the find_primes generator, without converting it to a list.



          from itertools import islice

          def find_n_prime(n):
          primes = find_primes(upper_bound_for_p_n(n))
          return next(islice(primes, n - 1, n))





          share|improve this answer























          • If the upper bound is $U$ then the running time of Eratosphenes' sieve is $O(U lg lg U)$. If you really want overkill, Meissel-Lehmer with an intelligent interpolation search should be $O(U^0.67+epsilon lg U)$. Maybe considerably better if you can cache and reuse subcomputations.
            – Peter Taylor
            Apr 24 at 15:12











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185219%2ffinding-nth-prime-using-python-and-sieve-of-eratosthenes%23new-answer', 'question_page');

          );

          Post as a guest






























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          10
          down vote



          accepted










          Upper bound for p_n



          There is a known upper bound for the n-th prime.



          It means that you don't need any loop inside find_n_prime, and you don't need to check if len(primes) >= n either.



          import pytest
          from math import log, ceil

          def find_primes(limit):
          nums = [True] * (limit + 1)
          nums[0] = nums[1] = False

          for (i, is_prime) in enumerate(nums):
          if is_prime:
          yield i
          for n in range(i * i, limit + 1, i):
          nums[n] = False

          def upper_bound_for_p_n(n):
          if n < 6:
          return 100
          return ceil(n * (log(n) + log(log(n))))

          def find_n_prime(n):
          primes = list(find_primes(upper_bound_for_p_n(n)))
          return primes[n - 1]


          It calculates the 100000th prime in less than 230ms on my computer, compared to 1.5s for your code.



          itertools.islice



          Another possible optimization would be to use itertools.isclice to get the n-th prime out of the find_primes generator, without converting it to a list.



          from itertools import islice

          def find_n_prime(n):
          primes = find_primes(upper_bound_for_p_n(n))
          return next(islice(primes, n - 1, n))





          share|improve this answer























          • If the upper bound is $U$ then the running time of Eratosphenes' sieve is $O(U lg lg U)$. If you really want overkill, Meissel-Lehmer with an intelligent interpolation search should be $O(U^0.67+epsilon lg U)$. Maybe considerably better if you can cache and reuse subcomputations.
            – Peter Taylor
            Apr 24 at 15:12















          up vote
          10
          down vote



          accepted










          Upper bound for p_n



          There is a known upper bound for the n-th prime.



          It means that you don't need any loop inside find_n_prime, and you don't need to check if len(primes) >= n either.



          import pytest
          from math import log, ceil

          def find_primes(limit):
          nums = [True] * (limit + 1)
          nums[0] = nums[1] = False

          for (i, is_prime) in enumerate(nums):
          if is_prime:
          yield i
          for n in range(i * i, limit + 1, i):
          nums[n] = False

          def upper_bound_for_p_n(n):
          if n < 6:
          return 100
          return ceil(n * (log(n) + log(log(n))))

          def find_n_prime(n):
          primes = list(find_primes(upper_bound_for_p_n(n)))
          return primes[n - 1]


          It calculates the 100000th prime in less than 230ms on my computer, compared to 1.5s for your code.



          itertools.islice



          Another possible optimization would be to use itertools.isclice to get the n-th prime out of the find_primes generator, without converting it to a list.



          from itertools import islice

          def find_n_prime(n):
          primes = find_primes(upper_bound_for_p_n(n))
          return next(islice(primes, n - 1, n))





          share|improve this answer























          • If the upper bound is $U$ then the running time of Eratosphenes' sieve is $O(U lg lg U)$. If you really want overkill, Meissel-Lehmer with an intelligent interpolation search should be $O(U^0.67+epsilon lg U)$. Maybe considerably better if you can cache and reuse subcomputations.
            – Peter Taylor
            Apr 24 at 15:12













          up vote
          10
          down vote



          accepted







          up vote
          10
          down vote



          accepted






          Upper bound for p_n



          There is a known upper bound for the n-th prime.



          It means that you don't need any loop inside find_n_prime, and you don't need to check if len(primes) >= n either.



          import pytest
          from math import log, ceil

          def find_primes(limit):
          nums = [True] * (limit + 1)
          nums[0] = nums[1] = False

          for (i, is_prime) in enumerate(nums):
          if is_prime:
          yield i
          for n in range(i * i, limit + 1, i):
          nums[n] = False

          def upper_bound_for_p_n(n):
          if n < 6:
          return 100
          return ceil(n * (log(n) + log(log(n))))

          def find_n_prime(n):
          primes = list(find_primes(upper_bound_for_p_n(n)))
          return primes[n - 1]


          It calculates the 100000th prime in less than 230ms on my computer, compared to 1.5s for your code.



          itertools.islice



          Another possible optimization would be to use itertools.isclice to get the n-th prime out of the find_primes generator, without converting it to a list.



          from itertools import islice

          def find_n_prime(n):
          primes = find_primes(upper_bound_for_p_n(n))
          return next(islice(primes, n - 1, n))





          share|improve this answer















          Upper bound for p_n



          There is a known upper bound for the n-th prime.



          It means that you don't need any loop inside find_n_prime, and you don't need to check if len(primes) >= n either.



          import pytest
          from math import log, ceil

          def find_primes(limit):
          nums = [True] * (limit + 1)
          nums[0] = nums[1] = False

          for (i, is_prime) in enumerate(nums):
          if is_prime:
          yield i
          for n in range(i * i, limit + 1, i):
          nums[n] = False

          def upper_bound_for_p_n(n):
          if n < 6:
          return 100
          return ceil(n * (log(n) + log(log(n))))

          def find_n_prime(n):
          primes = list(find_primes(upper_bound_for_p_n(n)))
          return primes[n - 1]


          It calculates the 100000th prime in less than 230ms on my computer, compared to 1.5s for your code.



          itertools.islice



          Another possible optimization would be to use itertools.isclice to get the n-th prime out of the find_primes generator, without converting it to a list.



          from itertools import islice

          def find_n_prime(n):
          primes = find_primes(upper_bound_for_p_n(n))
          return next(islice(primes, n - 1, n))






          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Jan 16 at 18:04


























          answered Jan 16 at 14:40









          Eric Duminil

          1,8501613




          1,8501613











          • If the upper bound is $U$ then the running time of Eratosphenes' sieve is $O(U lg lg U)$. If you really want overkill, Meissel-Lehmer with an intelligent interpolation search should be $O(U^0.67+epsilon lg U)$. Maybe considerably better if you can cache and reuse subcomputations.
            – Peter Taylor
            Apr 24 at 15:12

















          • If the upper bound is $U$ then the running time of Eratosphenes' sieve is $O(U lg lg U)$. If you really want overkill, Meissel-Lehmer with an intelligent interpolation search should be $O(U^0.67+epsilon lg U)$. Maybe considerably better if you can cache and reuse subcomputations.
            – Peter Taylor
            Apr 24 at 15:12
















          If the upper bound is $U$ then the running time of Eratosphenes' sieve is $O(U lg lg U)$. If you really want overkill, Meissel-Lehmer with an intelligent interpolation search should be $O(U^0.67+epsilon lg U)$. Maybe considerably better if you can cache and reuse subcomputations.
          – Peter Taylor
          Apr 24 at 15:12





          If the upper bound is $U$ then the running time of Eratosphenes' sieve is $O(U lg lg U)$. If you really want overkill, Meissel-Lehmer with an intelligent interpolation search should be $O(U^0.67+epsilon lg U)$. Maybe considerably better if you can cache and reuse subcomputations.
          – Peter Taylor
          Apr 24 at 15:12













           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185219%2ffinding-nth-prime-using-python-and-sieve-of-eratosthenes%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Chat program with C++ and SFML

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          Will my employers contract hold up in court?