Project Euler Problem #7 in Python (10001st prime number)











up vote
9
down vote

favorite












I have managed to solve the 7th Project Euler problem, however I think it can be improved by a lot, I am by no means a professional programmer or even consider myself really good at it. Any improvements / suggestions would be really helpful.



Problem statement:




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?




This is my solution.



counter = 2
n = 10001
for i in range(3, 1000000, 2):
k = 1
while k < i:
k += 2
if i % k == 0:
break
if k + 2 == i:
counter += 1
if counter == n:
print(i)
raise ZeroDivisionError


The program does skip 2 and 3, in an attempt of mine to make it faster. At the end I raise an error in order to stop the program from looping.










share|improve this question




























    up vote
    9
    down vote

    favorite












    I have managed to solve the 7th Project Euler problem, however I think it can be improved by a lot, I am by no means a professional programmer or even consider myself really good at it. Any improvements / suggestions would be really helpful.



    Problem statement:




    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?




    This is my solution.



    counter = 2
    n = 10001
    for i in range(3, 1000000, 2):
    k = 1
    while k < i:
    k += 2
    if i % k == 0:
    break
    if k + 2 == i:
    counter += 1
    if counter == n:
    print(i)
    raise ZeroDivisionError


    The program does skip 2 and 3, in an attempt of mine to make it faster. At the end I raise an error in order to stop the program from looping.










    share|improve this question


























      up vote
      9
      down vote

      favorite









      up vote
      9
      down vote

      favorite











      I have managed to solve the 7th Project Euler problem, however I think it can be improved by a lot, I am by no means a professional programmer or even consider myself really good at it. Any improvements / suggestions would be really helpful.



      Problem statement:




      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?




      This is my solution.



      counter = 2
      n = 10001
      for i in range(3, 1000000, 2):
      k = 1
      while k < i:
      k += 2
      if i % k == 0:
      break
      if k + 2 == i:
      counter += 1
      if counter == n:
      print(i)
      raise ZeroDivisionError


      The program does skip 2 and 3, in an attempt of mine to make it faster. At the end I raise an error in order to stop the program from looping.










      share|improve this question















      I have managed to solve the 7th Project Euler problem, however I think it can be improved by a lot, I am by no means a professional programmer or even consider myself really good at it. Any improvements / suggestions would be really helpful.



      Problem statement:




      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?




      This is my solution.



      counter = 2
      n = 10001
      for i in range(3, 1000000, 2):
      k = 1
      while k < i:
      k += 2
      if i % k == 0:
      break
      if k + 2 == i:
      counter += 1
      if counter == n:
      print(i)
      raise ZeroDivisionError


      The program does skip 2 and 3, in an attempt of mine to make it faster. At the end I raise an error in order to stop the program from looping.







      python python-3.x programming-challenge primes






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Feb 21 at 21:38









      200_success

      128k15149412




      128k15149412










      asked Feb 21 at 19:17









      Gentlebud

      462




      462






















          5 Answers
          5






          active

          oldest

          votes

















          up vote
          3
          down vote













          I'm not going to pay attention to your algorithm, as Arnav is right there, but instead focus on style problems. It should be a giant red flag when you raise a ZeroDivisionError when you aren't dividing by zero. The correct solution here is to put your code inside a function, which will let you return the correct result. While here, you might as well make the upper limit of your range n*n instead of 1,000,000, which will let it work for bigger values. Also, I know I said I wouldn't focus on the algorithm, but you can make the inner loop be while k*k<i, as any prime factor of n will be less than the n**.5. This simple change makes your code take .1 second instead of 30.



          def nth_prime(n):
          counter = 2
          for i in range(3, n**2, 2):
          k = 1
          while k*k < i:
          k += 2
          if i % k == 0:
          break
          else:
          counter += 1
          if counter == n:
          return i

          print(nth_prime(100001))





          share|improve this answer

















          • 1




            Nice. It's still pretty close to OP's code while not being too inefficient. You need print(nth_prime(10001)), though.
            – Eric Duminil
            Feb 22 at 10:31


















          up vote
          3
          down vote













          Upper bound for p_n



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



          It means that you don't need to guess how large it could be. upper_bound_for_p_n(10001) tells us in less than a micro-second that the desired number cannot be larger than 114320.



          You just need to apply the Sieve of Erathosthenes up to 114320 and you're done:



          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 10001th prime in 15ms on my computer, compared to 35s for your code.






          share|improve this answer





















          • Also, 1.26*n*log(n) is a tighter upper bound for n>17
            – Oscar Smith
            Feb 22 at 20:08


















          up vote
          3
          down vote













          What I dislike about your solution is the unnecessarily large amount of complexity your code has, which takes a toll on its performance.



          When I solved this problem myself, I used the Sieve of Eratosthenes to generate a list of prime numbers up to an arbitrary limit (I also picked one million, but you could use a formula to compute it) and indexed that list at 10,000 to get the 10,001st number.



          Here is how I implemented the sieve:



          def primes_upto(limit):
          limitN = limit+1
          not_prime = set()
          primes = [2]

          for i in range(3, limitN, 2):
          if i in not_prime:
          continue

          for j in range(i*3, limitN, i*2):
          not_prime.add(j)

          primes.append(i)
          return primes


          As you can see, this approach reduces the complexity of your code. Also, this is approximately 28 seconds quicker than your approach.






          share|improve this answer






























            up vote
            0
            down vote













            One way to solve this problem and use memory efficiently is through generators, this way only one prime at the time is processed and you won't get out of memory



            def is_prime(n):
            if n == 2:
            return True
            if n % 2 == 0 or n < 2:
            return False
            limit = int(n ** 0.5) + 1
            for i in range(3, limit, 2):
            if n % i == 0:
            return False
            return True

            def next_prime(count_limit):
            yield 2
            count = 1
            n = 3
            while True:
            if is_prime(n):
            yield n
            count += 1
            if count == count_limit:
            return
            n += 2

            n = 10001

            # Good
            item = None
            for item in next_prime(n):
            pass
            print(item)

            # Better
            from collections import deque
            dd = deque(next_prime(n), maxlen=1)
            print(dd.pop())


            Aditionally, if you need to run it several times, memoizing is suggested:



            def memoize(f):
            memo = {}
            def helper(x):
            if x not in memo:
            memo[x] = f(x)
            return memo[x]
            return helper

            @memoize
            def is_prime(n):
            ...





            share|improve this answer





















            • The first half of this isn't so much a review as an alternate method. You talk about reducing memory, but OP's algo was already O(1)
              – Oscar Smith
              Feb 22 at 3:23










            • You could also use islice to access the n-th element of your generator. You could also rename your functions. I wouldn't expect next_prime to return a generator of primes.
              – Eric Duminil
              Feb 22 at 10:32


















            up vote
            0
            down vote













            I use generator also.



            def prime():


            import itertools


            yield 2

            for i in itertools.count(3, 2):
            if i == 2:
            yield 2
            else:
            e = int(i**.5) + 1
            for j in range(2, e+1):
            if i % j == 0:
            break
            elif j < e:
            continue
            else:
            yield i

            for i, n in enumerate(prime()):
            if i < 10001:
            pass
            elif i == 10001:
            print(n)
            else:
            break





            share|improve this answer








            New contributor




            Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.


















              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: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              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%2f188053%2fproject-euler-problem-7-in-python-10001st-prime-number%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              5 Answers
              5






              active

              oldest

              votes








              5 Answers
              5






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              3
              down vote













              I'm not going to pay attention to your algorithm, as Arnav is right there, but instead focus on style problems. It should be a giant red flag when you raise a ZeroDivisionError when you aren't dividing by zero. The correct solution here is to put your code inside a function, which will let you return the correct result. While here, you might as well make the upper limit of your range n*n instead of 1,000,000, which will let it work for bigger values. Also, I know I said I wouldn't focus on the algorithm, but you can make the inner loop be while k*k<i, as any prime factor of n will be less than the n**.5. This simple change makes your code take .1 second instead of 30.



              def nth_prime(n):
              counter = 2
              for i in range(3, n**2, 2):
              k = 1
              while k*k < i:
              k += 2
              if i % k == 0:
              break
              else:
              counter += 1
              if counter == n:
              return i

              print(nth_prime(100001))





              share|improve this answer

















              • 1




                Nice. It's still pretty close to OP's code while not being too inefficient. You need print(nth_prime(10001)), though.
                – Eric Duminil
                Feb 22 at 10:31















              up vote
              3
              down vote













              I'm not going to pay attention to your algorithm, as Arnav is right there, but instead focus on style problems. It should be a giant red flag when you raise a ZeroDivisionError when you aren't dividing by zero. The correct solution here is to put your code inside a function, which will let you return the correct result. While here, you might as well make the upper limit of your range n*n instead of 1,000,000, which will let it work for bigger values. Also, I know I said I wouldn't focus on the algorithm, but you can make the inner loop be while k*k<i, as any prime factor of n will be less than the n**.5. This simple change makes your code take .1 second instead of 30.



              def nth_prime(n):
              counter = 2
              for i in range(3, n**2, 2):
              k = 1
              while k*k < i:
              k += 2
              if i % k == 0:
              break
              else:
              counter += 1
              if counter == n:
              return i

              print(nth_prime(100001))





              share|improve this answer

















              • 1




                Nice. It's still pretty close to OP's code while not being too inefficient. You need print(nth_prime(10001)), though.
                – Eric Duminil
                Feb 22 at 10:31













              up vote
              3
              down vote










              up vote
              3
              down vote









              I'm not going to pay attention to your algorithm, as Arnav is right there, but instead focus on style problems. It should be a giant red flag when you raise a ZeroDivisionError when you aren't dividing by zero. The correct solution here is to put your code inside a function, which will let you return the correct result. While here, you might as well make the upper limit of your range n*n instead of 1,000,000, which will let it work for bigger values. Also, I know I said I wouldn't focus on the algorithm, but you can make the inner loop be while k*k<i, as any prime factor of n will be less than the n**.5. This simple change makes your code take .1 second instead of 30.



              def nth_prime(n):
              counter = 2
              for i in range(3, n**2, 2):
              k = 1
              while k*k < i:
              k += 2
              if i % k == 0:
              break
              else:
              counter += 1
              if counter == n:
              return i

              print(nth_prime(100001))





              share|improve this answer












              I'm not going to pay attention to your algorithm, as Arnav is right there, but instead focus on style problems. It should be a giant red flag when you raise a ZeroDivisionError when you aren't dividing by zero. The correct solution here is to put your code inside a function, which will let you return the correct result. While here, you might as well make the upper limit of your range n*n instead of 1,000,000, which will let it work for bigger values. Also, I know I said I wouldn't focus on the algorithm, but you can make the inner loop be while k*k<i, as any prime factor of n will be less than the n**.5. This simple change makes your code take .1 second instead of 30.



              def nth_prime(n):
              counter = 2
              for i in range(3, n**2, 2):
              k = 1
              while k*k < i:
              k += 2
              if i % k == 0:
              break
              else:
              counter += 1
              if counter == n:
              return i

              print(nth_prime(100001))






              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Feb 21 at 22:45









              Oscar Smith

              2,698922




              2,698922








              • 1




                Nice. It's still pretty close to OP's code while not being too inefficient. You need print(nth_prime(10001)), though.
                – Eric Duminil
                Feb 22 at 10:31














              • 1




                Nice. It's still pretty close to OP's code while not being too inefficient. You need print(nth_prime(10001)), though.
                – Eric Duminil
                Feb 22 at 10:31








              1




              1




              Nice. It's still pretty close to OP's code while not being too inefficient. You need print(nth_prime(10001)), though.
              – Eric Duminil
              Feb 22 at 10:31




              Nice. It's still pretty close to OP's code while not being too inefficient. You need print(nth_prime(10001)), though.
              – Eric Duminil
              Feb 22 at 10:31












              up vote
              3
              down vote













              Upper bound for p_n



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



              It means that you don't need to guess how large it could be. upper_bound_for_p_n(10001) tells us in less than a micro-second that the desired number cannot be larger than 114320.



              You just need to apply the Sieve of Erathosthenes up to 114320 and you're done:



              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 10001th prime in 15ms on my computer, compared to 35s for your code.






              share|improve this answer





















              • Also, 1.26*n*log(n) is a tighter upper bound for n>17
                – Oscar Smith
                Feb 22 at 20:08















              up vote
              3
              down vote













              Upper bound for p_n



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



              It means that you don't need to guess how large it could be. upper_bound_for_p_n(10001) tells us in less than a micro-second that the desired number cannot be larger than 114320.



              You just need to apply the Sieve of Erathosthenes up to 114320 and you're done:



              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 10001th prime in 15ms on my computer, compared to 35s for your code.






              share|improve this answer





















              • Also, 1.26*n*log(n) is a tighter upper bound for n>17
                – Oscar Smith
                Feb 22 at 20:08













              up vote
              3
              down vote










              up vote
              3
              down vote









              Upper bound for p_n



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



              It means that you don't need to guess how large it could be. upper_bound_for_p_n(10001) tells us in less than a micro-second that the desired number cannot be larger than 114320.



              You just need to apply the Sieve of Erathosthenes up to 114320 and you're done:



              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 10001th prime in 15ms on my computer, compared to 35s for your code.






              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 to guess how large it could be. upper_bound_for_p_n(10001) tells us in less than a micro-second that the desired number cannot be larger than 114320.



              You just need to apply the Sieve of Erathosthenes up to 114320 and you're done:



              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 10001th prime in 15ms on my computer, compared to 35s for your code.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Feb 22 at 10:27









              Eric Duminil

              2,0261613




              2,0261613












              • Also, 1.26*n*log(n) is a tighter upper bound for n>17
                – Oscar Smith
                Feb 22 at 20:08


















              • Also, 1.26*n*log(n) is a tighter upper bound for n>17
                – Oscar Smith
                Feb 22 at 20:08
















              Also, 1.26*n*log(n) is a tighter upper bound for n>17
              – Oscar Smith
              Feb 22 at 20:08




              Also, 1.26*n*log(n) is a tighter upper bound for n>17
              – Oscar Smith
              Feb 22 at 20:08










              up vote
              3
              down vote













              What I dislike about your solution is the unnecessarily large amount of complexity your code has, which takes a toll on its performance.



              When I solved this problem myself, I used the Sieve of Eratosthenes to generate a list of prime numbers up to an arbitrary limit (I also picked one million, but you could use a formula to compute it) and indexed that list at 10,000 to get the 10,001st number.



              Here is how I implemented the sieve:



              def primes_upto(limit):
              limitN = limit+1
              not_prime = set()
              primes = [2]

              for i in range(3, limitN, 2):
              if i in not_prime:
              continue

              for j in range(i*3, limitN, i*2):
              not_prime.add(j)

              primes.append(i)
              return primes


              As you can see, this approach reduces the complexity of your code. Also, this is approximately 28 seconds quicker than your approach.






              share|improve this answer



























                up vote
                3
                down vote













                What I dislike about your solution is the unnecessarily large amount of complexity your code has, which takes a toll on its performance.



                When I solved this problem myself, I used the Sieve of Eratosthenes to generate a list of prime numbers up to an arbitrary limit (I also picked one million, but you could use a formula to compute it) and indexed that list at 10,000 to get the 10,001st number.



                Here is how I implemented the sieve:



                def primes_upto(limit):
                limitN = limit+1
                not_prime = set()
                primes = [2]

                for i in range(3, limitN, 2):
                if i in not_prime:
                continue

                for j in range(i*3, limitN, i*2):
                not_prime.add(j)

                primes.append(i)
                return primes


                As you can see, this approach reduces the complexity of your code. Also, this is approximately 28 seconds quicker than your approach.






                share|improve this answer

























                  up vote
                  3
                  down vote










                  up vote
                  3
                  down vote









                  What I dislike about your solution is the unnecessarily large amount of complexity your code has, which takes a toll on its performance.



                  When I solved this problem myself, I used the Sieve of Eratosthenes to generate a list of prime numbers up to an arbitrary limit (I also picked one million, but you could use a formula to compute it) and indexed that list at 10,000 to get the 10,001st number.



                  Here is how I implemented the sieve:



                  def primes_upto(limit):
                  limitN = limit+1
                  not_prime = set()
                  primes = [2]

                  for i in range(3, limitN, 2):
                  if i in not_prime:
                  continue

                  for j in range(i*3, limitN, i*2):
                  not_prime.add(j)

                  primes.append(i)
                  return primes


                  As you can see, this approach reduces the complexity of your code. Also, this is approximately 28 seconds quicker than your approach.






                  share|improve this answer














                  What I dislike about your solution is the unnecessarily large amount of complexity your code has, which takes a toll on its performance.



                  When I solved this problem myself, I used the Sieve of Eratosthenes to generate a list of prime numbers up to an arbitrary limit (I also picked one million, but you could use a formula to compute it) and indexed that list at 10,000 to get the 10,001st number.



                  Here is how I implemented the sieve:



                  def primes_upto(limit):
                  limitN = limit+1
                  not_prime = set()
                  primes = [2]

                  for i in range(3, limitN, 2):
                  if i in not_prime:
                  continue

                  for j in range(i*3, limitN, i*2):
                  not_prime.add(j)

                  primes.append(i)
                  return primes


                  As you can see, this approach reduces the complexity of your code. Also, this is approximately 28 seconds quicker than your approach.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Feb 22 at 11:33

























                  answered Feb 21 at 22:10









                  Arnav Borborah

                  693121




                  693121






















                      up vote
                      0
                      down vote













                      One way to solve this problem and use memory efficiently is through generators, this way only one prime at the time is processed and you won't get out of memory



                      def is_prime(n):
                      if n == 2:
                      return True
                      if n % 2 == 0 or n < 2:
                      return False
                      limit = int(n ** 0.5) + 1
                      for i in range(3, limit, 2):
                      if n % i == 0:
                      return False
                      return True

                      def next_prime(count_limit):
                      yield 2
                      count = 1
                      n = 3
                      while True:
                      if is_prime(n):
                      yield n
                      count += 1
                      if count == count_limit:
                      return
                      n += 2

                      n = 10001

                      # Good
                      item = None
                      for item in next_prime(n):
                      pass
                      print(item)

                      # Better
                      from collections import deque
                      dd = deque(next_prime(n), maxlen=1)
                      print(dd.pop())


                      Aditionally, if you need to run it several times, memoizing is suggested:



                      def memoize(f):
                      memo = {}
                      def helper(x):
                      if x not in memo:
                      memo[x] = f(x)
                      return memo[x]
                      return helper

                      @memoize
                      def is_prime(n):
                      ...





                      share|improve this answer





















                      • The first half of this isn't so much a review as an alternate method. You talk about reducing memory, but OP's algo was already O(1)
                        – Oscar Smith
                        Feb 22 at 3:23










                      • You could also use islice to access the n-th element of your generator. You could also rename your functions. I wouldn't expect next_prime to return a generator of primes.
                        – Eric Duminil
                        Feb 22 at 10:32















                      up vote
                      0
                      down vote













                      One way to solve this problem and use memory efficiently is through generators, this way only one prime at the time is processed and you won't get out of memory



                      def is_prime(n):
                      if n == 2:
                      return True
                      if n % 2 == 0 or n < 2:
                      return False
                      limit = int(n ** 0.5) + 1
                      for i in range(3, limit, 2):
                      if n % i == 0:
                      return False
                      return True

                      def next_prime(count_limit):
                      yield 2
                      count = 1
                      n = 3
                      while True:
                      if is_prime(n):
                      yield n
                      count += 1
                      if count == count_limit:
                      return
                      n += 2

                      n = 10001

                      # Good
                      item = None
                      for item in next_prime(n):
                      pass
                      print(item)

                      # Better
                      from collections import deque
                      dd = deque(next_prime(n), maxlen=1)
                      print(dd.pop())


                      Aditionally, if you need to run it several times, memoizing is suggested:



                      def memoize(f):
                      memo = {}
                      def helper(x):
                      if x not in memo:
                      memo[x] = f(x)
                      return memo[x]
                      return helper

                      @memoize
                      def is_prime(n):
                      ...





                      share|improve this answer





















                      • The first half of this isn't so much a review as an alternate method. You talk about reducing memory, but OP's algo was already O(1)
                        – Oscar Smith
                        Feb 22 at 3:23










                      • You could also use islice to access the n-th element of your generator. You could also rename your functions. I wouldn't expect next_prime to return a generator of primes.
                        – Eric Duminil
                        Feb 22 at 10:32













                      up vote
                      0
                      down vote










                      up vote
                      0
                      down vote









                      One way to solve this problem and use memory efficiently is through generators, this way only one prime at the time is processed and you won't get out of memory



                      def is_prime(n):
                      if n == 2:
                      return True
                      if n % 2 == 0 or n < 2:
                      return False
                      limit = int(n ** 0.5) + 1
                      for i in range(3, limit, 2):
                      if n % i == 0:
                      return False
                      return True

                      def next_prime(count_limit):
                      yield 2
                      count = 1
                      n = 3
                      while True:
                      if is_prime(n):
                      yield n
                      count += 1
                      if count == count_limit:
                      return
                      n += 2

                      n = 10001

                      # Good
                      item = None
                      for item in next_prime(n):
                      pass
                      print(item)

                      # Better
                      from collections import deque
                      dd = deque(next_prime(n), maxlen=1)
                      print(dd.pop())


                      Aditionally, if you need to run it several times, memoizing is suggested:



                      def memoize(f):
                      memo = {}
                      def helper(x):
                      if x not in memo:
                      memo[x] = f(x)
                      return memo[x]
                      return helper

                      @memoize
                      def is_prime(n):
                      ...





                      share|improve this answer












                      One way to solve this problem and use memory efficiently is through generators, this way only one prime at the time is processed and you won't get out of memory



                      def is_prime(n):
                      if n == 2:
                      return True
                      if n % 2 == 0 or n < 2:
                      return False
                      limit = int(n ** 0.5) + 1
                      for i in range(3, limit, 2):
                      if n % i == 0:
                      return False
                      return True

                      def next_prime(count_limit):
                      yield 2
                      count = 1
                      n = 3
                      while True:
                      if is_prime(n):
                      yield n
                      count += 1
                      if count == count_limit:
                      return
                      n += 2

                      n = 10001

                      # Good
                      item = None
                      for item in next_prime(n):
                      pass
                      print(item)

                      # Better
                      from collections import deque
                      dd = deque(next_prime(n), maxlen=1)
                      print(dd.pop())


                      Aditionally, if you need to run it several times, memoizing is suggested:



                      def memoize(f):
                      memo = {}
                      def helper(x):
                      if x not in memo:
                      memo[x] = f(x)
                      return memo[x]
                      return helper

                      @memoize
                      def is_prime(n):
                      ...






                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Feb 22 at 3:03









                      Ezequiel Castaño

                      417




                      417












                      • The first half of this isn't so much a review as an alternate method. You talk about reducing memory, but OP's algo was already O(1)
                        – Oscar Smith
                        Feb 22 at 3:23










                      • You could also use islice to access the n-th element of your generator. You could also rename your functions. I wouldn't expect next_prime to return a generator of primes.
                        – Eric Duminil
                        Feb 22 at 10:32


















                      • The first half of this isn't so much a review as an alternate method. You talk about reducing memory, but OP's algo was already O(1)
                        – Oscar Smith
                        Feb 22 at 3:23










                      • You could also use islice to access the n-th element of your generator. You could also rename your functions. I wouldn't expect next_prime to return a generator of primes.
                        – Eric Duminil
                        Feb 22 at 10:32
















                      The first half of this isn't so much a review as an alternate method. You talk about reducing memory, but OP's algo was already O(1)
                      – Oscar Smith
                      Feb 22 at 3:23




                      The first half of this isn't so much a review as an alternate method. You talk about reducing memory, but OP's algo was already O(1)
                      – Oscar Smith
                      Feb 22 at 3:23












                      You could also use islice to access the n-th element of your generator. You could also rename your functions. I wouldn't expect next_prime to return a generator of primes.
                      – Eric Duminil
                      Feb 22 at 10:32




                      You could also use islice to access the n-th element of your generator. You could also rename your functions. I wouldn't expect next_prime to return a generator of primes.
                      – Eric Duminil
                      Feb 22 at 10:32










                      up vote
                      0
                      down vote













                      I use generator also.



                      def prime():


                      import itertools


                      yield 2

                      for i in itertools.count(3, 2):
                      if i == 2:
                      yield 2
                      else:
                      e = int(i**.5) + 1
                      for j in range(2, e+1):
                      if i % j == 0:
                      break
                      elif j < e:
                      continue
                      else:
                      yield i

                      for i, n in enumerate(prime()):
                      if i < 10001:
                      pass
                      elif i == 10001:
                      print(n)
                      else:
                      break





                      share|improve this answer








                      New contributor




                      Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.






















                        up vote
                        0
                        down vote













                        I use generator also.



                        def prime():


                        import itertools


                        yield 2

                        for i in itertools.count(3, 2):
                        if i == 2:
                        yield 2
                        else:
                        e = int(i**.5) + 1
                        for j in range(2, e+1):
                        if i % j == 0:
                        break
                        elif j < e:
                        continue
                        else:
                        yield i

                        for i, n in enumerate(prime()):
                        if i < 10001:
                        pass
                        elif i == 10001:
                        print(n)
                        else:
                        break





                        share|improve this answer








                        New contributor




                        Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                        Check out our Code of Conduct.




















                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          I use generator also.



                          def prime():


                          import itertools


                          yield 2

                          for i in itertools.count(3, 2):
                          if i == 2:
                          yield 2
                          else:
                          e = int(i**.5) + 1
                          for j in range(2, e+1):
                          if i % j == 0:
                          break
                          elif j < e:
                          continue
                          else:
                          yield i

                          for i, n in enumerate(prime()):
                          if i < 10001:
                          pass
                          elif i == 10001:
                          print(n)
                          else:
                          break





                          share|improve this answer








                          New contributor




                          Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.









                          I use generator also.



                          def prime():


                          import itertools


                          yield 2

                          for i in itertools.count(3, 2):
                          if i == 2:
                          yield 2
                          else:
                          e = int(i**.5) + 1
                          for j in range(2, e+1):
                          if i % j == 0:
                          break
                          elif j < e:
                          continue
                          else:
                          yield i

                          for i, n in enumerate(prime()):
                          if i < 10001:
                          pass
                          elif i == 10001:
                          print(n)
                          else:
                          break






                          share|improve this answer








                          New contributor




                          Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.









                          share|improve this answer



                          share|improve this answer






                          New contributor




                          Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.









                          answered 22 mins ago









                          Matt Cao

                          1




                          1




                          New contributor




                          Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.





                          New contributor





                          Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.






                          Matt Cao is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Code Review Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              Use MathJax to format equations. MathJax reference.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188053%2fproject-euler-problem-7-in-python-10001st-prime-number%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Costa Masnaga

                              Fotorealismo

                              Sidney Franklin