两个运算符(+,-)对数组项的所有可能操作
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
变量与原始数组组合之前将您想要的任何排序算法应用于它。
给定一个数组,我想生成一个新数组,其中包含将 +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
变量与原始数组组合之前将您想要的任何排序算法应用于它。