如果我们允许用全零填充表格来开始,那么应该可以准确地执行2^n - 1
填充以设置我们想要的 1 位。这可能不会比编写手动循环更快,但它完全没有配置文件。
编辑:
线路std::vector<std::vector<int> > output(n, std::vector<int>(1 << n));
声明一个向量的向量。外层向量的长度为 n,内层向量的长度为2^n
(n 个输入的真值结果数)但我通过使用左移进行幂计算,以便编译器可以插入一个常量而不是调用,例如pow
。在这种情况下n=3
我们最终得到一个 3x8 向量。我以这种方式组织它(而不是通常的 8x3,以行作为第一个索引),因为我们将在输出数据中利用基于列的模式。使用vector
这种方式的构造函数还确保向量向量的每个元素都初始化为 0。因此,我们只需要担心将我们想要的值设置为 1,而无需理会其余的值。
第二组嵌套for
循环只是用于在完成后打印结果数据,没有什么特别的。
第一组 for 循环实现了真正的算法。我们在这里利用输出数据中基于列的模式。对于给定的真值表,最左边的列将有两部分:前半部分全为 0,后半部分全为 1。由于我们预先填充了零,因此将应用从中间向下开始的一半列高的单次填充我们需要的所有 1。第二列将包含行 1/4th 0、1/4th 1、1/4th 0、1/4th 1。因此,两次填充将应用我们需要的所有 1。我们重复此操作,直到到达最右边的列,在这种情况下,每隔一行都是 0 或 1。
我们开始说“我需要一次填充一半的行”(unsigned num_to_fill = 1U << (n - 1);
)。然后我们遍历每一列。第一列从要填充的位置开始,并用 1 填充那么多行。然后我们增加行并将填充大小减少一半(现在我们一次填充 1/4 行,但然后我们跳过空白行并第二次填充)下一列。
例如:
#include <iostream>
#include <vector>
int main()
{
const unsigned n = 3;
std::vector<std::vector<int> > output(n, std::vector<int>(1 << n));
unsigned num_to_fill = 1U << (n - 1);
for(unsigned col = 0; col < n; ++col, num_to_fill >>= 1U)
{
for(unsigned row = num_to_fill; row < (1U << n); row += (num_to_fill * 2))
{
std::fill_n(&output[col][row], num_to_fill, 1);
}
}
// These loops just print out the results, nothing more.
for(unsigned x = 0; x < (1 << n); ++x)
{
for(unsigned y = 0; y < n; ++y)
{
std::cout << output[y][x] << " ";
}
std::cout << std::endl;
}
return 0;
}