Divisor game cheating aid This code outputs the smallest number with more divisors than the input:

from operator import mul
from math import sqrt, ceil

def next_prime_factor(n):
    if n % 2 == 0:
        return 2
    for x in range(3, int(ceil(sqrt(n)) + 1), 2):
        if n % x == 0:
            return x
    return int(n)

def factor(n):
    factors=[]
    number=int(n)
    while number &gt; 1:
                f=next_prime_factor(number)
                factors.append(f)
                number /= float(f)
                number=int(number)
                if number==1:break

    return list(factors)

def sundaram(max_n):
    numbers = range(3, max_n+1, 2)
    half = (max_n)/2
    initial = 4
    for step in xrange(3, max_n+1, 2):
        for i in xrange(initial, half, step):
            numbers[i-1] = 0
        initial += 2*(step+1)

        if initial &gt; half:
            x=filter(None, numbers) + [2] if filter(None, numbers) != None else [2]
            return sorted(x)

def factor_count(n):
    factors=factor(n)
    primecounts=[]
    primes_list=sundaram(int(sqrt(n)))
    primes_list = primes_list if primes_list != None else [2]
    for i in primes_list:
        primecounts.append(factors.count(i))
    return primecounts

def div_exps(pcount):
    return [i+1 for i in pcount if i!=0]

def div_count(n):
    pcount=factor_count(n)
    div_count=reduce(mul,div_exps(pcount),1)
    return div_count

def next_num(last_num):
    if last_num == 1:
        return 2
    if last_num in sundaram(last_num+1):
        return 4

    plist=sundaram(int(sqrt(last_num))+1)

    div_count_factors=factor(div_count(last_num))
    num=1
    for i in enumerate(div_count_factors):
        num*=plist[i[0]]**(i[1]-1)

    end_num=num
    while 1:
        if div_count(end_num)&lt;=div_count(last_num):
            end_num*=min(div_count_factors)
        else:
            break
    return end_num

ans=next_num(input('Input the last number chosen: '))
print 'The smallest number with more divisors than the inputted number is',ans,'.'


It was written to help win aid a number game.  The game is simple: somebody says a number, you say a number with more divisors than that number.  

You get a point if your number is smaller.  So if Bob says "5", you can say "4" and get a point. The winner is first to 3 points.

This code outputs the next best number given the previous number as input.
Style guide

You should code your Python to follow PEP (Python Enhancement Proposal) documents, and in particular, PEP8.

PEP8

Comparing your code to PEP8's standards shows quite a few violations.


You should have whitespace between your binary operators.





factors=[]
number=int(n)




Two blank lines after a declaration





from operator import mul
from math import sqrt, ceil

def next_prime_factor(n):




Comparison to None: instead of != None it should be is not None





x=filter(None, numbers) + [2] if filter(None, numbers) != None else [2]




Line too long: PEP8 has a maximum character count of 79 characters per line, this line has 82:




print 'The smallest number with more divisors than the inputted number is',ans,'.'




while 1 should be denoted as while True instead:



while 1:





Whitespace and naming

You have double indentation here:


while number &gt; 1:
            f=next_prime_factor(number)
            factors.append(f)
            number /= float(f)
            number=int(number)
            if number==1:break



You should avoid names like this:


numbers = range(3, max_n+1, 2)
half = (max_n)/2



Their purpose is a little confusing. Try to use more descriptive names that better describe what they are.

You should name your variables like snake_case:


primecounts





Unnecessary logic


div_count=reduce(mul,div_exps(pcount),1)
return div_count



You're defining a variable right before returning it, just return it directly.


for i in primes_list:
    primecounts.append(factors.count(i))
return v



You can use the list comprehension notation instead:

primecounts = [factors.count(i) for i in primes_list]



if div_count(end_num)&lt;=div_count(last_num):
    end_num*=min(div_count_factors)
else:
    break



When you have a block that looks like this:


if condition == true/false:
    doSomething()
else:
    endBlock #return, break, continue



When the block terminates in the else loop, you can reverse the conditions and reduce a layer of logic:


if condition != true/false:
    endBlock

doSomething()



So, you can simplify that above block down:

if div_count(end_num) &gt; div_count(last_num):
    break

end_num *= min(div_count_factors)


The code after the if is not needed: filter always returns a list, which is empty, if no elements remain. This results in identical behavior to the current code.


x=filter(None, numbers) + [2] if filter(None, numbers) != None else [2]