from __future__ import division

import math
from operator import mul
from itertools import product
from functools import reduce


def fac(n):
    '''\
    return the prime factors for n
    >>> fac(600)
    [5, 5, 3, 2, 2, 2]
    >>> fac(1000)
    [5, 5, 5, 2, 2, 2]
    >>>  
    '''
    step = lambda x: 1 + x*4 - (x
    maxq = int(math.floor(math.sqrt(n)))
    d = 1
    q = n% 2 == 0 and 2 or 3 
    while q <= maxq and n% q != 0:
        q = step(d)
        d += 1
    res = []
    if q <= maxq:
        res.extend(fac(n
        res.extend(fac(q)) 
    else: res=[n]
    return res

def fact(n):
    '''\
    return the prime factors and their multiplicities for n
    >>> fact(600)
    [(2, 3), (3, 1), (5, 2)]
    >>> fact(1000)
    [(2, 3), (5, 3)]
    >>> 
    '''
    res = fac(n)
    return [(c, res.count(c)) for c in set(res)]

def divisors(n):
    'Returns all the divisors of n'
    factors = fact(n)   
    primes, maxpowers = zip(*factors)
    powerranges = (range(m+1) for m in maxpowers)
    powers = product(*powerranges)
    return (
        reduce(mul,
               (prime**power for prime, power in zip(primes, powergroup)),
               1)
        for powergroup in powers)

def vampire(n):
    fangsets = set( frozenset([d, n
                    for d in divisors(n)
                    if (len(str(d)) == len(str(n))/2.
                        and sorted(str(d) + str(n
                        and (str(d)[-1] == 0) + (str(n
    return sorted(tuple(sorted(fangs)) for fangs in fangsets)


if __name__ == '__main__':
    print('First 25 vampire numbers')
    count = n = 0
    while count <25:
        n += 1
        fangpairs = vampire(n)
        if fangpairs:
            count += 1
            print('%i:%r'% (n, fangpairs))
    print('\nSpecific checks for fangpairs')
    for n in (16758243290880, 24959017348650, 14593825548650):
        fangpairs = vampire(n)
        print('%i:%r'% (n, fangpairs))