fast_interval_tree 0.2.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.
@@ -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: []