C++ 生成器,用于带有扭曲的排列减少每个位置

问题描述

我不是数学家,所以我不知道是否有相关术语(我找不到)。

我正在寻找的是 C++ 代码来生成所有排列,重复,但有一点:第一个位置可以有 n-1 作为最高值,第二个位置可以有 n-2 作为最高值等 n-(n...0)。例如。给定 n=3 并允许重复,结果应为:

[0,0]   ✓
[0,1] ✗
[0,2] ✗
[0,1,2,0] ✗
[0,2] ✗
[1,0]   ✓
[1,1] ✗
[1,0] ✗
[1,2] ✗
[2,0]   ✓
[2,1] ✗
[2,0] ✗
[2,2] ✗

所以它就像一个 N 长度的排列列表,重复 ,除了加上每个位置的限制 。这种序列是否有现有的名称或描述?

我可以制作类似递归模式的东西,但我想要一个生成器。仅用于速度目的。这可能比函数更快吗?你会如何处理这个问题?

解决方法

我们可以观察到:

  • 列中的值仅限于列号
  • 索引从右到左
  • 可以通过模除法来进行限制
  • 如果我们有一个下降沿,从这一列的最大值过渡到 0,那么我们需要对下一列做一些事情。我们为此使用了一个利差值
  • 对最右边的列进行特殊处理。它始终为 0,因此始终具有下降沿。将始终设置进位。

难点在于使用从右到左运行的索引。这些间接使代码有点难以阅读。

当然,一如既往。有许多不同的可能解决方案。

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

constexpr size_t MaxFieldWith = 9;

bool nextSpecialPermutation(std::vector<unsigned int>& v) {
    unsigned int carry{};
    const size_t vectorSize = v.size();

    // Iterate over all columns from right to left
    for (size_t i = vectorSize; i > 0; --i) {

        // Corrected index
        size_t index = i - 1;

        // Limiting value for column
        const unsigned int modValue = (vectorSize - i + 1);

        // And the next value for this column,limited
        const unsigned int nextValue = (v[index] + carry) % modValue;

        // Special handling for right most column
        if (i == vectorSize) {
            // In rightmost  column value is always 0 and carry always 1
            carry = 1;
        }
        else {
            // So,now we are not in a rightmost column
            // Detect a falling edge,and if found,set the carry for the next column
            if ((v[index] == (modValue-1)) && nextValue == 0)
                carry = 1;
            else
                carry = 0;
        }
        // Set the resulting value for this column
        v[index] = nextValue;

    }
    // If all is 0 then we are done
    return not std::all_of(v.begin(),v.end(),[](const auto& i) { return i == 0; });
}

int main() {
    // Inform user what to do
    std::cout << "Enter number of columns. Give number >= 2 and <= " << MaxFieldWith << ": ";

    // Get value from user and check,if it is valid
    if (size_t numberOfColumns{}; (std::cin >> numberOfColumns) && (numberOfColumns >= 2) && (numberOfColumns <= MaxFieldWith)) {

        // Create a vector as specified by the user
        std::vector<unsigned int> v(numberOfColumns,0);

        // Get all special permutations
        bool doLoop{ true };
        while (doLoop) {

            // Debug output
            std::copy(v.begin(),std::ostream_iterator<unsigned int>(std::cout," "));
            std::cout << '\n';

            // Get next special permutation
            doLoop = nextSpecialPermutation(v);
        }
    }
    else std::cerr << "\nError. Invalid input!\n";
    return 0;
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...