Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 生成不包括循环旋转的所有置换_C++_Algorithm_Rotation_Permutation - Fatal编程技术网

C++ 生成不包括循环旋转的所有置换

C++ 生成不包括循环旋转的所有置换,c++,algorithm,rotation,permutation,C++,Algorithm,Rotation,Permutation,因此,我需要一个算法来生成不包括循环旋转的数字列表的所有置换(例如,[1,2,3]=[2,3,1]=[3,1,2]) 当序列中至少有一个唯一的数字时,它是相当直接的,取出该唯一的数字,生成剩余数字的所有排列(但对“标准”排列算法进行一点修改),并将唯一的数字添加到前面 为了生成置换,我发现有必要将置换代码更改为: def permutations(done, options) permuts = [] seen = [] for each o in options

因此,我需要一个算法来生成不包括循环旋转的数字列表的所有置换(例如,[1,2,3]=[2,3,1]=[3,1,2])

当序列中至少有一个唯一的数字时,它是相当直接的,取出该唯一的数字,生成剩余数字的所有排列(但对“标准”排列算法进行一点修改),并将唯一的数字添加到前面

为了生成置换,我发现有必要将置换代码更改为:

def permutations(done, options)
    permuts = []
    seen = []
    for each o in options
        if o not in seen
            seen.add(o)
            permuts += permutations(done+o, options.remove(o))
    return permuts
仅使用选项中的每个唯一数字一次意味着您不会获得322次

该算法在没有唯一元素时仍然输出旋转,例如对于[1,1,2,2],它将输出[1,1,2,2]、[1,2,2,1]和[1,2,1,2],前两个是循环旋转

那么,有没有一种有效的算法可以让我生成所有的排列,而不必在之后通过移除循环旋转

如果没有,什么是消除循环旋转的最有效方法


<强>注:这不是使用Python,而是C++(

< P>)。这个解决方案将涉及到一点使用,以及一些好的OLL模式集差异。请记住,查找置换的运行时仍然是O(n!)。我的解决方案也不会在线进行,但可能有一个更优雅的解决方案允许您这样做(并且不涉及
itertools.permutations
)。为此,这是完成任务的简单方法

步骤1:使用给定的第一个元素生成循环的算法。对于列表
[1,1,2,2]
,这将为我们提供
[1,1,2,2],[1,2,2,1],[2,1,1,2],[2,2,1,1]

def rotations(li):
    count = 0
    while count < len(li):
        yield tuple(li)
        li = li[1:] + [li[0]]
        count += 1
第三步:使用生成器为我们提供自己的集合,以及循环(我们想要摆脱的东西)

步骤4:对每个应用设置差异,然后删除循环

perm = perm.difference(cycles)

希望这能帮到你。我愿意接受建议和/或更正。

考虑测试您输出的每个排列,寻找比您得到的排列“词汇上”更早的循环旋转。如果有,不要返回它-它将在其他地方被枚举

选择“唯一”的第一个元素(如果存在)有助于优化。你知道如果你修复了第一个元素,并且它是唯一的,那么你就不可能通过旋转来复制它。另一方面,如果没有这样独特的元素,只需选择出现最少的元素。这样,您只需要检查具有第一个元素的循环旋转。(例如,当您生成[1,2,2,1]时,您只需要检查[1,1,2,2],而不是[2,2,1,1]或[2,1,1,2])


好的,伪代码。。。显然是O(n!),我确信没有比这更聪明的方法了,因为“所有符号都不同”的情况显然必须返回(n-1)!元素

// generate all permutations with count[0] 0's, count[1] 1's...
def permutations(count[])
    if(count[] all zero)
        return just the empty permutation;
    else
        perms = [];
        for all i with count[i] not zero
            r = permutations(copy of count[] with element i decreased);
            perms += i prefixed on every element of r
        return perms;

// generate all noncyclic permutations with count[0] 0's, count[1] 1's...
def noncyclic(count[])
    choose f to be the index with smallest count[f];
    perms = permutations(copy of count[] with element f decreased);
    if (count[f] is 1)
        return perms;
    else
        noncyclic = [];
        for each perm in perms
            val = perm as a value in base(count.length);
            for each occurence of f in perm
                test = perm rotated so that f is first
                tval = test as a value in base(count.length);
                if (tval < val) continue to next perm;
            if not skipped add perm to noncyclic;
        return noncyclic;

// return all noncyclic perms of the given symbols
def main(symbols[])
    dictionary = array of all distinct items in symbols;
    count = array of counts, count[i] = count of dictionary[i] in symbols
    nc = noncyclic(count);
    return (elements of nc translated back to symbols with the dictionary)
//生成计数为[0]0、计数为[1]1的所有置换。。。
def置换(计数[])
如果(计数[]全部为零)
只返回空排列;
其他的
perms=[];
尽管我的计数不是零
r=排列(元素i减少时计数[]的副本);
perms+=i,在r的每个元素上加前缀
回烫;
//生成计数为[0]0,计数为[1]1的所有非循环置换。。。
def非循环(计数[])
选择f作为计数最小的索引[f];
排列=排列(元素f减少时计数[]的副本);
如果(计数[f]为1)
回烫;
其他的
非循环=[];
烫发中的每一次烫发
val=作为基数(count.length)值的perm;
在perm中每次出现f
测试=旋转perm,使f位于第一位
tval=测试作为基准值(计数长度);
如果(tval
对于所有数字都不同的排列,这很简单。假设数字是
1,2,…,n
,然后生成
1,2,…,n-1的所有排列,并将
n
粘贴在前面。这给出了全集模循环旋转的所有置换。例如,使用
n=4
,您可以

4 1 2 3
4 1 3 2
4 2 1 3
4 2 3 1
4 3 1 2
4 3 2 1
这确保
1,2,3,4
的每个排列的某些循环旋转在列表中正好出现一次

对于一般情况,您需要多集的置换(允许重复条目),您可以使用类似的技巧。删除最大字母
n
的所有实例(类似于在上例中忽略
4
),并生成剩余多集的所有排列。下一步是以规范的方式将
n
s放回排列中(类似于上例中将
4
放在开头)


这实际上只是一个查找所有要生成的实例。首先,我将展示我们将使用的容器和算法

#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
#include <iterator>

using std::vector;
using std::set;
using std::sort;
using std::next_permutation;
using std::copy;
using std::ostream_iterator;
using std::cout;
我们需要一个比较对象来检查排列是否为旋转:

struct CompareCyclicPermutationsEqual
{
    bool operator()(const Permutation& lhs, const Permutation& rhs);
};
以及使用循环比较对象的
typedef
a
set

typedef set<Permutation, CompareCyclicPermutationsEqual> Permutations;

我还没有实现
compareCyclePermutationSequal
。另外,当我运行代码时,您需要实现
ostream&operatorHmm,似乎返回
set([(1,2,1,2),(2,1,2,1)]
,而不是(1,1,2,2)和(1,2,1,2)。此外,我更喜欢与python无关的东西,因为我实际上是在C++中编写这篇文章的,不知道为什么会包含python标记。对我来说,这有点误导
typedef vector<unsigned int> Permutation;
struct CompareCyclicPermutationsEqual
{
    bool operator()(const Permutation& lhs, const Permutation& rhs);
};
typedef set<Permutation, CompareCyclicPermutationsEqual> Permutations;
int main()
{
    Permutation permutation = {1, 2, 1, 2};
    sort(permutation.begin(). permutation.end());

    Permutations permutations;

    do {
        permutations.insert(permutation);
    } while(next_permutation(numbers.begin(), numbers.end()))


    copy(permutations.begin(), permutations.end(),
         ostream_iterator<Permutation>(cout, "\n");

    return 0;
}
1, 1, 2, 2,
1, 2, 1, 2,