使用 Ruby/Erlang 迭代生成排列,无需递归或堆栈

Posted

技术标签:

【中文标题】使用 Ruby/Erlang 迭代生成排列,无需递归或堆栈【英文标题】:Generate permutations iteratively without recursion or stack with Ruby/Erlang 【发布时间】:2012-01-18 19:28:12 【问题描述】:

我想生成列表的所有排列,但我想在将某些排列添加到堆栈或存储在任何地方之前过滤掉它们。

我将根据一些自定义的临时规则过滤掉排列。

换句话说,我想生成一个大列表(50-300 个元素)的排列列表,但我想在此过程中丢弃大部分生成的排列(我知道完整的数字排列的数量是N!)。

我已经用它的Array.permutation.to_a 尝试了 Ruby,但它看起来在执行过程中维护了一个完整的堆栈,所以我很快就耗尽了内存 (8 GB)。

我也尝试过this Erlang 解决方案,但它的性能似乎与之前的 Ruby 类似。

这个问题有什么定制的解决方案吗?

附:我看过this和this,可惜我不懂C/C++。

【问题讨论】:

您可以使用一种称为“Steinhaus-Johnson-Trotter 算法”的算法通过迭代生成排列:en.wikipedia.org/wiki/… 您链接的第二个问题得到了一个很好的解决方案,应该很容易将其重写为 ruby​​。 听起来你想要的可能不是排列生成的路线,而是列表推导的路线。 TreyE,您能否详细说明一下使用列表推导式? 为什么要担心递归和堆栈?在 Erlang 中,递归是事物的自然顺序。 【参考方案1】:

Ruby 的Array.permutation.to_a 确实生成了一个数组。那就不要使用to_a!它的意思是“排列”。 Array.permutation 给你一个“枚举器”,一个生成器。由于您想丢弃大多数排列,请使用reject

res = [1,2,3,4].permutation(3).reject do |perm|
  perm.first.even? #if this line is true, the perm will be rejected
end

将生成三个元素的所有排列,并拒绝第一个位置为偶数的那些。但是嗯……你见过多少300!是吗?

【讨论】:

谢谢,steenslag!我看过多少300!是:) 在回答前面关于列表推导的问题时,上面的内容非常相似。列表推导可以在许多方面被描述为与过滤器相结合的生成器。 steenslag 上面的定义与 one 非常相似。还 +1 以获得我不知道的出色答案 - 感谢您帮助我了解有关 ruby​​ steenslag 的新知识!

以上是关于使用 Ruby/Erlang 迭代生成排列,无需递归或堆栈的主要内容,如果未能解决你的问题,请参考以下文章

Python3 - 排列组合的迭代

使用 LINQ 生成排列

使用 LINQ 生成排列

在函数的每次迭代中动态更新输入数据帧,无需全局分配

如何迭代 Rust 中序列的所有唯一排列?

为啥迭代置换生成器比递归慢?