augmented_interval_tree 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/interval_tree.rb +130 -0
  3. metadata +64 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2591f2d25e1de25e701a3115d5eb647334a67a74
4
+ data.tar.gz: e224077f0534ff854255a2d3ba840278148ac466
5
+ SHA512:
6
+ metadata.gz: 88911836bf22f53b32cb414ec7583ac91bb4dee0c4d72e11af929c8873fc4cc49206d18db427e4c7dca29e5c6b7a1c68ce5bfc3843fadc53f0b05163cf695224
7
+ data.tar.gz: 02dea2fac6b40520bb156cdc429f936c42b8c919e27cd958cec8e3ca9731c422cc8f18d03c6a95e527e991fa13f09a6660400fdb6aae80312f5044e14e646429
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Title:: the IntervalTree module using "augmented tree"
4
+ # Author:: Hiroyuki Mishima, Simeon Simeonov, Carlos Alonso
5
+ # Copyright:: The MIT/X11 license
6
+ #
7
+ # see also ....
8
+ # description in Wikipedia
9
+ # http://en.wikipedia.org/wiki/Interval_tree
10
+ # implementation 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
+ module IntervalTree
25
+
26
+ class Tree
27
+ def initialize(ranges, &range_factory)
28
+ range_factory = lambda { |l, r| (l ... r+1) } unless block_given?
29
+ ranges_excl = ensure_exclusive_end([ranges].flatten, range_factory)
30
+ @top_node = divide_intervals(ranges_excl)
31
+ end
32
+ attr_reader :top_node
33
+
34
+ def divide_intervals(intervals)
35
+ return nil if intervals.empty?
36
+ x_center = center(intervals)
37
+ s_center = Array.new
38
+ s_left = Array.new
39
+ s_right = Array.new
40
+
41
+ intervals.each do |k|
42
+ case
43
+ when k.last < x_center
44
+ s_left << k
45
+ when k.first > x_center
46
+ s_right << k
47
+ else
48
+ s_center << k
49
+ end
50
+ end
51
+ Node.new(x_center, s_center,
52
+ divide_intervals(s_left), divide_intervals(s_right))
53
+ end
54
+
55
+
56
+ def search(interval)
57
+ return nil unless @top_node
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, range_factory)
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_factory.call(range.first, range.end)
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
+ i = intervals.reduce([intervals.first.first, intervals.first.last]) { |acc, int| [[acc.first, int.first].min, [acc.last, int.last].max] }
97
+ i.first + (i.last - i.first) / 2
98
+ end
99
+
100
+ def point_search(node, point, result)
101
+ node.s_center.each do |k|
102
+ if k.include?(point)
103
+ result << k
104
+ end
105
+ end
106
+ if node.left_node && ( point < node.x_center )
107
+ point_search(node.left_node, point, []).each{|k|result << k}
108
+ end
109
+ if node.right_node && ( point >= node.x_center )
110
+ point_search(node.right_node, point, []).each{|k|result << k}
111
+ end
112
+ result.uniq
113
+ end
114
+ end # class Tree
115
+
116
+ class Node
117
+ def initialize(x_center, s_center, left_node, right_node)
118
+ @x_center = x_center
119
+ @s_center = s_center
120
+ @left_node = left_node
121
+ @right_node = right_node
122
+ end
123
+ attr_reader :x_center, :s_center, :left_node, :right_node
124
+ end # class Node
125
+
126
+ end # module IntervalTree
127
+
128
+ if __FILE__ == $0
129
+ puts "This is the Augmented Interval Tree library."
130
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: augmented_interval_tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Hiroyuki Mishima
8
+ - Simeon Simeonov
9
+ - Carlos Alonso
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2015-11-09 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '2.11'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '2.11'
29
+ description: |
30
+ A Ruby implementation of the Augmented Interval Tree data structure.
31
+ See also: http://en.wikipedia.org/wiki/Interval_tree
32
+ email:
33
+ - missy@be.to
34
+ - info@mrcalonso.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - lib/interval_tree.rb
40
+ homepage: https://github.com/misshie/interval-tree
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 2.4.5
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: A Ruby implementation of the Augmented Interval Tree data structure
64
+ test_files: []