我想要所有这些组合,但我没有足够的内存。如何释放脚本中的内存?
use strict;
use warnings;
use Algorithm::Combinatorics 'variations_with_repetition';
my @let = qw/ A G C T /;
my @cad = variations_with_repetition(\@let, 24);
print "@$_\n" for @cad;
答案1
解决方案是简单地使用iterators
.通过将结果分配variations_with_repetition
给标量,它会生成一个迭代器,您每次都可以询问该迭代器以获取下一个元素。通过这样做,您不必将整个列表保留在内存中,并且可以立即访问第一个元素。这是一个可爱的概念,叫做惰性求值。这是您的案例的代码:
use strict;
use warnings;
use Algorithm::Combinatorics 'variations_with_repetition';
my @let = qw / A G C T/;
my $cad = variations_with_repetition(\@let,24);
while(my $c = $cad->next)
{
print "@$c\n";
}
请注意,迭代器实际上返回对数组的引用,您必须首先取消引用该数组,然后加入或对其执行任何您喜欢的操作。
测试结果:我无法在我的机器上运行初始代码(内存使用量按预期无限增长),但是使用迭代器,我立即开始获取输出行,而 perl 几乎不消耗任何内存。
答案2
嗯,枚举字母表上的单词(A、G、C、T)与以四为基数进行计数非常相似。知道这一点(删除对 head 的调用;它只是在测试时截断很长的输出):
{ echo 4o; seq 0 $((4 ** 24 - 1)) | sed 's/$/p/'; } | dc | awk '{ printf "%024d\n", $1 }' | tr 0-4 AGCT | head
解释:
echo 4o
是一个命令,指示dc
以四进制输出;seq
要求对 24 位四进制数字涵盖的整个范围进行计数;sed
在每行附加一个p
,要求dc
打印每个数字(记住以四为基数);awk
前置足够的零以使数字打印 24 位;tr
将数字 (0, 1, 2, 3) 转换为字母表 (A, G, C, T)。