interval-tree 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,117 @@
1
+ #!/usr/local/bin/ruby-1.9
2
+ #
3
+ # Title:: the IntervalTree module using "augmented tree"
4
+ # Author:: MISHIMA, Hiroyuki ( https://github.com/misshie ), 2011
5
+ # Copyright:: The MIT/X11 license
6
+ #
7
+ # see also ....
8
+ # description in Wikipedia
9
+ # http://en.wikipedia.org/wiki/Interval_tree
10
+ # implementstion in Python by Tyler Kahn
11
+ # http://forrst.com/posts/Interval_Tree_implementation_in_python-e0K
12
+ #
13
+ # Usage:
14
+ # require "interval_tree"
15
+ # itv = [(0...3), (1...4), (3...5),]
16
+ # t = IntervalTree::Tree.new(itv)
17
+ # p t.search(2) => [0...3, 1...4]
18
+ # p t.search(1...3) => [0...3, 1...4, 3...5]
19
+ #
20
+ # note: result intervals are always returned
21
+ # in the "left-closed and right-open" style that can be expressed
22
+ # by three-dotted Range object literals (first...last)
23
+ #
24
+
25
+ require 'interval-tree-node'
26
+
27
+ module IntervalTree
28
+ class ExclusiveTree
29
+ def initialize(ranges)
30
+ ranges_excl = ensure_exclusive_end([ranges].flatten)
31
+ @top_node = divide_intervals(ranges_excl)
32
+ end
33
+ attr_reader :top_node
34
+
35
+ def divide_intervals(intervals)
36
+ return nil if intervals.empty?
37
+ x_center = center(intervals)
38
+ s_center = Array.new
39
+ s_left = Array.new
40
+ s_right = Array.new
41
+
42
+ intervals.each do |k|
43
+ case
44
+ when k.last < x_center
45
+ s_left << k
46
+ when x_center < k.first
47
+ s_right << k
48
+ else
49
+ s_center << k
50
+ end
51
+ end
52
+ Node.new(x_center, s_center,
53
+ divide_intervals(s_left), divide_intervals(s_right))
54
+ end
55
+
56
+
57
+ def search(interval)
58
+ if interval.respond_to?(:first)
59
+ first = interval.first
60
+ last = interval.last
61
+ else
62
+ first = interval
63
+ last = nil
64
+ end
65
+
66
+ if last
67
+ result = Array.new
68
+ (first...last).each do |j|
69
+ search(j).each{|k|result << k}
70
+ result.uniq!
71
+ end
72
+ result.sort_by{|x|[x.first, x.last]}
73
+ else
74
+ point_search(self.top_node, first, []).sort_by{|x|[x.first, x.last]}
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def ensure_exclusive_end(ranges)
81
+ ranges.map do |range|
82
+ case
83
+ when !range.respond_to?(:exclude_end?)
84
+ range
85
+ when range.exclude_end?
86
+ range
87
+ else
88
+ (range.first ... range.end+1)
89
+ end
90
+ end
91
+ end
92
+
93
+ # augmented tree
94
+ # using a start point as resresentative value of the node
95
+ def center(intervals)
96
+ fs = intervals.sort_by{|x|x.first}
97
+ fs[fs.length/2].first
98
+ end
99
+
100
+ def point_search(node, point, result)
101
+ node.s_center.each do |k|
102
+ result << k if (k.first <= point) && (point < k.last)
103
+ end
104
+ if node.left_node && ( point < node.left_node.s_max )
105
+ point_search(node.left_node, point, []).each{|k|result << k}
106
+ end
107
+ if node.right_node && ( node.right_node.x_center <= point )
108
+ point_search(node.right_node, point, []).each{|k|result << k}
109
+ end
110
+ result.uniq
111
+ end
112
+ end # class Tree
113
+ end # module IntervalTree
114
+
115
+ if __FILE__ == $0
116
+ puts "Interval Tree Library"
117
+ end
@@ -0,0 +1,122 @@
1
+ #!/usr/local/bin/ruby-1.9
2
+ # encoding: utf-8
3
+ #
4
+ # Title:: the InclusiveIntervalTree module using "augmented tree"
5
+ # Author:: MISHIMA, Hiroyuki ( https://github.com/misshie ), 2011
6
+ # Copyright:: The MIT/X11 license
7
+ #
8
+ # see also ....
9
+ # description in Wikipedia
10
+ # http://en.wikipedia.org/wiki/Interval_tree
11
+ # implementstion in Python by Tyler Kahn
12
+ # http://forrst.com/posts/Interval_Tree_implementation_in_python-e0K
13
+ #
14
+ # Usage:
15
+ # require "interval_tree"
16
+ # itv = [(0..2), (1..3), (3..4),]
17
+ # t = InclusiveIntervalTree::Tree.new(itv)
18
+ # p t.search(2) => [0..2, 1..3]
19
+ # p t.search(1..3) => [0..2, 1..3, 3..4]
20
+ #
21
+ # note: result intervals are always returned
22
+ # in the "left-closed and right-closed" style that can be expressed
23
+ # by two-dotted Range object literals (first..last)
24
+ #
25
+
26
+ require 'interval-tree-node'
27
+
28
+ module IntervalTree
29
+ class InclusiveTree
30
+ def initialize(ranges)
31
+ ranges_incl = ensure_inclusive_end([ranges].flatten)
32
+ @top_node = divide_intervals(ranges_incl)
33
+ end
34
+ attr_reader :top_node
35
+
36
+ def divide_intervals(intervals)
37
+ return nil if intervals.empty?
38
+ x_center = center(intervals)
39
+
40
+ s_center = Array.new
41
+ s_left = Array.new
42
+ s_right = Array.new
43
+
44
+ intervals.each do |k|
45
+ case
46
+ when k.last < x_center
47
+ s_left << k
48
+ when x_center < k.first
49
+ s_right << k
50
+ else
51
+ s_center << k
52
+ end
53
+ end
54
+
55
+ Node.new(x_center, s_center, divide_intervals(s_left), divide_intervals(s_right))
56
+ end
57
+
58
+
59
+ def search(interval)
60
+ return [] unless self.top_node
61
+ ret = nil
62
+ if interval.respond_to?(:first)
63
+ first = interval.first
64
+ last = interval.last
65
+ else
66
+ first = interval
67
+ last = nil
68
+ end
69
+
70
+ if last
71
+ result = Array.new
72
+ (interval).each do |j|
73
+ search(j).each{|k|result << k}
74
+ result.uniq!
75
+ end
76
+ ret = result.sort_by{|x|[x.first, x.last]}
77
+ else
78
+ ret = point_search(self.top_node, first, []).sort_by{|x|[x.first, x.last]}
79
+ end
80
+ return ret
81
+ end
82
+
83
+ private
84
+
85
+ def ensure_inclusive_end(ranges)
86
+ ret = []
87
+ ranges.each do |r|
88
+ if r.exclude_end?
89
+ ret << Range.new(r.first, r.last-1)
90
+ else
91
+ ret << r
92
+ end
93
+ end
94
+ ret
95
+ end
96
+
97
+ # augmented tree
98
+ # using a start point as resresentative value of the node
99
+ def center(intervals)
100
+ fs = intervals.sort_by{ |x| x.first}
101
+ fs[fs.length/2].first
102
+ end
103
+
104
+ def point_search(node, point, result)
105
+ raise "error" unless node;
106
+ node.s_center.each do |k|
107
+ result << k if (k.first <= point) && (point <= k.last)
108
+ end
109
+ if point <= node.x_center && node.left_node
110
+ point_search(node.left_node, point, []).each{ |k| result << k}
111
+ end
112
+ if point > node.x_center && node.right_node
113
+ point_search(node.right_node, point, []).each{ |k| result << k}
114
+ end
115
+ result.uniq
116
+ end
117
+ end # class Tree
118
+ end # module IntervalTree
119
+
120
+ if __FILE__ == $0
121
+ puts "Inclusive Interval Tree Library"
122
+ end
@@ -0,0 +1,15 @@
1
+
2
+ module IntervalTree
3
+
4
+ class Node
5
+ def initialize(x_center, s_center, left_node, right_node)
6
+ @x_center = x_center
7
+ @s_center = s_center.sort_by(&:first)
8
+ @s_max = s_center.map(&:last).max
9
+ @left_node = left_node
10
+ @right_node = right_node
11
+ end
12
+ attr_reader :x_center, :s_center, :s_max, :left_node, :right_node
13
+ end # class Node
14
+
15
+ end # module IntervalTree
@@ -0,0 +1,4 @@
1
+
2
+ require 'inclusive-interval-tree'
3
+ require 'exclusive-interval-tree'
4
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interval-tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,14 +9,18 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-06 00:00:00.000000000 Z
12
+ date: 2012-11-12 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: http://wikipedia.com/wiki/Interval_tree
15
15
  email: gam3-pause@gam3.net
16
16
  executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
- files: []
19
+ files:
20
+ - lib/inclusive-interval-tree.rb
21
+ - lib/interval-tree-node.rb
22
+ - lib/interval-tree.rb
23
+ - lib/exclusive-interval-tree.rb
20
24
  homepage: https://github.com/gam3/interval-tree
21
25
  licenses: []
22
26
  post_install_message: