给出表达式
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
?
答案 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