简体   繁体   中英

Permutations list random results

Can someone help with this code, i need it to be able to save a list of permutations and a number after each one, and to print random lets say 20 of them.

for now it works only for the first part.. it prints the permutations of a given word, but i don't know hot to incorporate the second half that is commented, it has to do counts and takes random results.

lets say you want the permutations of "mice", there are 24 rows that should appear, that should be the input for the second half of the code(last 6 rows). using sys.stdin these 24 rows have to be added to counts list.. Every row gets a number (1-24) and then 20 of those are chosen randomly (import math, random must be used) as a result.

input is one word, output must be 20 random permutations.

Any advice will be appreciated, thanks.

import sys, re



def gen_permutations(a, n):
 
    if n == 0:
        print(''.join(a))
    else:
        for i in range(n):
            gen_permutations(a, n-1)
            j = 0 if n % 2 == 0 else i
            a[j], a[n] = a[n], a[j]
        gen_permutations(a, n-1)

if len(sys.argv) != 2:
    sys.stderr.write('one argument only\n')
    sys.exit(1)


word = sys.argv[1]

gen_permutations(list(word), len(word)-1)

#counts = {}
#for line in sys.stdin:
#     for word in re.findall(r'[a-z\']+', line.lower()):
#         counts[word] = counts.get(word, 0) + 1
#         for word, count in sorted(counts.items()):
#             print (word, count)



from itertools import permutations
from random import sample

word = ...

perms = sample(list(enumerate(permutations(word))), 20)
for id_val, perm in perms:
    print("".join(perm), id_val)

Output for word "abcd":

bcad 8
bdca 11
cdba 17
cbad 14
acdb 3
adcb 5
abcd 0
dbac 20
dbca 21
cabd 12
abdc 1
bacd 6
cbda 15
cadb 13
badc 7
bdac 10
cdab 16
dcba 23
dcab 22
dacb 19

Note : this (as well as your original implementation) generates all permutations, even those not used in the output. This means for large words, it will take a much longer time to run than necessary, being O(n!) in nature.

If you find that you run into performance issues, instead you should use random.choices to select 20 indices , and then generate corresponding those specific permutations corresponding to those indices. You'll find math.comb and math.factorial useful for this.


For counting repeats, you'll want to replace random.sample with random.choices (to allow repetition), and then use collections.Counter to count them.

from itertools import permutations
from random import choices
from collections import Counter

perms = choices(list(enumerate(permutations(word))), k=20)
counts = Counter(counts)

for perm, count in counts.items():
    print("".join(perm), count)

As an alternative answer, tackling how to approach this problem from a more mathematical perspective:

from math import factorial
from random import sample


def solve(word, count):
    factorials = [factorial(x) for x in range(len(word))][::-1]
    indices = sample(range(factorial(len(word))), count)
    
    output = []
    for index in indices:
        alphabet = list(word)
        result = ""
        for fact in factorials:
            q, index = divmod(index, fact)
            result += alphabet.pop(q)
        output.append(result)
    return output

Example usage

>>> print(solve("abcde", 10))
['bdeca', 'bdcea', 'decba', 'caebd', 'daceb', 'cedba', 'cdbea', 'ebcda', 'decab', 'becad']

The way this work is by first selecting indices of permutations to select, and the computes the permutations associated with those indices. A permutation of n characters has n! permutations, so if our index is larger than that, we are going to need an additional character. We (conceptually) swap out the leading character, subtract the n! permutations we skipped over, and see if this new index value is less than n! - rinse and repeating until it is. We then repeat on n-1 , and so on, until we have built the entire permutation, and then do so for the rest of the indices.

The index mapping I use corresponds to the order of itertools.permutations as well- if you have indices of [2, 5, 9] , the output will be the same as the 2, 5, and 9 'th elements of list(permutations(...)) .

This implementation is much faster for small sample sizes, since its time complexity is O(C * S) - at least if you use small enough numbers that you can treat multiplication as O(1) . Otherwise, that factorial pre-computation will be a non-negligible portion of the time complexity.

If you need your results in sorted order, you can sort indices before iterating, and the results will be returned in sorted order.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM