简体   繁体   中英

Euler#12, what's wrong with my Python program?

The 12th problem is :

The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

Let us list the factors of the first seven triangle numbers:

1: 1 3: 1,3 6: 1,2,3,6 10: 1,2,5,10 15: 1,3,5,15 21: 1,3,7,21 28: 1,2,4,7,14,28 We can see that 28 is the first triangle number to have over five divisors.

What is the value of the first triangle number to have over five hundred divisors?


My program in Python 3.4

def Nfactor(n):
    k=2
    c=0
    while k<=n:
        if n%k==0:
          n=n//k
          c+=1
        else:
            k=k+1       
    return c

a=1    
for i in range(10**6):
    a+=i
    if Nfactor(a)>=500:
        print(a)
        break

I waited more than 10 minutes and never have an answer. And for my own my program is not too bad and must run in seconds.. well it makes me crazy lol i didn't find my mistake.

Can you help me please?

Thank you in advance !


EDIT

My solution now :

import math

def Nfactor(n):
    if n==1:
        return 1
    else:
        c=0

        for i in range(1, int(math.sqrt(n)+1)):
            if n%i==0:
                c+=1
        return c*2

a=0    
for i in range(1,10**6):
    a+=i
    if Nfactor(a)>=500:
        print(a)
        break

You will most likely not get any output.

Your last value of a is 499999500001 while the smallest number for which NFactor(..) is 500, is 2^500 which is 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376


a few hints (I have a working example which runs in less than one second now but I guess posting it here would be a spoiler):

  • as the another (deleted) answer pointed out, given the count of prime factors for a number, the number of divisors of a number is the product of (counts of each prime factor plus one), ie if a prime factor p appears N times, you can build N+1 products from that from 0 to p^N and combine the different powers of the primes.

  • as @NightShadeQueen points out, once you have calculated the prime factorization of a number n , keep it in a cache (I use a dict mapping from n to a dict which itself maps from a prime number to the number of times it occurs). When asked to calculate the set of prime factors for a given number, first check the cache, then start scanning from 2 upwards to see if you can find a first factor. Then call the function recursively with n divided by the first factor etc.

  • for finding prime factors of n, there is no need to go up to n, you can stop at sqrt(n)

  • when finding prime factors ( k in your function Nfactor(..) ), you can check k=2 , k=3 (ie if 2 divides n , if 3 divides n etc.) and then increment k in steps of 2 (only test odd values of k after k=2 )

  • as mentioned in a comment above, start with a=1 and use range(1,10**6) instead for i

Not used in my solution; found by using my favourite search engine:

  • the i'th triangle number is a = i * (i+1) / 2 so you can combine the prime factors of i and i+1 (removing one occurrence of 2 ). Since i and i+1 do not share any common prime factors you can even derive the number of divisors of a from the number of divisors of i and i+1 .

Some thoughts...

  1. If I read correctly, you're effectively testing every number n from 2 to to n. You should be able to test just to sqrt(n). (Update: Apologies, I was not thinking clearly... it needs to be to n/2, not sqrt(n). Testing for primality would require only to sqrt(n).)
  2. Run 2 ** 500 in a python shell. I think you'll find you're not testing nearly high enough. :-)
  3. Maybe go lower... test your method with a smaller number of factors?

You are listing the prime numbers, but not their products. In the definition, for 28, you have 7, 14, and 28 where in your function you just count the number 7.

So the Nfactor, to do it as asked, should look like this :

def Nfactor(n):
    k=2
    c=2
    while k<n:
        if n%k == 0:
            c+=1
        k=k+1       
    return c

But there is a really faster way to get the factors (thanks to this page ):

from math import sqrt
def Nfactor(n):
    factors = set()
    for x in range(1, int(sqrt(n)) + 1):
        if n % x == 0:
            factors.add(x)
            factors.add(n//x)
     return len(factors)

Also, you are not following the instructions. You don't limit your search to the numbers defined by the sum of subsequent terms (1, 1+2, 1+2+3, 1+2+3+4, etc), but are making the test for every number ( for i in range(10**6): ).

To have these numbers, you could use a generator (see here ) like this :

def gen():
    counter = 1
    total = 0
    while True:
        total += counter
        yield total
        counter += 1

and then, you could do this to find your desired number :

g = gen()
for n in g:
    if Nfactor(n) > 500:
        print(n)
        break
import math
num=2
i=3
def is_notprime(num):
    j=3
    flag=int(math.sqrt(num))   
    while((j<=flag and num>=3)):    
      if num%j==0:    
        return True
        break
      else:
        j=j+2
def check_div(num):
  temp=1
  a=i
  if(num%2==0 and num>1):
    while(num%2==0):
        num=num/2
        temp+=1
  for j in range(3,int((num+5)/2),2):
    count=1
    if((is_notprime(num) and num>1) or num==j):
      while num%j==0:
        num=num/j
        count+=1
    elif num>1:
      temp=temp*2
      break

    temp=temp*count
  print("divisor is and  %d ans is %d" %(temp,a))
  return(temp)
while(i>=1):
  if(check_div(i)>5):
    break
  num+=1
  i=num*(num+1)/2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM