【问题标题】:All possible operations with two operators(+, -) on items of an array对数组项使用两个运算符 (+, -) 的所有可能操作
【发布时间】:2016-08-19 17:42:02
【问题描述】:

给定一个数组,我想生成一个新数组,其中包含依次向原始数组的每个项目添加 +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.:数组的长度可以变化。

【问题讨论】:

  • 你看过repeated_permutation方法吗?
  • @sagarpandya82 是的,但这似乎只解决了部分问题,但感谢您的建议。
  • 我已经编辑了你的问题,试图让它更清楚。这是一个很难用语言表达的问题,不是吗?我对这个问题做了很多修改;我希望我已经改进了它。如果我没有,请回滚我的编辑并接受我的道歉。
  • @WayneConrad 感谢您的编辑。实际上,我想让它更通用,因为一次将“n”项结合起来,而在两者之间感到困惑。我应该为没能正确表达而道歉。

标签: ruby math permutation


【解决方案1】:

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

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

【讨论】:

  • 但在这种情况下它正在修改原始数组大小。根据您的预期,预期的数组是:[[2, 2, 3], [1, 3, 3], [1, 2, 4], [0, 2, 3], [1, 1, 3], [1, 2, 2]] 在数组的每个项目上应用 +1-1 并返回结果数组。
  • 嘿,我很抱歉,我认为问题出在我的问题上。让我更新一下。
  • 如果您愿意,可以将 2 参数更改为 3
  • 是的,我也会尝试的。谢谢。
【解决方案2】:

最终编辑:我删除了旧代码,因为它没有达到 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 项或 2 等上,一次最多为数组的长度。在这里,您假设它发生在所有项目上,这也是我被卡住的地方。例如:一次取 1 项应该给出结果数组: [[2, 2, 100], [1, 3, 100], [1, 2, 101], [0, 2, 100], [1 , 1, 100], [1, 2, 99]]
  • 感谢您付出如此多的努力,实际上您更新的代码确实提供了所需的元素,但顺序不正确。例如:当 +1-1 在 [1, 10, 100] 上一次取 2 时应该给出:[[2, 11, 100], [0, 9, 100], [2, 10, 101], [0, 10, 99], [1, 11, 101], [1, 9, 99], [2, 9, 100], [0, 9, 100], [2, 10, 99], [0, 10, 101], [1, 11, 99], [1, 9, 101]]。另外,我真的很想了解你的代码细节,如果你能解释一下。
  • 棘手!这是一项艰巨的任务。你应该看看你的底层数据结构,看看你的设计是否真的是它应该的样子。我更新的代码呢?
  • 是的,效果很好。非常感谢您提供的详细信息。
【解决方案3】:

问题是我想对数组的每个项目执行所有可能的操作(+ 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"

【讨论】:

  • @Abhinay 好的。如果不需要进一步解释,您可以将其标记为答案。
  • 是否可以维持顺序并生成类似的结果,如果+1 在第一项上然后[2, 2, 3] 同样如果-1 然后[0, 2, 3,] 这就是我想要的达到。我问这个是因为它是我希望在每个操作中生成的数组。
  • 顺便说一句,非常感谢您付出额外的努力来提供详细的解决方案。
  • 我不明白“如果在第一项上 +1 则 [2, 2, 3] 同样如果 -1 则 [0, 2, 3,]”。您的意思是按以下顺序 1+1、1+2,然后是 1+1、1-2 和 1-1、1+2 和 1-1、1-2?
  • 别忘了permutationcombination
猜你喜欢
  • 1970-01-01
  • 2016-04-10
  • 1970-01-01
  • 2015-09-01
  • 2017-11-22
  • 2018-06-23
  • 2023-03-10
  • 2016-03-11
  • 1970-01-01
相关资源
最近更新 更多