从所有组合的假设列表中获取索引排列的算法?
Algorithm to get permutation from an index from the hypothetical list of all combinations?
我的意思是:
假设我们有 X 种颜色和一个由 16 个正方形组成的 4x4 网格,我们可以为 任何 个具有 任意 颜色的方块。
假设您可以生成所有可能配置的列表,并且算法将它们一个接一个地吐出(configuration#1
,然后是 configuration#2
等等),有没有办法使用数字i
并立即获得 configuration#i
?
(因为存储 1e+16 配置在普通硬件上是不可能的)
而且更重要的是,是否可以使用该算法的逆运算并为其提供一个配置,为此它将 return 一个 i
重新插入时将 return原来的配置?像这样:
int colours[4][4] = GenerateSomeConfig(); // Gets some combination of colours
int i = GetIndex(colours); // This is the main function I was asking about
int colours2[4][4] = GetConfig(i); // This is the reverse of GetIndex()
assert(CompareGridsEqual(colours, colours2)); // This shouldn't break
这些是重复的组合。
总之。让我们稍微简化一下问题。假设我们有 10 种颜色。编号为 0 到 9。让我们也为我们的方块编号,从 1 到 16(或其他。你说 4x4,你的代码说 16x16 但这并不重要)。
您可以使用方框颜色的数量。所以你最终会说:
0 9 6 3
4 7 5 1
0 2 1 7
5 2 3 4
现在你可以把网格变成条纹 - 0 9 6 3 4 7 5 1 0 2 1 7 5 2 3 4
。删除空格,您就有了映射。
要使用不同数量的颜色,请使用不同的基色。不同大小的网格将导致编码数字中的数字位数不同。
你应该能够从这个提示中脱颖而出。我不会编写一个 c++ 实现来匹配你的努力 =P,我认为你应该能够做到。唯一的技术难点是处理任意基数。
正如我在评论中所说,每个生成配置的算法都可以创建一个包装器,将配置转换为整数,反之亦然。
最简单和通用的解决方案是这样的:
config_t GetConfig(size_t index)
{
Generator gen;
for(size_t i = 0; i < index; ++i) gen.GetNextConfig();
return gen.GetNextConfig();
}
size_t GetIndex(const config_t & conf)
{
size_t ret = 0;
Generator gen;
while(gen.GetNext() != conf) ++ret;
return ret;
}
这显然不是很有效的方法,但它表明这是可能的。如果你需要更有效地做到这一点,你可能不得不牺牲通用性并专门为一个生成器实现它。 @luk32 的回答向您展示了一个非常简单的生成器的实现方式,但是当然可以有更复杂的生成器。
我的意思是:
假设我们有 X 种颜色和一个由 16 个正方形组成的 4x4 网格,我们可以为 任何 个具有 任意 颜色的方块。
假设您可以生成所有可能配置的列表,并且算法将它们一个接一个地吐出(configuration#1
,然后是 configuration#2
等等),有没有办法使用数字i
并立即获得 configuration#i
?
(因为存储 1e+16 配置在普通硬件上是不可能的)
而且更重要的是,是否可以使用该算法的逆运算并为其提供一个配置,为此它将 return 一个 i
重新插入时将 return原来的配置?像这样:
int colours[4][4] = GenerateSomeConfig(); // Gets some combination of colours
int i = GetIndex(colours); // This is the main function I was asking about
int colours2[4][4] = GetConfig(i); // This is the reverse of GetIndex()
assert(CompareGridsEqual(colours, colours2)); // This shouldn't break
这些是重复的组合。
总之。让我们稍微简化一下问题。假设我们有 10 种颜色。编号为 0 到 9。让我们也为我们的方块编号,从 1 到 16(或其他。你说 4x4,你的代码说 16x16 但这并不重要)。
您可以使用方框颜色的数量。所以你最终会说:
0 9 6 3
4 7 5 1
0 2 1 7
5 2 3 4
现在你可以把网格变成条纹 - 0 9 6 3 4 7 5 1 0 2 1 7 5 2 3 4
。删除空格,您就有了映射。
要使用不同数量的颜色,请使用不同的基色。不同大小的网格将导致编码数字中的数字位数不同。
你应该能够从这个提示中脱颖而出。我不会编写一个 c++ 实现来匹配你的努力 =P,我认为你应该能够做到。唯一的技术难点是处理任意基数。
正如我在评论中所说,每个生成配置的算法都可以创建一个包装器,将配置转换为整数,反之亦然。
最简单和通用的解决方案是这样的:
config_t GetConfig(size_t index)
{
Generator gen;
for(size_t i = 0; i < index; ++i) gen.GetNextConfig();
return gen.GetNextConfig();
}
size_t GetIndex(const config_t & conf)
{
size_t ret = 0;
Generator gen;
while(gen.GetNext() != conf) ++ret;
return ret;
}
这显然不是很有效的方法,但它表明这是可能的。如果你需要更有效地做到这一点,你可能不得不牺牲通用性并专门为一个生成器实现它。 @luk32 的回答向您展示了一个非常简单的生成器的实现方式,但是当然可以有更复杂的生成器。