```I'm sorry for spamming this list with my inferior solutions. But J
Koppel's approach made me to reconsider my solution, which now
supports custom output format (eg for Arrays), functions with 3+
arity, and functions for which the arity is defined by the last
argument on the stack.

Thomas.

class Quiz148
class << self
def run(args)
iqueue = args.map {|e| e.split(/\s+/)}.flatten
return Quiz148.new(iqueue).process
end
end

def initialize(iqueue)
@iqueue  = iqueue
@depth   = 0
@stack   = []
@ops     = {
'+'     => [10],
'-'     => [10, 2, nil, [[Object, nil], [String,
'(%s)']]],
'*'     => [5],
'/'     => [5],
'%'     => [5],
'<<'    => [3],
'^'     => [5, 2, nil, [[String, '(%s)'],
[Numeric, nil]]],
'**'    => [5, 2, nil, [[String, '(%s)'],
[Numeric, nil]]],
'sqrt'  => [0, 1, '#{op}(#{vals})'],
'binom' => [0, 2, '#{op}(#{vals.join(\', \')})'],
'sum3'  => [0, 3],
'Array' => [0, -1, '[#{vals.join(\', \')}]'],
}
@opnames = @ops.keys
end

def process
@iqueue.each do |token|
if @opnames.include?(token)
op = token
opp, arity, fmt, *patterns  = @ops[op]
case arity
when -1
aop, arity = @stack.pop
when nil
arity = 2
end
case arity
when 1
fmt ||= '#{op}#{vals}'
when 2
fmt ||= '#{vals.join(\' \' + op + \' \')}'
else
fmt ||= '#{op}(#{vals.join(\', \')})'
end
vals = (1..arity).inject([]) {|a, i| a <<
@stack.pop}.reverse
idx  = 0
vals.map! do |aop, val|
if aop
aopp, *aopatterns  = @ops[aop]
if opp > 0 and aopp > opp
val = '(%s)' % val
end
end
patterns.each do |pattern|
p, e = pattern[idx]
if (aop.nil? or aopp > 0) and val.kind_of?(p)
if e
val = e % val
end
break
end
end
idx += 1
val
end
@stack << [op, eval("\"#{fmt}\"")]
else
@stack << [nil, eval(token)]
end
end
# The stack should include only one element here. A check
would
# be necessary.
o, v = @stack.pop
v
end
end

if __FILE__ == \$0
if ARGV.empty?
puts Quiz148.run('2 3 +')                     == '2 + 3'
puts Quiz148.run('56 34 213.7 + * 678 -')     == '56 * (34 +
213.7) - 678'
puts Quiz148.run('1 56 35 + 16 9 - / +')      == '1 + (56 +
35) / (16 - 9)'
puts Quiz148.run('1 2 + 3 4 + +')             == '1 + 2 + 3 +
4'
puts Quiz148.run('1 2 - 3 4 - -')             == '1 - 2 - (3 -
4)'
puts Quiz148.run('1 3 4 - -')                 == '1 - (3 - 4)'
puts Quiz148.run('2 2 ^ 2 ^')                 == '(2 ^ 2) ^ 2'
puts Quiz148.run('2 2 2 ^ ^')                 == '2 ^ 2 ^ 2'
puts Quiz148.run('2 sqrt 2 2 ^ ^')            == 'sqrt(2) ^ 2
^ 2'
puts Quiz148.run('2 3 2 2 ^ ^ sqrt 3 + *')    == '2 * (sqrt(3
^ 2 ^ 2) + 3)'
puts Quiz148.run('2 3 binom 2 2 ^ ^')         == 'binom(2, 3)
^ 2 ^ 2'
puts Quiz148.run('1 2 3 2 2 ^ ^ binom + 3 *') == '(1 +
binom(2, 3 ^ 2 ^ 2)) * 3'
puts Quiz148.run('2 3 2 2 ^ ^ binom')         == 'binom(2, 3 ^
2 ^ 2)'
puts Quiz148.run('1 2 2 binom 3 2 ^ sum3')    == 'sum3(1,
binom(2, 2), 3 ^ 2)'
puts Quiz148.run('1 2 2 binom 3 3 Array')     == '[1, binom(2,
2), 3]'
puts Quiz148.run('1 2 3 3 Array 4 <<')        == '[1, 2, 3] <<
4'
puts Quiz148.run('1 2 3 3 Array 4 2 * <<')    == '[1, 2, 3] <<
(4 * 2)'
else
puts Quiz148.run(ARGV)
end
end

```