Python生成一系列没有相同数字和数字的数字。独特

时间:2016-07-27 16:10:14

标签: python

我想弄清楚如何生成一个不仅是唯一的,而且没有相似数字的数字列表 目的是使用crypt来破解样本哈希,我知道密码是唯一的,没有重复的数字和最多6位数

例>

[1,2,3,4,5,6,7,8,9...120, 123,124,125,126,127... 123456,123457...]

所以122或123451或12345673因为会有重复的数字

我的代码

#!/usr/bin/env python

from os import getuid
from crypt import crypt
import time

# all initialisation here
password = range(1000000)
# all initialisation ends here

def VerifyHash(shadowHashes, salt, user):
    # crypt("Message", "Salt")
    for i in password:
        if (shadowHashes == crypt(str(i),salt)):
            print "Password of %s is " % user + str(i)
            break
        else:
            pass

def main():
    with open('shadow.txt') as p:
            for line in p:
                shadowList = line
                shadowHashes = shadowList.split(':')[1]
                user = shadowList.split(':')[0]
                salt = shadowHashes[:12]
                VerifyHash(shadowHashes,salt,user)  

main()

现在我使用范围(1000000)并且它有效但效率低,因为我所比较的数字是唯一的,没有重复数字所以我想让我的python程序更有效

请指出正确的方向

3 个答案:

答案 0 :(得分:3)

对越来越多的重复数字使用itertools.permutations(),最多9位,将这些数字与1到9之间的所有数字相结合(以防止生成带前导0的数字)。

from itertools import permutations

def generate_unique_numbers():
    yield 0
    for i in range(10):
        for leading in '123456789':
            if not i:  # 1-digit numbers
                yield int(leading)
                continue
            remaining_digits = '0123456789'.replace(leading, '')
            for combo in permutations(remaining_digits, i):
                yield int(leading + ''.join(combo))

这会生成所有这些有效数字,而不必跳过任何内容。有8877691这样的数字,范围从0到9876543210:

>>> sum(1 for _ in generate_unique_numbers())
8877691
>>> next(generate_unique_numbers())
0
>>> for i in generate_unique_numbers(): pass
...
>>> i
9876543210

输出的一些样本:

>>> from itertools import islice
>>> gen = generate_unique_numbers()
>>> list(islice(gen, 15))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15]
>>> list(islice(gen, 150, 165))
[204, 205, 206, 207, 208, 209, 210, 213, 214, 215, 216, 217, 218, 219, 230]
>>> list(islice(gen, 100000, 100015))
[542319, 542360, 542361, 542367, 542368, 542369, 542370, 542371, 542376, 542378, 542379, 542380, 542381, 542386, 542387]
>>> list(islice(gen, 1000000, 1000015))
[31279056, 31279058, 31279064, 31279065, 31279068, 31279084, 31279085, 31279086, 31279405, 31279406, 31279408, 31279450, 31279456, 31279458, 31279460]

这种方法比用range(9876543211)生成所有数字然后过滤掉重复数字的数字(这是Moses Koledoye正在做的那样)要快得多:

>>> from timeit import timeit
>>> from itertools import islice
>>> def consume_n(it, n): next(islice(it, n, n), None)
...
>>> timeit('consume_n(gen(), 10000)', 'from __main__ import consume_n, unique_count as gen', number=100)
1.825788974761963
>>> timeit('consume_n(gen(), 10000)', 'from __main__ import consume_n, generate_unique_numbers as gen', number=100)
0.6307981014251709

上述代码仅为每种方法生成前10000个数字,并重复这些测试100次。我的方法很容易快3倍!

增加计数(并调整重复次数以保持可管理性),对比度增加:

>>> timeit('consume_n(gen(), 100000)', 'from __main__ import consume_n, unique_count as gen', number=10)
4.125269889831543
>>> timeit('consume_n(gen(), 100000)', 'from __main__ import consume_n, generate_unique_numbers as gen', number=10)
0.6416079998016357

现在差异已经增长了6倍。仅使用range版本生成前一百万个数字 23秒,使用上述生成器生成.67秒

>>> timeit('consume_n(gen(), 1000000)', 'from __main__ import consume_n, unique_count as gen', number=1)
23.268329858779907
>>> timeit('consume_n(gen(), 1000000)', 'from __main__ import consume_n, generate_unique_numbers as gen', number=1)
0.6738729476928711

你走的系列越远,必须跳过更自然的数字,速度差异才会进一步增大;例如,必须跳过8800000000-8899999999范围内的所有数字,range()方法将测试所有。这是1亿浪费的周期!

发生器可以在我的笔记本电脑上以6.7秒的速度生成所有可能的数字:

>>> from collections import deque
>>> def consume(it): deque(it, maxlen=0)
...
>>> timeit('consume(gen())', 'from __main__ import consume, generate_unique_numbers as gen', number=1)
6.6731719970703125

我没有敢于测试range()方法需要多长时间;这些数字不到900万,但range()方法将测试接近100亿种可能性,是所需数量的10000倍。

答案 1 :(得分:3)

当数字中的数字放在一个集合中时,您可以检查当表示为字符串时数字的长度是否相同:

def unique_count():
    for i in range(1000000):
        if len(str(i)) == len(set(str(i))):
            yield i

该集合消除了重复的数字,因此没有重复数字的数字将通过该条件。

答案 2 :(得分:0)

您可以使用下面的生成函数获取最大数字i然后它将生成小于i唯一的数字的侦听,并且不重复数字。

def isDigitsRepeated(integer):
    n = str(integer)
    digits = []
    for digit in n:
        if digit in digits:
            return True
        digits += [digit]
    return False

def generate(maximum):
    lst = []
    for x in range(maximum):
        if not isDigitsRepeated(x):
            lst += [x]
    return lst