简体   繁体   English

排列列出随机结果

[英]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.有人可以帮忙处理这段代码吗,我需要它来保存一个排列列表和每个排列后的一个数字,并随机打印让我们说其中的 20 个。

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).假设您想要“小鼠”的排列,应该出现 24 行,这应该是代码后半部分(最后 6 行)的输入。 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.使用 sys.stdin 必须将这 24 行添加到计数列表中。每行都有一个数字(1-24),然后随机选择其中的 20 个(导入数学,必须使用随机)。

input is one word, output must be 20 random permutations.输入是一个词,输出必须是 20 个随机排列。

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":单词“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.这意味着对于大字,运行时间比必要的要长得多,本质上是 O(n!)。

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.如果您发现遇到性能问题,则应使用random.choices选择 20 个索引,然后生成与这些索引相对应的那些特定排列。 You'll find math.comb and math.factorial useful for this.你会发现math.combmath.factorial很有用。


For counting repeats, you'll want to replace random.sample with random.choices (to allow repetition), and then use collections.Counter to count them.对于重复计数,您需要将random.sample替换为random.choices (以允许重复),然后使用collections.Counter对其进行计数。

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! n字符的排列有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!我们(从概念上)换掉主角,减去n! permutations we skipped over, and see if this new index value is less than n!我们跳过的排列,看看这个新的索引值是否小于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.然后我们在n-1上重复,依此类推,直到我们构建了整个排列,然后对其余的索引进行此操作。

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(...)) .我使用的索引映射也对应于itertools.permutations的顺序-如果您有[2, 5, 9]indices ,则输出将与list(permutations(...)) ) 的第 2、5 和 9 个元素相同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) .对于小样本量,此实现要快得多,因为它的时间复杂度为O(C * S) - 至少如果您使用足够小的数字,您可以将乘法视为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.如果您需要按排序顺序排列结果,您可以在迭代之前对indices进行排序,结果将按排序顺序返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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