如何在数组中实现表达式的操作顺序?

时间:2016-05-20 20:00:19

标签: ruby

给出表达式

1 * 2 / 3 + 4

我正在尝试在实施操作顺序时写出等式的所有可能变体。如:

(1 * 2) / 3) + 4

(1 * (2 / 3)) + 4

这就是我现在所拥有的:

expression = [1.0, "+", 2.0, "+", 3.0, "+", 4.0]
storage = []

exp1 = expression    #Make new object because insert method will overwrite expression object
storage << exp1.insert(0, "((").insert(4, ")").insert(7, ")")

exp1的变化也反映在表达中。我甚至用不同的方法制作它们,但这些变化反映在表达上。

如何保持表达式对象不变?我需要总共配置5次原始表达式,但是当我使用insert时,我很难保持清洁。阅读Ruby文档,insert方法是唯一适合我正在做的方法。

我是否必须使用不同的数据结构来存储除数组之外的1 * 2 / 3 + 4

2 个答案:

答案 0 :(得分:4)

考虑使用expression.dup.insert(0, "((").insert(4, ")").insert(7, ")") ,这样就不会改变原始集:

{{1}}

答案 1 :(得分:2)

<强>代码

def all_equations(expression)
  nums = expression.select { |o| o.kind_of? Numeric }.map(&:to_s)
  ops  = expression.select { |o| o.is_a? String }.uniq
  ops.permutation(ops.size).to_a.map { |ao|
    ([nums.first] + ao.zip(nums[1..-1]).map(&:join)).join }
end

<强>实施例

all_equations [1.0, "*", 2.0, "/", 3.0, "+", 4.0]
  #=> ["1.0*2.0/3.0+4.0", "1.0*2.0+3.0/4.0", "1.0/2.0*3.0+4.0",
  #    "1.0/2.0+3.0*4.0", "1.0+2.0*3.0/4.0", "1.0+2.0/3.0*4.0"]

a = all_equations [1.0, "*", 2.0, "/", 3.0, "+", 4.0, "-", 4.0, "**", 5.0]
  #=> ["1.0*2.0/3.0+4.0-4.0**5.0", "1.0*2.0/3.0+4.0**4.0-5.0",
  #    ...
  #    "1.0*2.0+3.0**4.0/4.0-5.0", "1.0*2.0+3.0**4.0-4.0/5.0",
  #    ...
  #    "1.0**2.0-3.0+4.0*4.0/5.0", "1.0**2.0-3.0+4.0/4.0*5.0"] 
a.size
  #=> 120 

<强>解释

步骤如下。

expression = [1.0, "*", 2.0, "/", 3.0, "*", 3.0] # note `"*"` appears twice
nums = expression.select { |o| o.kind_of? Numeric }.map(&:to_s)
  #=> ["1.0", "2.0", "3.0", "3.0"] 
ops = expression.select { |o| o.is_a? String }
  #=> ["*", "/", "*"]
a = ops.uniq
  #=> ["*", "/"] 
b = a.permutation(a.size)
  #=> #<Enumerator: ["*", "/"]:permutation(2)> 
c = b.to_a
  #=> [["*", "/"], ["/", "*"]] 
c.map { |ao| ([nums.first] + ao.zip(nums[1..-1]).map(&:join)).join }
  #=> ["1.0*2.0/3.0", "1.0/2.0*3.0"] 
仅当uniq包含重复项时,

ops才会生效。

<强>扩展

以下允许对数字进行重新排序。 (我最初认为这是一项要求,这是我提供此修改的唯一原因。)

expression = [1.0, "*", 2.0, "/", 3.0, "+", 4.0]
nums = expression.select { |o| o.kind_of? Numeric }.map(&:to_s)
  #=> ["1.0", "2.0", "3.0", "4.0"] 
ops  = expression.select { |o| o.is_a? String }
  #=> [["*", "/", "+"], ["*", "+", "/"], ["/", "*", "+"],
  #    ["/", "+", "*"], ["+", "*", "/"], ["+", "/", "*"]] 
anums, aops = nums.permutation(nums.size).to_a.uniq, ops.permutation(ops.size).to_a.uniq  
anums
  #=> [["1", "2", "3", "4"], ["1", "2", "4", "3"], ["1", "3", "2", "4"],
  #    ["1", "3", "4", "2"], ["1", "4", "2", "3"], ["1", "4", "3", "2"],
  #    ["2", "1", "3", "4"], ["2", "1", "4", "3"], ["2", "3", "1", "4"],
  #    ["2", "3", "4", "1"], ["2", "4", "1", "3"], ["2", "4", "3", "1"],
  #    ["3", "1", "2", "4"], ["3", "1", "4", "2"], ["3", "2", "1", "4"],
  #    ["3", "2", "4", "1"], ["3", "4", "1", "2"], ["3", "4", "2", "1"],
  #    ["4", "1", "2", "3"], ["4", "1", "3", "2"], ["4", "2", "1", "3"],
  #    ["4", "2", "3", "1"], ["4", "3", "1", "2"], ["4", "3", "2", "1"]] 
aops
  #=> [["*", "/", "+"], ["*", "+", "/"], ["/", "*", "+"],
  #    ["/", "+", "*"], ["+", "*", "/"], ["+", "/", "*"]]

a = anums.product(aops).map { |an,ao|
  ([an.first] + ao.zip(an[1..-1]).map(&:join)).join }
  #=> ["1*2/3+4", "1*2+3/4", "1/2*3+4",..., "4/3+2*1", "4+3*2/1", "4+3/2*1"] 
a.size
  #=> 144