augmented_interval_tree 0.1.0
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.
- checksums.yaml +7 -0
- data/lib/interval_tree.rb +130 -0
- 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: []
|