fast_interval_tree 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 42b8ee0cf97e339df2d7b54b29291f6a9365eab9bda925a92d935b2c5c23ac47
4
+ data.tar.gz: 90000f00518ca5f3a547e7990f9c57c7a8a72a35929b650f05b511dfa4aab2e1
5
+ SHA512:
6
+ metadata.gz: b4c99025fa3a0071bacc862ae2080e3236ad8052da0ce4556b0cc0db4c241b4a263b5df964e99f222084b3b96d3aa08098cf3197f02578acb2be8b6966da178f
7
+ data.tar.gz: 6756e05df8be87515476355806a0549736512cf1eb1243db7ceeb86c2042d89c2286daababaeae8fbaee97d6baeb63cf18834207fedb9d507458c3aefb539153
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+
2
+ source 'https://rubygems.org'
3
+
4
+ gemspec
@@ -0,0 +1,34 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fast_interval_tree (0.2.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.4.4)
10
+ rake (13.0.1)
11
+ rspec (3.10.0)
12
+ rspec-core (~> 3.10.0)
13
+ rspec-expectations (~> 3.10.0)
14
+ rspec-mocks (~> 3.10.0)
15
+ rspec-core (3.10.0)
16
+ rspec-support (~> 3.10.0)
17
+ rspec-expectations (3.10.0)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.10.0)
20
+ rspec-mocks (3.10.0)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.10.0)
23
+ rspec-support (3.10.0)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ fast_interval_tree!
30
+ rake (~> 13.0.1)
31
+ rspec (~> 3.10)
32
+
33
+ BUNDLED WITH
34
+ 1.17.3
@@ -0,0 +1,70 @@
1
+ # IntervalTree
2
+
3
+ An implementation of the centered interval tree algorithm in Ruby.
4
+
5
+ This is a fork of [https://github.com/misshie/interval-tree] until our (performance related PR)[https://github.com/misshie/interval-tree/pull/8] gets merged.
6
+
7
+ ## See also
8
+
9
+ * description in Wikipedia http://en.wikipedia.org/wiki/Interval_tree
10
+ * an implementation in Python by Tyler Kahn http://forrst.com/posts/Interval_Tree_implementation_in_python-e0K (broken link)
11
+
12
+ ## ChangeLog
13
+
14
+ ### 2020-11-09, contribution by Brendan Weibrecht, Chris Nankervis and Thomas van der Pol
15
+
16
+ * Substantially improved performance when supplied with a large range as the search query.
17
+
18
+ ### 2017-05-12, contribution by Sam Davies ( https://github.com/samphilipd )
19
+
20
+ * User can specify an option in search `unique: false` if s/he wants multiple matches to be returned.
21
+
22
+ ### 2015-11-02, contribution by Carlos Alonso ( https://github.com/calonso )
23
+
24
+ * Improved centering
25
+ * Fixed searching: With some use cases with very large trees, the library fails to find intervals.
26
+ * Added rubygems structure to be able to be pushed as a gem
27
+
28
+ ### 2013-04-06, contribution by Simeon Simeonov ( https://github.com/ssimeonov )
29
+
30
+ * **Range factory**: The current design allows for Range-compatible elements to be added except for the case where `Tree#ensure_exclusive_end` constructs a Range in a private method. In keeping with good design practices of containers such as Hash, this pull requests allows for a custom range factory to be provided to `Tree#initialize` while maintaining perfect backward compatibility.
31
+ Search in empty trees failing
32
+ * Adds a nil guard in `Tree#search` to protect against empty tree searches failing.
33
+ * **Cosmetic improvements**: Language & whitespace in specs, Gemfile addition, and .gitignore update
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ $ gem install fast_interval_tree
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ See spec/interval_tree_spec.rb for details.
44
+
45
+ ```ruby
46
+ require "interval_tree"
47
+
48
+ itv = [(0...3), (1...4), (3...5), (0...3)]
49
+ t = IntervalTree::Tree.new(itv)
50
+ p t.search(2) #=> [0...3, 1...4]
51
+ p t.search(2, unique: false) #=> [0...3, 0...3, 1...4]
52
+ p t.search(1...4) #=> [0...3, 1...4, 3...5]
53
+ ```
54
+
55
+ ## Note
56
+
57
+ Result intervals are always returned
58
+ in the "left-closed and right-open" style that can be expressed
59
+ by three-dotted Range object literals `(first...last)`
60
+
61
+ Two-dotted full-closed intervals `(first..last)` are also accepted and internally
62
+ converted to half-closed intervals.
63
+
64
+ ## Copyright
65
+
66
+ **Author**: MISHIMA, Hiroyuki ( https://github.com/misshie ), Simeon Simeonov ( https://github.com/ssimeonov ), Carlos Alonso ( https://github.com/calonso ), Sam Davies ( https://github.com/samphilipd ), Brendan Weibrecht (https://github.com/ZimbiX), Chris Nankervis (https://github.com/chrisnankervis), Thomas van der Pol (https://github.com/tvanderpol).
67
+
68
+ **Copyright**: (c) 2011-2020 MISHIMA, Hiroyuki; Simeon Simeonov; Carlos Alonsol; Sam Davies; Brendan Weibrecht; Chris Nankervis; Thomas van der Pol
69
+
70
+ **License**: The MIT/X11 license
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require_relative 'lib/interval_tree/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'fast_interval_tree'
9
+ s.version = IntervalTree::VERSION
10
+ s.summary = 'A Ruby implementation of the Centered Interval Tree data structure'
11
+ s.description = <<-END.gsub(/^ {4}/, '')
12
+ A Ruby implementation of the Centered Interval Tree data structure.
13
+ See also: http://en.wikipedia.org/wiki/Interval_tree
14
+ END
15
+ s.authors = ['Hiroyuki Mishima', 'Simeon Simeonov', 'Carlos Alonso', 'Sam Davies', 'Brendan Weibrecht', 'Chris Nankervis', 'Thomas van der Pol']
16
+ s.email = ['brendan@weibrecht.net.au']
17
+ s.files = ['lib/interval_tree.rb']
18
+ s.homepage = 'https://github.com/greensync/interval-tree'
19
+ s.metadata['source_code_uri'] = 'https://github.com/greensync/interval-tree'
20
+ s.license = 'MIT'
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ s.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ Dir.glob('{bin,lib}/**/*') + %w[README.md Gemfile Gemfile.lock Rakefile fast_interval_tree.gemspec]
26
+ end
27
+ s.require_paths = ['lib']
28
+
29
+ s.add_development_dependency 'rspec', '~> 3.10'
30
+ s.add_development_dependency 'rake', '~> 13.0.1'
31
+ end
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module IntervalTree
4
+
5
+ class Tree
6
+ def initialize(ranges, &range_factory)
7
+ range_factory = lambda { |l, r| (l ... r+1) } unless block_given?
8
+ ranges_excl = ensure_exclusive_end([ranges].flatten, range_factory)
9
+ @top_node = divide_intervals(ranges_excl)
10
+ end
11
+ attr_reader :top_node
12
+
13
+ def divide_intervals(intervals)
14
+ return nil if intervals.empty?
15
+ x_center = center(intervals)
16
+ s_center = Array.new
17
+ s_left = Array.new
18
+ s_right = Array.new
19
+
20
+ intervals.each do |k|
21
+ case
22
+ when k.last < x_center
23
+ s_left << k
24
+ when k.first > x_center
25
+ s_right << k
26
+ else
27
+ s_center << k
28
+ end
29
+ end
30
+ Node.new(x_center, s_center,
31
+ divide_intervals(s_left), divide_intervals(s_right))
32
+ end
33
+
34
+ # Search by range or point
35
+ DEFAULT_OPTIONS = {unique: true}
36
+ def search(query, options = {})
37
+ options = DEFAULT_OPTIONS.merge(options)
38
+
39
+ return nil unless @top_node
40
+
41
+ if query.respond_to?(:first)
42
+ result = top_node.search(query)
43
+ options[:unique] ? result.uniq : result
44
+ else
45
+ point_search(self.top_node, query, [], options[:unique])
46
+ end
47
+ .sort_by{|x|[x.first, x.last]}
48
+ end
49
+
50
+ def ==(other)
51
+ top_node == other.top_node
52
+ end
53
+
54
+ private
55
+
56
+ def ensure_exclusive_end(ranges, range_factory)
57
+ ranges.map do |range|
58
+ case
59
+ when !range.respond_to?(:exclude_end?)
60
+ range
61
+ when range.exclude_end?
62
+ range
63
+ else
64
+ range_factory.call(range.first, range.end)
65
+ end
66
+ end
67
+ end
68
+
69
+ # Note: Floors the result
70
+ def center(intervals)
71
+ (
72
+ intervals.map(&:begin).min +
73
+ intervals.map(&:end).max
74
+ ) / 2
75
+ end
76
+
77
+ def point_search(node, point, result, unique = true)
78
+ node.s_center.each do |k|
79
+ if k.include?(point)
80
+ result << k
81
+ end
82
+ end
83
+ if node.left_node && ( point < node.x_center )
84
+ point_search(node.left_node, point, []).each{|k|result << k}
85
+ end
86
+ if node.right_node && ( point >= node.x_center )
87
+ point_search(node.right_node, point, []).each{|k|result << k}
88
+ end
89
+ if unique
90
+ result.uniq
91
+ else
92
+ result
93
+ end
94
+ end
95
+ end # class Tree
96
+
97
+ class Node
98
+ def initialize(x_center, s_center, left_node, right_node)
99
+ @x_center = x_center
100
+ @s_center = s_center
101
+ @left_node = left_node
102
+ @right_node = right_node
103
+ end
104
+ attr_reader :x_center, :s_center, :left_node, :right_node
105
+
106
+ def ==(other)
107
+ x_center == other.x_center &&
108
+ s_center == other.s_center &&
109
+ left_node == other.left_node &&
110
+ right_node == other.right_node
111
+ end
112
+
113
+ # Search by range only
114
+ def search(query)
115
+ search_s_center(query) +
116
+ (query.begin < x_center && left_node&.search(query) || []) +
117
+ (query.end > x_center && right_node&.search(query) || [])
118
+ end
119
+
120
+ private
121
+
122
+ def search_s_center(query)
123
+ s_center.select do |k|
124
+ (
125
+ # k is entirely contained within the query
126
+ (k.begin >= query.begin) &&
127
+ (k.end <= query.end)
128
+ ) || (
129
+ # k's start overlaps with the query
130
+ (k.begin >= query.begin) &&
131
+ (k.begin < query.end)
132
+ ) || (
133
+ # k's end overlaps with the query
134
+ (k.end > query.begin) &&
135
+ (k.end <= query.end)
136
+ ) || (
137
+ # k is bigger than the query
138
+ (k.begin < query.begin) &&
139
+ (k.end > query.end)
140
+ )
141
+ end
142
+ end
143
+ end # class Node
144
+
145
+ end # module IntervalTree
@@ -0,0 +1,3 @@
1
+ module IntervalTree
2
+ VERSION = "0.2.0"
3
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fast_interval_tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Hiroyuki Mishima
8
+ - Simeon Simeonov
9
+ - Carlos Alonso
10
+ - Sam Davies
11
+ - Brendan Weibrecht
12
+ - Chris Nankervis
13
+ - Thomas van der Pol
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+ date: 2020-11-09 00:00:00.000000000 Z
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rspec
21
+ requirement: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3.10'
26
+ type: :development
27
+ prerelease: false
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.10'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 13.0.1
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 13.0.1
47
+ description: |
48
+ A Ruby implementation of the Centered Interval Tree data structure.
49
+ See also: http://en.wikipedia.org/wiki/Interval_tree
50
+ email:
51
+ - brendan@weibrecht.net.au
52
+ executables: []
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - Gemfile
57
+ - Gemfile.lock
58
+ - README.md
59
+ - Rakefile
60
+ - fast_interval_tree.gemspec
61
+ - lib/interval_tree.rb
62
+ - lib/interval_tree/version.rb
63
+ homepage: https://github.com/greensync/interval-tree
64
+ licenses:
65
+ - MIT
66
+ metadata:
67
+ source_code_uri: https://github.com/greensync/interval-tree
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubygems_version: 3.1.4
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: A Ruby implementation of the Centered Interval Tree data structure
87
+ test_files: []