master
  1description = <<-DESC
  2Given a binary tree and a number k, your task is to find the sum of tree nodes at level k. 
  3The binary tree is represented by a string tree with the format: (<node-value>(<left subtree>)(<right subtree>)).
  4
  5Example
  6
  7For tree = "(0(5(6()())(14()(9()())))(7(1()())(23()())))" and k = 2, the output should be
  8
  9treeLevelSum(tree, k) = 44.
 10
 11Explanation: The nodes at level 2 are 6, 14, 1, and 23, so the answer is 6 + 14 + 1 + 23 = 44.
 12
 13Input/Output
 14
 15[time limit] 4000ms (rb)
 16[input] string tree
 17
 18A valid string representing a tree.
 19
 20Guaranteed constraints:
 21
 222  tree.length  105.
 23
 24All the values in a given tree are guaranteed to be integers.
 25
 26[input] integer k
 27
 28Guaranteed constraints:
 29
 300  k  105.
 31
 32[output] integer
 33
 34The total sum of all the values at level k in a tree.
 35
 36https://en.wikipedia.org/wiki/S-expression
 37DESC
 38
 39describe "tree_level_sum" do
 40  # parse s-expression
 41  def parse(tokens, values, offset = 0)
 42    struct = []
 43    while offset < tokens.length
 44      if "(" == tokens[offset]
 45        offset, items = parse(tokens, values, offset + 1)
 46        struct << items
 47      elsif ")" == tokens[offset]
 48        break
 49      else
 50        struct << values.shift
 51      end
 52      offset += 1
 53    end
 54
 55    return [offset, struct]
 56  end
 57
 58  def build_tree(string)
 59    tokens = string.gsub("(", " ( ").gsub(")", " ) ").split(" ")
 60    values = string.scan(/\d+/).map(&:to_i)
 61    _, tree = parse(tokens, values, 0)
 62    tree[0]
 63  end
 64
 65  def tree_level_sum(tree, target)
 66    tree = build_tree(tree)
 67    queue = [node: tree, level: 0]
 68    sum = 0
 69    until queue.empty?
 70      top = queue.shift
 71
 72      if top[:level] == target
 73        sum += top[:node][0]
 74      end
 75
 76      left = top[:node][1]
 77      right = top[:node][2]
 78      if left.size > 0
 79        queue.push(node: left, level: top[:level] + 1)
 80      end
 81      if right.size > 0
 82        queue.push(node: right, level: top[:level] + 1)
 83      end
 84    end
 85    sum
 86  end
 87
 88  def tree_level_sum(tree, target)
 89    # ( + level
 90    # ) - level
 91    # if level == target
 92    #   add number to sum
 93    level = -1
 94    sum = 0
 95    tokens = tree.gsub("(", " ( ").gsub(")", " ) ").split(" ")
 96    tokens.each do |token|
 97      if token == "("
 98        level += 1
 99      elsif token == ")"
100        level -= 1
101      elsif level == target
102        sum += token.to_i
103      end
104    end
105    sum
106  end
107
108  <<-EXAMPLE
109       0
110      / \
111     /   \
112    5     7
113   / \   / \
114  6  14 1  23
115       \
116        9
117
118  (0(5(6()())(14()(9()()))) (7(1()())(23()())))
119[0,
120  [ 5,
121    [6, [], [] ],
122    [14, [], [9, [], []]]
123  ],
124  [ 7,
125    [1, [], []],
126    [23, [], []]
127  ]
128]
129level 2: tree[1][1][0] + tree[1][2][0] + tree[2][1][0] + tree[2][2][0] = 44
130  EXAMPLE
131  [
132    {tree: "(0(5(6()())(14()(9()())))(7(1()())(23()())))", k: 2, expected: 44},
133    {tree: "(3(3()())(1()()))", k: 1, expected: 4},
134    {tree: "(0(5(6()())(4()(9()())))(7(1()())(3()())))", k: 2, expected: 14},
135    {tree: "(3()())", k: 0, expected: 3},
136    {tree: "(0(5()())())", k: 1, expected: 5},
137  ].each do |x|
138    it do
139      expect(tree_level_sum(x[:tree], x[:k])).to eql(x[:expected])
140    end
141  end
142end