multi_range 0.0.1 → 1.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.
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
- require 'bundler/gem_tasks'
2
- require 'rake/testtask'
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << 'test'
6
- t.libs << 'lib'
7
- t.test_files = FileList['test/**/*_test.rb']
8
- end
9
-
10
- task :default => :test
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -1,14 +1,14 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'bundler/setup'
4
- require 'multi_range'
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require 'irb'
14
- IRB.start
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'multi_range'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup CHANGED
@@ -1,8 +1,8 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install --gemfile=gemfiles/4.2.gemfile
7
-
8
- # Do any other automated setup that you need to do here
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install --gemfile=gemfiles/4.2.gemfile
7
+
8
+ # Do any other automated setup that you need to do here
@@ -1,9 +1,9 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in rails_or.gemspec
4
-
5
- group :test do
6
- gem 'simplecov'
7
- end
8
-
9
- gemspec :path => '../'
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rails_or.gemspec
4
+
5
+ group :test do
6
+ gem 'simplecov'
7
+ end
8
+
9
+ gemspec :path => '../'
@@ -1,10 +1,10 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in rails_or.gemspec
4
-
5
- group :test do
6
- gem 'simplecov'
7
- gem 'minitest', '~> 5.11.3'
8
- end
9
-
10
- gemspec :path => '../'
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rails_or.gemspec
4
+
5
+ group :test do
6
+ gem 'simplecov'
7
+ gem 'minitest', '~> 5.11.3'
8
+ end
9
+
10
+ gemspec :path => '../'
@@ -1,64 +1,143 @@
1
- require 'multi_range/version'
2
- require 'roulette-wheel-selection'
3
-
4
- if not Range.method_defined?(:size)
5
- warn "Please backports Range#size method to use multi_range gem.\n" \
6
- "You can use backports gem and add the following lines to your program:\n" \
7
- "require 'backports/1.9.2/float/infinity'\n" \
8
- "require 'backports/2.0.0/range/size'"
9
- end
10
-
11
- if not Enumerable.method_defined?(:to_h)
12
- warn "Please backports Enumerable#to_h method to use multi_range gem.\n" \
13
- "You can use backports gem and add the following lines to your program:\n" \
14
- "require 'backports/2.1.0/enumerable/to_h'"
15
- end
16
-
17
- class MultiRange
18
- attr_reader :ranges
19
-
20
- def initialize(ranges) # range 要由小到大排序,且各 range 不能重疊
21
- @ranges = ranges
22
- end
23
-
24
- def -(other)
25
- new_ranges = @ranges.clone
26
-
27
- return MultiRange.new(new_ranges) if new_ranges.empty?
28
- return MultiRange.new(new_ranges) if other.min > @ranges.last.max # 大於最大值
29
- return MultiRange.new(new_ranges) if other.max < @ranges.first.min # 小於最小值
30
-
31
- changed_size = 0
32
- @ranges.each_with_index do |range, idx|
33
- next if other.min > range.max # 大於這個 range
34
- break if other.max < range.min # 小於這個 range
35
-
36
- sub_range1 = range.min...other.min
37
- sub_range2 = (other.max + 1)..range.max
38
-
39
- sub_ranges = []
40
- sub_ranges << sub_range1 if sub_range1.any?
41
- sub_ranges << sub_range2 if sub_range2.any?
42
-
43
- new_ranges[idx + changed_size, 1] = sub_ranges
44
- changed_size += sub_ranges.size - 1
45
- break if other.max <= range.max # 沒有超過一個 range 的範圍
46
- end
47
-
48
- return MultiRange.new(new_ranges)
49
- end
50
-
51
- def sample
52
- range = RouletteWheelSelection.sample(@ranges.map{|s| [s, s.size] }.to_h)
53
- return nil if range == nil
54
- return rand(range.max - range.min) + range.min
55
- end
56
-
57
- def size
58
- @ranges.inject(0){|sum, v| sum + v.size }
59
- end
60
-
61
- def any?
62
- @ranges.any?
63
- end
64
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'multi_range/version'
4
+ require 'roulette-wheel-selection'
5
+
6
+ if not Range.method_defined?(:size)
7
+ warn "Please backports Range#size method to use multi_range gem.\n" \
8
+ "You can use backports gem and add the following lines to your program:\n" \
9
+ "require 'backports/1.9.2/float/infinity'\n" \
10
+ "require 'backports/2.0.0/range/size'"
11
+ end
12
+
13
+ if not Enumerable.method_defined?(:to_h)
14
+ warn "Please backports Enumerable#to_h method to use multi_range gem.\n" \
15
+ "You can use backports gem and add the following lines to your program:\n" \
16
+ "require 'backports/2.1.0/enumerable/to_h'"
17
+ end
18
+
19
+ class MultiRange
20
+ INDEX_WITH_DEFAULT = Object.new
21
+
22
+ attr_reader :ranges
23
+
24
+ def initialize(ranges)
25
+ @ranges = ranges.map{|s| s.is_a?(Integer) ? s..s : s }.sort_by(&:begin).freeze
26
+ end
27
+
28
+ def merge_overlaps
29
+ return MultiRange.new([]) if @ranges.size == 0
30
+
31
+ new_ranges = []
32
+ current_range = nil
33
+
34
+ @ranges.each do |range|
35
+ next current_range = range if current_range == nil
36
+ next if range.max <= current_range.max
37
+
38
+ if current_range.max + 1 < range.min
39
+ new_ranges << current_range
40
+ current_range = range
41
+ else
42
+ current_range = current_range.min..range.max
43
+ end
44
+ end
45
+
46
+ new_ranges << current_range
47
+ return MultiRange.new(new_ranges)
48
+ end
49
+
50
+ def -(other)
51
+ if other.is_a?(MultiRange)
52
+ new_multi_range = dup
53
+ other.ranges.each{|range| new_multi_range -= range }
54
+ return new_multi_range
55
+ end
56
+
57
+ new_ranges = @ranges.dup
58
+
59
+ return MultiRange.new(new_ranges) if new_ranges.empty?
60
+ return MultiRange.new(new_ranges) if other.min > @ranges.last.max # 大於最大值
61
+ return MultiRange.new(new_ranges) if other.max < @ranges.first.min # 小於最小值
62
+
63
+ changed_size = 0
64
+ @ranges.each_with_index do |range, idx|
65
+ next if other.min > range.max # 大於這個 range
66
+ break if other.max < range.min # 小於這個 range
67
+
68
+ sub_range1 = range.min...other.min
69
+ sub_range2 = (other.max + 1)..range.max
70
+
71
+ sub_ranges = []
72
+ sub_ranges << sub_range1 if sub_range1.any?
73
+ sub_ranges << sub_range2 if sub_range2.any?
74
+
75
+ new_ranges[idx + changed_size, 1] = sub_ranges
76
+ changed_size += sub_ranges.size - 1
77
+ break if other.max <= range.max # 沒有超過一個 range 的範圍
78
+ end
79
+
80
+ return MultiRange.new(new_ranges)
81
+ end
82
+
83
+ def |(other)
84
+ other_ranges = other.is_a?(MultiRange) ? other.ranges : [other]
85
+ return MultiRange.new(@ranges + other_ranges).merge_overlaps
86
+ end
87
+
88
+ def overlaps?(other)
89
+ multi_range = merge_overlaps
90
+ return multi_range.size != (multi_range - other).size
91
+ end
92
+
93
+ def sample
94
+ range = RouletteWheelSelection.sample(@ranges.map{|s| [s, s.size] }.to_h)
95
+ return nil if range == nil
96
+ return rand(range.max - range.min) + range.min
97
+ end
98
+
99
+ def size
100
+ @ranges.inject(0){|sum, v| sum + v.size }
101
+ end
102
+
103
+ def any?
104
+ @ranges.any?
105
+ end
106
+
107
+ def index_with(default = INDEX_WITH_DEFAULT)
108
+ if block_given?
109
+ fail ArgumentError, 'wrong number of arguments (given 1, expected 0)' if default != INDEX_WITH_DEFAULT
110
+ return map{|s| [s, yield(s)] }.to_h
111
+ end
112
+
113
+ return to_enum(:index_with){ size } if default == INDEX_WITH_DEFAULT
114
+ return map{|s| [s, default] }.to_h
115
+ end
116
+
117
+ def each
118
+ return to_enum(:each){ size } if !block_given?
119
+
120
+ ranges.each do |range|
121
+ range.each{|s| yield(s) }
122
+ end
123
+ end
124
+
125
+ def map
126
+ return to_enum(:map){ size } if !block_given?
127
+ return each.map{|s| yield(s) }
128
+ end
129
+
130
+ def to_a
131
+ each.to_a
132
+ end
133
+
134
+ def min
135
+ range = @ranges.first
136
+ return range.min if range
137
+ end
138
+
139
+ def max
140
+ range = @ranges.last
141
+ return range.max if range
142
+ end
143
+ end
@@ -1,3 +1,5 @@
1
- class MultiRange
2
- VERSION = '0.0.1'
3
- end
1
+ # frozen_string_literal: true
2
+
3
+ class MultiRange
4
+ VERSION = '1.1.0'
5
+ end
@@ -1,43 +1,43 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'multi_range/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = 'multi_range'
8
- spec.version = MultiRange::VERSION
9
- spec.authors = ['khiav reoy']
10
- spec.email = ['mrtmrt15xn@yahoo.com.tw']
11
-
12
- spec.summary = 'Provides cross-rails methods for you to upgrade rails, backport features, create easy-to-maintain gems, and so on.'
13
- spec.description = 'Provides cross-rails methods for you to upgrade rails, backport features, create easy-to-maintain gems, and so on.'
14
- spec.homepage = 'https://github.com/khiav223577/multi_range'
15
- spec.license = 'MIT'
16
-
17
- # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
- # delete this section to allow pushing this gem to any host.
19
- # if spec.respond_to?(:metadata)
20
- # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21
- # else
22
- # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
- # end
24
-
25
- spec.files = `git ls-files -z`.split("\x0").reject{|f| f.match(%r{^(test|spec|features)/}) }
26
- spec.bindir = 'exe'
27
- spec.executables = spec.files.grep(%r{^exe/}){|f| File.basename(f) }
28
- spec.require_paths = ['lib']
29
- spec.metadata = {
30
- 'homepage_uri' => 'https://github.com/khiav223577/multi_range',
31
- 'changelog_uri' => 'https://github.com/khiav223577/multi_range/blob/master/CHANGELOG.md',
32
- 'source_code_uri' => 'https://github.com/khiav223577/multi_range',
33
- 'documentation_uri' => 'https://www.rubydoc.info/gems/multi_range',
34
- 'bug_tracker_uri' => 'https://github.com/khiav223577/multi_range/issues',
35
- }
36
-
37
- spec.add_development_dependency 'bundler', '>= 1.17', '< 3.x'
38
- spec.add_development_dependency 'rake', '>= 10.5.0'
39
- spec.add_development_dependency 'minitest', '~> 5.0'
40
- spec.add_development_dependency 'backports', '~> 3.15.0'
41
-
42
- spec.add_dependency 'roulette-wheel-selection', '~> 1.1.1'
43
- end
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'multi_range/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'multi_range'
8
+ spec.version = MultiRange::VERSION
9
+ spec.authors = ['khiav reoy']
10
+ spec.email = ['mrtmrt15xn@yahoo.com.tw']
11
+
12
+ spec.summary = 'Provides cross-rails methods for you to upgrade rails, backport features, create easy-to-maintain gems, and so on.'
13
+ spec.description = 'Provides cross-rails methods for you to upgrade rails, backport features, create easy-to-maintain gems, and so on.'
14
+ spec.homepage = 'https://github.com/khiav223577/multi_range'
15
+ spec.license = 'MIT'
16
+
17
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
+ # delete this section to allow pushing this gem to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ # end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject{|f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = 'exe'
27
+ spec.executables = spec.files.grep(%r{^exe/}){|f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+ spec.metadata = {
30
+ 'homepage_uri' => 'https://github.com/khiav223577/multi_range',
31
+ 'changelog_uri' => 'https://github.com/khiav223577/multi_range/blob/master/CHANGELOG.md',
32
+ 'source_code_uri' => 'https://github.com/khiav223577/multi_range',
33
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/multi_range',
34
+ 'bug_tracker_uri' => 'https://github.com/khiav223577/multi_range/issues',
35
+ }
36
+
37
+ spec.add_development_dependency 'bundler', '>= 1.17', '< 3.x'
38
+ spec.add_development_dependency 'rake', '>= 10.5.0'
39
+ spec.add_development_dependency 'minitest', '~> 5.0'
40
+ spec.add_development_dependency 'backports', '~> 3.15.0'
41
+
42
+ spec.add_dependency 'roulette-wheel-selection', '~> 1.1.1'
43
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multi_range
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - khiav reoy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-01 00:00:00.000000000 Z
11
+ date: 2020-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler