我一直在使用來自堆棧溢出的算法:https://stackoverflow.com/a/9650593/4771889 也就是permute2()函數。將移植函數從Python移植到C++
爲了我的目的,我改變了一些東西,它生成了我需要的正確數據。
這裏是我的Python版本:
def permute(list, nextFixable, num, begin, end):
if end == begin + 1:
yield list
else:
for i in range(begin, end):
if nextFixable[list[i]] == num[i]:
nextFixable[list[i]] += 1
num[begin], num[i] = num[i], num[begin]
list[begin], list[i] = list[i], list[begin]
for p in permute(list, nextFixable, num, begin + 1, end):
yield p
list[begin], list[i] = list[i], list[begin]
num[begin], num[i] = num[i], num[begin]
nextFixable[list[i]] -= 1
if __name__ == "__main__":
list = [0, 1, 2]
nextFixable = {0:0, 1:0, 2:0}
num = [0, 0, 0]
for p in permute(list, nextFixable, num, 0, len(list)):
print(p)
我已經簡化了使用一點點那裏給一個基本的例子。
本實施例的輸出是:
[0, 1, 2]
[0, 2, 1]
[1, 0, 2]
[1, 2, 0]
[2, 1, 0]
[2, 0, 1]
由於我的這個實際用途是較長的列表(未瑣碎「0,1,2」)我很喜歡在這裏所使用的發電機的功能(該產量報表)。
問題是Python很慢,我有時需要等幾天才能得到結果。
我不是C++專家,但之前我發現C++比Python更快。所以你可以猜測我接下來做了什麼 - 我試圖用C++(Visual Studio 2015)重寫它。
這就是我想出了:
#include "stdafx.h"
#include <iostream> // for std::cout
#include <vector> // for std::vector
#include <map> // for std::map
// https://blogs.msdn.microsoft.com/vcblog/2014/11/12/resumable-functions-in-c/
#include <experimental/generator>
using namespace std::experimental;
using namespace std;
using std::cout;
using std::vector;
using std::map;
void print(vector<unsigned short> data) {
cout << "[";
for (unsigned short i = 0; i < data.size(); ++i) {
cout << (int)data[i];
if (i < data.size() - 1) {
cout << ", ";
}
}
cout << "]\n";
}
generator<vector<unsigned short>> permute(
vector<unsigned short> list,
map<unsigned short, unsigned short> nextFixable,
vector<unsigned short> num,
unsigned short begin,
unsigned short end
) {
if (end == begin + 1) {
__yield_value list;
}
else {
for (unsigned short i = begin; i < end; ++i) {
if (nextFixable[list[i]] == num[i]) {
nextFixable[list[i]]++;
swap(num[begin], num[i]);
swap(list[begin], list[i]);
for (auto p : permute(list, nextFixable, num, begin + 1, end)) {
__yield_value p;
swap(list[begin], list[i]);
swap(num[begin], num[i]);
nextFixable[list[i]]--;
}
}
}
}
}
int main()
{
vector<unsigned short> list = { 0, 1, 2 };
map<unsigned short, unsigned short> nextFixable = { {0, 0}, {1, 0}, {2, 0} };
vector<unsigned short> num = { 0, 0, 0 };
for (auto p : permute(list, nextFixable, num, 0, (unsigned short)list.size())) {
print(p);
}
// Keep output window open.
std::getchar();
return 0;
}
你可以看到我一直引用https://blogs.msdn.microsoft.com/vcblog/2014/11/12/resumable-functions-in-c/ 這是給我帶來__yield_value功能。 (我認爲這是不可移植的,這對我來說最終確實會成爲一個問題,因爲我更喜歡在linux下運行這個工具,但對於一些早期的實驗來說它確實有用。)
代碼運行良好,但輸出是:
[0, 1, 2]
[0, 2, 1]
[1, 2, 0]
[2, 1, 0]
讓我們比較Python的輸出 - 看來我們有兩條線丟失:
[0, 1, 2] - Yes
[0, 2, 1] - Yes
[1, 0, 2] - Missing
[1, 2, 0] - Yes
[2, 1, 0] - Yes
[2, 0, 1] - Missing
通常在這一點上寫一個SO問題,答案的從我不得不解釋問題跳到我身上。在這種情況下,它沒有。
這是可能的我做了一個不正確的語言假設,我沒有知識來糾正自己。
因此,要解決這個問題 - 爲什麼我的端口從Python到C++的permute()函數不能給我相同的輸出?
[std :: next_permutation](http://en.cppreference.com/w/cpp/algorithm/next_permutation),除非你有令人信服的理由不使用它。 – PaulMcKenzie
@PaulMcKenzie - 謝謝。雖然我聽說過這個,但我確實認爲它會使用基於索引的方法,並且如果相同的int在列表中出現兩次,則會爲我提供重複結果。現在的一個快速測試表明,情況並非如此。他們應該更好地宣傳不重複的東西:)我想這就是「詞彙學」所指的 - woops! – braks
即使有重複,排序和調用'std :: unique'也會刪除'next_permutation'函數中使用的重複項。 – PaulMcKenzie