优化阵列内存使用

时间:2016-02-27 04:50:18

标签: ruby

我目前有一个非常大的排列数组,目前正在使用大量的RAM。这是我当前的代码,应该:

计算除了存在多个“1”或连续存在三个“2”的所有事件。

arr = [*1..3].repeated_permutation(30).to_a;

count = 0

arr.each do |x|
    if not x.join('').include? '222' and x.count(1) < 2
        count += 1
    end
end

print count

所以基本上这会产生一个24,360个元素数组,每个数组都有30个元素。

我试图通过终端运行它,但它实际上通过14GB的RAM吃了,并且没有移动15分钟,所以我不确定这个过程在尝试访问更多RAM时是否冻结或者是否还在计算。

我的问题是:有更快的方法吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

我不确定你试图解决什么问题。如果您的代码只是一个更复杂问题的示例,并且您确实需要以编程方式检查每一个permumation,那么您可能希望尝试lazy

[*1..3].repeated_permutation(30).lazy.each do ||
  # your condition
end

或者你可能想要使嵌套的iteratior非常明确:

[1,2,3].each do |x1|
  [1,2,3].each do |x2|
    [1,2,3].each do |x3|
      # ...
        [1,2,3].each do |x30|
          permutation = [x1,x2,x3, ... , x30]
          # your condition
        end
      end
    end
  end
end

但是我觉得用Ruby enumerables解决这类问题感觉不对。我们来看看你的字符串:

111111111111111111111111111111
111111111111111111111111111112
111111111111111111111111111113
111111111111111111111111111121
111111111111111111111111111122
111111111111111111111111111123
111111111111111111111111111131
...
333333333333333333333333333323
333333333333333333333333333331
333333333333333333333333333332
333333333333333333333333333333

我建议只使用enumerative combinatorics。只需查看模式并分析(或计算)您的情况true的频率。例如,你的字符串中有28个索引可以放置222子字符串,2222子字符串只有27个...如果你放置一个子字符串,那么它有多可能没有{{ 1}}在字符串的其他部分?

我认为你的问题是数学问题,而不是编程问题。

答案 1 :(得分:0)

NB 这是一个不完整的答案,但我认为这个想法可能会推动正确的解决方案。

我可以想到以下方法:让我们将每个排列表示为三元数基数中的值,用零填充:

1 = 000..00001
2 = 000..00002
3 = 000..00010
4 = 000..00011
5 = 000..00012
...

现在考虑我们重申最初的任务,将零视为一个,一个视为三个,两个视为三个。到目前为止一切都很好。

整个排列列表将表示为:

(1..3**30-1).map { |e| x = e.to_s(3).rjust(30, '0') }

现在我们要应用你的条件:

def do_calc permutation_count
(1..3**permutation_count-1).inject do |memo, e|
  x = e.to_s(3).rjust(permutation_count, '0')
  !x.include?('111') && x.count('0') < 2 ? memo + 1 : memo
end

不幸的是,即使是permutation_count == 20,计算也需要5分钟以上,因此可能还需要一些额外的步骤。我会考虑进一步优化。目前我希望这会给你一个提示,让你自己找到好的方法。