Number permutations in python iterative

前端 未结 3 537
囚心锁ツ
囚心锁ツ 2021-01-26 14:04

I need to generate permutations of digits, the number can be bigger than the digit count. For my current purpose I need to generate permutations of these digits 0, 1, 2

相关标签:
3条回答
  • 2021-01-26 14:13

    What you are looking is called a Cartesian product, not a permutation. Python itertools have a method itertools.product() to produce the desired result:

    import itertools
    
    for p in itertools.product(range(3), repeat=4):
        print p
    

    Output is 3^4 lines:

    (0, 0, 0, 0)
    (0, 0, 0, 1)
    (0, 0, 0, 2)
    (0, 0, 1, 0)
    (0, 0, 1, 1)
    ...
    (2, 2, 2, 1)
    (2, 2, 2, 2) 
    

    To produce output tuples with length form 1 to 4, use an additional iteration:

    for l in range(1, 5):
        for p in itertools.product(range(3), repeat=l):
            print p
    

    Finally, this works for string elements, too:

    for i in range(5):
        for p in itertools.product(('0', '1', '2'), repeat=i):
            print ''.join(p),
    print
    

    Output:

    0 1 2 00 01 02 10 11 12 20 21 22 000 001 002 010 [...] 2220 2221 2222
    
    0 讨论(0)
  • 2021-01-26 14:28

    Yes, your program could like like this:

    import itertools
    
    
    def perform_test(permutation):
        pass
    
    # permutations() does not construct entire list, but yields 
    # results one by on.
    for permutation in itertools.permutations([1, 2, 3, 4, 5], 2):
        perform_test(permutation)
    
    0 讨论(0)
  • 2021-01-26 14:34

    While there are ways to do this using itertools etc, here is a way that is a bit different from what you would normally do.

    If you were to have a list of these permutations in order, what you would actually have is ternary numbers that represent their place in the list. e.g. list[4] is 11 which is 4 in ternary (3*1+1*1). So you could convert the index value that you want to test into ternary and that would produce the correct value.

    While python can do conversion from an integer to its form in that base (e.g. int("11",3) outputs 4) the reverse is not implicitly implemented. There are lots of implementations out there though. Here is a good one (modified for your case):

    def digit_to_char(digit):
        if digit < 10:
            return str(digit)
        return chr(ord('a') + digit - 10)
    
    def perm(number):
        (d, m) = divmod(number, 3)
        if d > 0:
            return perm(d) + digit_to_char(m)
        return digit_to_char(m)
    

    So if you wanted to find the 20th permutation, you could do perm(20), which would give you 202. So now you can just do a regular loop through the index values that you want. With no storage of big lists in memory.

    permutation = 0
    i = 0
    while len(str(permutation)) < 20:
        permutation = perm(i)
        do_test(permutation)
        i += 1
    
    0 讨论(0)
提交回复
热议问题