5

I would like to know how in Python I can iterate through a set of conditions.

  1. string that has 2-6 lower alpha or numeric characters
  2. the first character is always a number

So a short progression would be:

1a
1b
1c
...
1aa
1ab
1ac
...
2aaa
2aab
2aac

etc.

A horrible example that can do the first two is

##Loop through 1a-z0-9
start = '1'
l = 97
while l < 123:
    num = start
    num += chr(l)
    print num
    l += 1

l = 48
while l < 58:
    num = start
    num += chr(l)
    print num
    l += 1

I found itertools but can't find good examples to go off of.

Michael J. Barber
  • 22,744
  • 8
  • 61
  • 84
Ryan
  • 157
  • 1
  • 2
  • 12

4 Answers4

5

You can do this using itertools.product and itertools.chain. First define strings of the numbers and letters:

numbers = '0123456789'
alnum = numbers + 'abcdefghijklmnopqrstuvwxyz'

Using itertools.product, you can get tuples with the characters for the strings of various length:

len2 = itertools.product(numbers, alnum) # length 2
len3 = itertools.product(numbers, alnum, alnum) # length 3
...

Chain the iterators for all the lengths together, joining the tuples into strings. I'd do it with a list comprehension:

[''.join(p) for p in itertools.chain(len2, len3, len4, len5, len6)]
Michael J. Barber
  • 22,744
  • 8
  • 61
  • 84
  • if letters was `['a','b','c']` you can do the following one liner, lol `[ ''.join(p) for p in chain( *[ product( numbers, *letters * times )for times in xrange(2, 6 + 1 ) ] )` – Doboy Mar 17 '12 at 07:56
  • but, dont use that one liner rather use the concepts in it namely `*` the unpacking operator – Doboy Mar 17 '12 at 08:00
  • Yup this did it! Thanks a bunch! – Ryan Mar 17 '12 at 16:58
3

I would go with product function from itertools.

import itertools 
digits = '0123456789'
alphanum = 'abcdef...z' + digits # this should contain all the letters and digits

for i in xrange(1, 6):    
    for tok in itertools.product(digits, itertools.product(alphanum, repeat=i)):
        # do whatever you want with this token `tok` here.
dirtybit
  • 627
  • 6
  • 16
  • hmm.. will `permutations(letters, 5 )` include repeated letters like `aaaaa`, and will it will definitely not contain alphanumerics less than 5 in length like `aa` – Doboy Mar 17 '12 at 07:40
  • i've missed that variable length. it seems better now :) i think we are ok with repeated letters here. – dirtybit Mar 17 '12 at 07:43
  • I am not sure about the repeated letters, `list(itertools.permutations( 'ab', 2 ))` returns `[('a', 'b'), ('b', 'a')]` for me, which does not include `aa` nor `bb` – Doboy Mar 17 '12 at 07:51
  • 1
    `permutations` isn't what you need here. Use `product` with a `repeat` optional argument given. – Michael J. Barber Mar 17 '12 at 07:57
1

You can think of this problem in base 26 (Ignoring the first number, we will put this in a separate case.) So with the letters we want to range from 'a' to 'zzzzz' in the base 26 would be 0 and (26,26,26,26,26) = 26 ^ 0 + 26 + 26^2 + 26^3 + 26^4 + 26^5. So now we have a bijection from numbers to letters, we just want to write a function that takes us from a number to a word

 letters = 'abcdef..z'

 def num_to_word( num ):
      res = ''
      while num:
           res += letters[num%26]
           num //= 26
      return res

Now to write our function that enumerates this

 def generator():
     for num in xrange(10):
         for letter_num in xrange( sum( 26 ** i for i in xrange( 6 ) ) + 1 ):
             tok = str(num) + num_to_word( letter_num )
             yield tok
Doboy
  • 8,863
  • 9
  • 35
  • 48
-1

lets do this with a breadth first search type algorithm

starting from 
Root:
    have 10 children, i = 0,1,...,9
    so , this root must have an iterator, 'i'
    therefore this outermost loop will iterate 'i' from 0 to 9

i:
    for each 'i', there are 5 children (ix , ixx, ixxx, ixxxx, ixxxxx)
    ( number of chars at the string )
    so each i should have its own iterator 'j' representing number of chars
    the loop inside Root's loop will iterate 'j' from 1 to 5

j:
    'j' will have 'j' number of children ( 1 -> x , 2 -> xx ,..., 5-> xxxxx)
    so each j will have its own iterator 'k' representing each "character"
    so, 'k' will be iterated inside this j loop, from 1 to j
    ( i=2, j=4, k = 3 will focus on 'A' at string  "2xxAx" )

k:
    each 'k' represents a character, so it iterates from 'a' to 'z'
    each k should have a iterator(value) 'c' that iterates from 'a' to 'z' (or 97 to 122)

i think this will make sense than what i wanted to show u earlier. :) if u dont get the idea please tell me.. btw, its an interesting question :)

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
Deamonpog
  • 757
  • 1
  • 7
  • 21
  • I would like to iterate through this, and place it in a list. I'm trying to go through all combinations of a URL. So it would be http://site.com/place/1a then http://site.com/place/1ab etc. So I'm trying to build the last part of the URL. – Ryan Mar 17 '12 at 06:26
  • so, u want to brute force(a greedy search) through every possible link named "" thing. rite? ok i will edit my answer. – Deamonpog Mar 17 '12 at 06:31