1

Possible Duplicate:
Using itertools.product and want to seed a value

I have this code, which generates a consistent list of strings.

import itertools
choices = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"
for length in range(0,20):
    for entry in itertools.product(choices, repeat = length):
        string = ''.join(entry)
        print string

I want to be able to continue running this script from the last known string. How is this possible to do?

Community
  • 1
  • 1
Dmytro Sadovnychyi
  • 6,171
  • 5
  • 33
  • 60
  • 2
    This may be relevant: http://stackoverflow.com/questions/9864809/using-itertools-product-and-want-to-seed-a-value – abought Nov 13 '12 at 21:07

3 Answers3

4
import itertools
def choices():
    choices = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"
    for length in range(0,20):
        for entry in itertools.product(choices, repeat = length):
            string = ''.join(entry)
            yield string

choice_seq = choices()
print next(choice_seq)
print next(choice_seq)

The point of generators is that they carry their state with them.

Marcin
  • 48,559
  • 18
  • 128
  • 201
2

Assuming you have the variable string set as the last known string (or '' to start at beginning):

import itertools
choices = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"
for length in range(len(string), 20):
    itr = itertools.product(choices, repeat = length)
    if string != '' and length == len(string):
        itr = itertools.dropwhile(tuple(string).__ne__, itr)
    for entry in itr:
        string = ''.join(entry)
        print string

Note that the first element this will print is the last known string. If you want to skip the last known and start by printing the next string, you could do next(itr) inside of the if statement.

This assumes that you are trying to resume where you left off on multiple executions of a script, or other scenarios where a generator solution isn't applicable. If you can use a generator, you should.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
0

Your "saved state" is just the current length, and the current state of the itertools.product. Both of those things can be pickled. So, here's some pseudocode:

import itertools
import pickle

choices = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"

def tryWithStateSave(currentlength, currentproduct):
    try:
        for entry in currentproduct:
            string = ''.join(entry)
            print string
    except KeyboardInterrupt:
        pickle.dump((currentlength, currentproduct), <saved state file>)
        raise

if <a saved state file exists>:
    currentlength, currentproduct = pickle.load(<the saved state file>)
    tryWithStateSave(currentlength, currentproduct)
    currentlength += 1
else:
    currentlength = 0

for length in range(currentlength+1,20):
    tryWithStateSave(length, itertools.product(choices, repeat = length))
abarnert
  • 354,177
  • 51
  • 601
  • 671