All solutions you posted are fun. But now it's time for REAL challenge. :)))
'a b c d = 1 2 + and = ='
should be converted to
'a = b = ( c = d and 1 + 2 )'
My program does this.
The final task is: having information about operators priorities,
commutativity/non-commutativity, and associativity type (left or
right)
construct OP_STRENGTH
input = 'a b c d = 1 2 + and = ='
#
OP_STRENGTH = {
:left => {'and'=>-1, '='=>1, '+'=>2, '-'=>2, '*'=>4, '/'=>4},
:right => {'and'=>-1, '='=>0 ,'+'=>2, '-'=>3, '*'=>4, '/'=>5}
}
def parenthesize(triplet, top_op_strength, side)
q = [ [triplet, top_op_strength, side] ]
while !q.empty?
t,top_op_strength,side = q.pop
if t.is_a?(Array)
if OP_STRENGTH[side][t[1]] < top_op_strength
print '( '
q << ')'
end
q << [t[2], OP_STRENGTH[:right][t[1]], :left]
q << t[1]
q << [t[0], OP_STRENGTH[:left][t[1]], :right]
else
print t, ' '
end
end
end
require 'benchmark'
puts Benchmark.measure {
stack = []
input.strip.split.each do |token|
case token
when '*', '+', '/', '-', '=', 'and'
stack << [stack.pop, token, stack.pop].reverse!
else
stack << token
end
end
parenthesize(stack.last, 0, :right)
puts
}
And the second thing.
For inputs
'0 ' + (1..10000).to_a.join(' - ') + ' *'
(1..N).to_a.join(' ') + ' /' * (N-1)
where N = 10000 i have benchmark:
0.282000 0.000000 0.282000
0.313000 0.000000 0.313000