2

When I run this code I don't get all the possible combinations of 3 characters:

def comb(iterable, r):
    pool = tuple(iterable)
    n = len(pool)
    for indices in permutations(range(n), r):
        if sorted(indices) == list(indices):
            yield tuple(pool[i] for i in indices)
def start():
    for x in comb("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12234567890!@#$%^&*?,()-=+[]/;",3):
        print x

Instead it skips some. When I repeated the characters 3 times, I got all the combinations I needed, but I get some multiple times. This takes triple the time and isn't what I want. I'm going to be calculating millions of of combinations so I need to to know an alternative to repeating the characters.

agf
  • 171,228
  • 44
  • 289
  • 238
Noah R
  • 5,287
  • 21
  • 56
  • 75
  • 3
    Lets say you wanted length 2 instead of instead of 3, and you had `abcd` as your string. What would you want the output to be? `ab, ac, ad, bc, bd, cd`? `aa, ab, ac, ad, bb, bc, bd, cc, cd, dd`? `aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc, cd, da, db, dc, dd`? `ab, ac, ad, ba, bc, bd, ca, cb, cd, da, db, dc`? Something else? – agf Apr 19 '12 at 18:41
  • aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc, cd, da, db, dc, dd is the output I'm looking for. – Noah R Apr 19 '12 at 18:43
  • 2
    In case you do not find a way to do w/o the long string literal, you may want to look at what you can import from `string`. E.g., `from string import printable` `print printable` yields `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~` without error (in your example 2 is listed twice, and other characters might be missing) Smaller specific subsets are available too, like `ascii_lowercase, ascii_uppercase, punctuation` and `digits` – Levon Apr 19 '12 at 18:46
  • 1
    People would be having a hard time understanding the question. This requires rewording. – Abhijit Apr 19 '12 at 18:48
  • @Abhijit all the info we needed was in his comment :) – agf Apr 19 '12 at 18:50

1 Answers1

8

You're looking for itertools.product(characters, repeat = 3).

See the itertools.product docs.

>>> ' '.join(''.join(x) for x in itertools.product('abcd', repeat = 2))
aa ab ac ad ba bb bc bd ca cb cc cd da db dc dd
agf
  • 171,228
  • 44
  • 289
  • 238
  • This is almost what I want. However, when I did a test at a repeat of 2 when it hit "('b', 'c')" I want it to be "('b', 'a')" It totally skipped over the 'a'. This also happens for the rest except skipping the corresponding letter before it. – Noah R Apr 19 '12 at 18:51
  • @NoahR You made a mistake. Look at the example in my answer. It hits every set of two, including doubled letters, with order mattering -- `ba` and `ab` are considered different. I've use `product` many times to do exactly what you're doing. What you're describing is `combinations_with_replacement`, not `product`. – agf Apr 19 '12 at 18:53
  • Could you use my code edit it and post it on your answer so I can see clearly what you're doing that I'm not? – Noah R Apr 19 '12 at 18:59
  • @NoahR You don't need any of your code at all, except the `for` loop. Just `for chars in itertools.product(characters, repeat = 3): print chars` would do it. You don't need `combs`, which is a really inefficient way of generating combinations from permutations and was meant only as an example in the docs. It has nothing to do with `product`. – agf Apr 19 '12 at 19:02
  • You're really looking for permutations, or combinations with replacement. See Lossy's answer. –  Apr 19 '12 at 22:00
  • 1
    @Brendan No, he's not. Look at his comment on the question. He wants `aa`, `ba` and `ab` -- only `product` will give him all 3. `permutations` won't give him `aa`, `combinations` won't give him eiher `aa` or `ba`, and `combinations_with_replacement` won't give him `ba`. I asked him a very carefully constructed question in the comments in order to determine which one he wanted. – agf Apr 19 '12 at 22:07
  • 1
    For what it's worth (not much more than moral support I'm afraid), I agree that this is 100% correct according to Noah R's comments. As a side note, I find that the word "combination" is _horribly_ abused in all sorts of ways. "On this site" I was about to say -- but really -- everywhere. Sigh. – senderle Apr 22 '12 at 12:34
  • @senderle It's always a problem when words have both formal meanings in a jargon and informal meanings. I've accidentally insulted people by calling something "trivial" when I meant "simple", which is what it means in mathematics, but they assumed I meant "unimportant". It's good to have someone back me up here so future readers don't get even more confused. – agf Apr 23 '12 at 03:54
  • @senderle It appears the disagreeing user has been deleted, leaving only his posts behind. – agf Apr 23 '12 at 06:56