繁体   English   中英

通过重复生成所有排列

[英]Generating all permutations with repetition

我们怎么能生成n个的所有可能的排列在那里的任何项目可以重复任意次数,每次拍摄的R(给)不同的项目?

Combinatorics告诉我它们会有n ^ r ,只是想知道如何使用C ++ / python生成它们?

n基数值系统中将您的置换视为r数字。 以000 ... 0开头并将'number'增加1:0000,0001,0002,000(r-1),0010,0011,...

代码很简单。

这是C ++中可能的实现,与标准库函数std :: next_permutation一致

//---------------------------------------------------------------------------
// Variations with repetition in lexicographic order
// k: length of alphabet (available symbols)
// n: number of places
// The number of possible variations (cardinality) is k^n (it's like counting)
// Sequence elements must be comparable and increaseable (operator<, operator++)
// The elements are associated to values 0÷(k-1), max=k-1
// The iterators are at least bidirectional and point to the type of 'max'
template <class Iter>
bool next_variation(Iter first, Iter last, const typename std::iterator_traits<Iter>::value_type max)
{
    if(first == last) return false; // empty sequence (n==0)

    Iter i(last); --i; // Point to the rightmost element
    // Check if I can just increase it
    if(*i < max) { ++(*i); return true; } // Increase this element and return

    // Find the rightmost element to increase
    while( i != first )
       {
        *i = 0; // reset the right-hand element
        --i; // point to the left adjacent
        if(*i < max) { ++(*i); return true; } // Increase this element and return
       }

    // If here all elements are the maximum symbol (max=k-1), so there are no more variations
    //for(i=first; i!=last; ++i) *i = 0; // Should reset to the lowest sequence (0)?
    return false;
} // 'next_variation'

这就是用法:

std::vector<int> b(4,0); // four places initialized to symbol 0
do{
   for(std::vector<int>::const_iterator ib=b.begin(); ib!=b.end(); ++ib)
      {
       std::cout << std::to_string(*ib);
      }
   std::cout << '\n';
  }
while( next_variation(b.begin(), b.end(), 2) ); // use just 0-1-2 symbols

这是一个@ Inspired方法的例子,其中n作为字母表的前三个字母,r = 3:

alphabet = [ 'a', 'b', 'c' ]

def symbolic_increment( symbol, alphabet ):
    ## increment our "symbolic" number by 1
    symbol = list(symbol)
    ## we reverse the symbol to maintain the convention of having the LSD on the "right"
    symbol.reverse()
    place = 0;
    while place < len(symbol):
        if (alphabet.index(symbol[place])+1) < len(alphabet):
            symbol[place] = alphabet[alphabet.index(symbol[place])+1]
            break
        else:
            symbol[place] = alphabet[0];
            place+=1
    symbol.reverse()
    return ''.join(symbol)

permutations=[]
r=3
start_symbol = alphabet[0] * (r)
temp_symbol = alphabet[0] * (r)
while 1:
    ## keep incrementing the "symbolic number" until we get back to where we started
    permutations.append(temp_symbol)
    temp_symbol = symbolic_increment( temp_symbol, alphabet)
    if( temp_symbol == start_symbol ): break

您也可以使用itertools来完成它:

from itertools import product

r=3
for i in xrange(r-1):
    if (i==0):
        permutations = list(product(alphabet, alphabet))
    else:
        permutations = list(product(permutations, alphabet))
    permutations = [ ''.join(item) for item in permutations ]

暂无
暂无

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

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