在数组项上使用两个运算符(+, - )的所有可能操作

时间:2016-08-19 17:42:02

标签: ruby math permutation

给定一个数组,我想生成一个新数组,其中包含依次为原始数组的每个项添加+1或-1的结果。这很难用语言来解释,所以请看下面的例子。

例如,给定数组

ary = [1,2]

一次在一个项目中添加或减去1时生成的数组应为:

[[1+1, 2], [1-1, 2], [1, 2+1], [1, 2-1]]

同样,一次在两个项目中添加或减去1时产生的数组将是:

[[1+1, 2+1], [1+1, 2-1], [1-1, 2-1], [1-1, 2+1]]

基本上所有关于具有+1 and -1的项目的结果并获得结果数组。几乎是一次性1项目或2一次性项目的组合。

我首先想到排列可以解决这个问题,但它只提供样本:[['+', '-'], ['-', '+']]这很明显。

我不确定是否可以通过应用公式从概率中获取所有样本空间来解决这个问题。

为了达到同样的目的,我应该以编程方式做什么?

P.S。:阵列的长度可以变化。

3 个答案:

答案 0 :(得分:2)

这有点令人费解,但它应该产生所有可能的排列:

numbers = [ 1, 2, 3 ]

operations = [ :+, :- ].repeated_permutation(2).to_a

x = numbers.repeated_permutation(2).to_a.repeated_permutation(2).flat_map do |pair|
  operations.map do |op_pair|
    op_pair.each_with_index.map do |op, i|
      pair[i][0].send(op, pair[i][1])
    end
  end
end

puts x.to_a.inspect
# => [[2, 2], [2, 0], [0, 2], [0, 0], [2, 3], [2, -1], [0, 3], [0, -1], [2, 4], [2, -2], [0, 4], ... ]

这极大地依赖于repeated_permutation方法进行扩展。它还使用send来执行数学运算。

答案 1 :(得分:1)

  

问题是我想对数组的每个项目进行所有可能的操作(+ 1或-1)。

您可以将所有操作放在一个数组中,将数字放在第二个数组中。然后你可以迭代它们来涵盖所有情况:

operations = %i(+ -)
data = [1, 2, 3]

data.each do |x|
  data.each do |y|
    operations.each do |operation|
      p "#{x} #{operation} #{y} = #{x.send(operation, y)}"
    end
  end
end

此脚本将产生以下输出:

"1 + 1 = 2"
"1 - 1 = 0"
"1 + 2 = 3"
"1 - 2 = -1"
"1 + 3 = 4"
"1 - 3 = -2"
"2 + 1 = 3"
"2 - 1 = 1"
"2 + 2 = 4"
"2 - 2 = 0"
"2 + 3 = 5"
"2 - 3 = -1"
"3 + 1 = 4"
"3 - 1 = 2"
"3 + 2 = 5"
"3 - 2 = 1"
"3 + 3 = 6"
"3 - 3 = 0"

如果你想对1进行操作而不是对输入数组中的所有元素进行操作,你可以通过以下方式进行操作:

operations = %i(+ -)
data = [1, 2, 3]

data.each do |x|
  operations.each do |operation|
    p "#{x} #{operation} #{1} = #{x.send(operation, 1)}"
  end
end

将给出:

"1 + 1 = 2"
"1 - 1 = 0"
"2 + 1 = 3"
"2 - 1 = 1"
"3 + 1 = 4"
"3 - 1 = 2"

答案 2 :(得分:1)

最终编辑:我删除了旧代码,因为它没有按照OP的要求进行操作。

相同的代码,但保持顺序:

代码的想法是创建一个修饰符数组。

对于具有应该修改的大小为3和1的元素的数组的示例,第一行代码将使用数组mod_final填充变量[[-1, 0, 0], [0, -1, 0], [0, 0, -1], [1, 0, 0], [0, 1, 0], [0, 0, 1]]。只是一组1,0和-1。然后在最后一步中,我们映射此数组并将其与原始数据一起添加以生成最终输出。

array = [1,10,100]

def combination_plus_minus(array,number)

  # Create an array of modifiers we are going to use:
  mod =  [-1,1].repeated_combination(number).to_a
  # mod = [[-1, -1], [-1, 1], [1, 1]]

  # Fill the rest of the array up with zeros:
  mod_with_fill = mod.map{|x| x + [0]*(array.size-number) }
  # mod_with_fill = [[-1, -1, 0], [-1, 1, 0], [1, 1, 0]]

  # Map each modifier set to every permuation, then combine them all:
  mod_final = mod_with_fill.flat_map{|x| x.permutation(array.size).to_a }.uniq
  # mod_final = [[-1, -1, 0], [-1, 0, -1], [0, -1, -1], [-1, 1, 0], [-1, 0, 1], [1, -1, 0], [1, 0, -1], [0, -1, 1], [0, 1, -1], [1, 1, 0], [1, 0, 1], [0, 1, 1]]


  #Finally take each set and add the numbers of the inital array: 
  mod_final.map{|x| x.zip(array).map{|x| x.reduce(:+) } }

end

p combination_plus_minus array, 2 #=> [[0, 9, 100], [0, 10, 99], [1, 9, 99], [0, 11, 100], [0, 10, 101], [2, 9, 100], [2, 10, 99], [1, 9, 101], [1, 11, 99], [2, 11, 100], [2, 10, 101], [1, 11, 101]] 

如果您对订单不满意,可以在将mod_final变量与原始数组合并之前应用任何排序算法。