1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
require "strscan"

# def evaluate(input)
#   while input.include?(?()
#     input = input.gsub(/\((?~[()])+\)/) {|m| evaluate(m[1..-2]) }
#   end

#   # part one
#   # ss = StringScanner.new(input)
#   # n = ss.scan(/\d+/).to_i
#   # until ss.eos?
#   #   case
#   #   when ss.scan(/\s*\+\s*(\d+)/)
#   #     n += ss.captures[0].to_i
#   #   when ss.scan(/\s*\*\s*(\d+)/)
#   #     n *= ss.captures[0].to_i
#   #   else
#   #     fail
#   #   end
#   # end
#   # n

#   while input.include?(?+)
#     input = input.gsub(/\d+\s*\+\s*\d+/) {|m| eval(m) }
#   end
#   while input.include?(?*)
#     input = input.gsub(/\d+\s*\*\s*\d+/) {|m| eval(m) }
#   end
#   input.to_i
# end

def evaluate(input)
  stack = [->(x) { x }]

  ss = StringScanner.new(input)
  until ss.eos?
    ss.scan(/\s*/)
    stack << case
             when n = ss.scan(/\d+/)
               stack.pop[n.to_i]
             when ss.scan(/\+/)
               ->(x) { stack.pop + x }
             when ss.scan(/\*/)
               ->(x) { stack.pop * x }
             when ss.scan(/\(/)
               ->(x) { x }
             when ss.scan(/\)/)
               n = stack.pop
               stack.pop[n]
             else
               fail
             end
  end

  stack.pop
end

p ARGF.read.split("\n").map {|line| evaluate(line) }.sum