fork download
  1. class Node
  2. attr_accessor :value, :left, :right
  3. def initialize(val)
  4. @value = val # ノードが保持する値
  5. @left = nil # 左側のノード
  6. @right = nil # 右側のノード
  7. end
  8.  
  9. # 描画に必要な情報を計算 (内部用)
  10. def render_info(canvas, margin, x, y)
  11. # 左のノードがあれば、そのノード以下の木の横幅が返ってくる
  12. x = @left.render_info(canvas, margin, x, y + 1) + margin if @left
  13.  
  14. # このノードの分の描画に必要な情報を追加
  15. canvas << [x, y, self]
  16.  
  17. # このノードの分の描画に必要な情報を追加
  18. x += @value.to_s.size
  19. x = @right.render_info(canvas, margin, x + margin, y + 1) if @right
  20.  
  21. # 呼び出した親のために横幅を返す
  22. x
  23. end
  24. protected :render_info
  25.  
  26. # render_infoで描画情報を集めて返す (外部用)
  27. def render(margin)
  28. canvas = []
  29. render_info(canvas, margin, 0, 0)
  30. canvas
  31. end
  32. end
  33.  
  34.  
  35. def print_canvas(canvas)
  36. canvas = canvas.sort_by {|x, y, *| [y, x] }
  37.  
  38. last_x = 0
  39. last_y = 0
  40.  
  41. canvas.each do |x, y, node|
  42. text = node.value.to_s
  43.  
  44. if y != last_y
  45. last_x = 0
  46. puts
  47. end
  48.  
  49. print " " * (x - last_x)
  50. print text
  51.  
  52. last_x = x + text.to_s.size
  53. last_y = y
  54. end
  55. puts
  56. end
  57.  
  58. def print_canvas2(canvas)
  59. canvas = canvas.sort_by {|x, y, *| [y, x] }
  60.  
  61. last_x = 0
  62. last_y = 0
  63.  
  64. canvas.each do |x, y, node|
  65. text = node.value.to_s
  66.  
  67. if y != last_y
  68. last_x = 0
  69. puts
  70. end
  71.  
  72. if node.left
  73. ileft = canvas.index {|nx, ny, *| y + 1 == ny && x <= nx } - 1
  74. left_x, * = canvas[ileft]
  75. left_x_end = left_x + node.left.value.to_s.size
  76. print " " * (left_x_end - last_x)
  77. print "_" * (x - left_x_end)
  78. else
  79. print " " * (x - last_x)
  80. end
  81.  
  82. print text
  83.  
  84. x += text.to_s.size
  85.  
  86. if node.right
  87. iright = canvas.index {|nx, ny, *| y + 1 == ny && x <= nx }
  88. right_x, * = canvas[iright]
  89.  
  90. print "_" * (right_x - x)
  91. x = right_x
  92. end
  93.  
  94. last_x = x
  95. last_y = y
  96. end
  97. puts
  98. end
  99.  
  100. def print_canvas3(canvas)
  101. canvas = canvas.sort_by {|x, y, *| [y, x] }
  102. canvas_lines = canvas.group_by {|x, y, *| y }.sort.map {|_, line| line }
  103.  
  104. canvas_lines.each do |line|
  105. slashes = []
  106.  
  107. last_x = 0
  108. line.each do |x, y, node|
  109. text = node.value.to_s
  110.  
  111. if node.left
  112. next_line = canvas_lines[y + 1]
  113. ileft = next_line.index {|nx, *| x <= nx } - 1
  114. left_x, * = next_line[ileft]
  115. left_x_end = left_x + node.left.value.to_s.size
  116. print " " * (left_x_end - last_x)
  117. if left_x_end < x
  118. print " "
  119. print "_" * (x - left_x_end - 1)
  120. slashes << [left_x_end, '/']
  121. end
  122. else
  123. print " " * (x - last_x)
  124. end
  125.  
  126. print text
  127.  
  128. x += text.to_s.size
  129.  
  130. if node.right
  131. next_line = canvas_lines[y + 1]
  132. iright = next_line.index {|nx, *| x <= nx }
  133. right_x, * = next_line[iright]
  134.  
  135. if x < right_x
  136. print "_" * (right_x - x - 1)
  137. print " "
  138. slashes << [right_x - 1, '\\']
  139. end
  140. x = right_x
  141. end
  142.  
  143. last_x = x
  144. end
  145.  
  146. puts
  147.  
  148. last_x = 0
  149. slashes.each do |x, char|
  150. print " " * (x - last_x)
  151. print char
  152. last_x = x + 1
  153. end
  154. puts unless slashes.empty?
  155. end
  156. end
  157.  
  158. # ツリーの宣言を短く書くために定義
  159. def Node(val, left=nil, right=nil)
  160. node = Node.new(val)
  161. node.left = left
  162. node.right = right
  163. node
  164. end
  165.  
  166. tree = Node(9, Node(4, Node(2), Node(6)), Node(15, Node(12), Node(17)))
  167. print_canvas tree.render(0)
  168. print_canvas2 tree.render(0)
  169. print_canvas2 tree.render(3)
  170. print_canvas3 tree.render(1)
  171. print_canvas3 tree.render(2)
  172. print_canvas3 tree.render(3)
  173. print_canvas3 Node(4, tree, tree).render(0)
  174. print_canvas3 Node(4, tree, tree).render(1)
  175. print_canvas3 Node(4, Node(9, tree, nil), tree).render(2)
  176. print_canvas3 Node(4, tree, tree).render(3)
  177.  
Success #stdin #stdout 0.02s 7432KB
stdin
Standard input is empty
stdout
   9
 4    15
2 6 12  17
  _9__
 4    15
2 6 12  17
     _______9________
 ___4___          ___15___
2       6       12        17
    __9___ 
   /      \
  4        15 
 / \      /  \
2   6   12    17
     ____9_____ 
    /          \
  _4_          _15_ 
 /   \        /    \
2     6     12      17
      ______9_______ 
     /              \
  __4__            __15__ 
 /     \          /      \
2       6       12        17
     _____4__ 
    /        \
   9_         9_ 
  /  \       /  \
 4    15    4    15
2 6 12  17 2 6 12  17
        _________4______ 
       /                \
    __9___             __9___ 
   /      \           /      \
  4        15        4        15 
 / \      /  \      / \      /  \
2   6   12    17   2   6   12    17
                          _4__________ 
                         /            \
           _____________9          ____9_____ 
          /                       /          \
     ____9_____                 _4_          _15_ 
    /          \               /   \        /    \
  _4_          _15_           2     6     12      17
 /   \        /    \
2     6     12      17
              _________________4______________ 
             /                                \
      ______9_______                     ______9_______ 
     /              \                   /              \
  __4__            __15__            __4__            __15__ 
 /     \          /      \          /     \          /      \
2       6       12        17       2       6       12        17