interval-tree 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: