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

All possible operations with two operators(+, -) on items of an array

给定一个数组,我想生成一个新数组,其中包含将 +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 等等的组合。

我最初认为排列可以解决这个问题,但它只给出了样本:[['+', '-'], ['-', '+']],这是显而易见的。

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

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

P.S.: 数组的长度可以变化。

The problem is I want to do all possible operation(either + 1 or - 1) on each item of an array.

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

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"

这有点复杂,但它应该产生所有可能的排列:

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 来执行数学运算。

最终编辑:我删除了旧代码,因为它不符合 OP 的要求。

相同的代码但保持顺序:

代码的思路是创建一个修饰符数组。

对于应该修改的大小为 3 和 1 的数组的示例,第一行代码将使用数组 [[-1, 0, 0], [0, -1, 0], [0, 0, -1], [1, 0, 0], [0, 1, 0], [0, 0, 1]] 填充变量 mod_final。只是一组 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 变量与原始数组组合之前将您想要的任何排序算法应用于它。