enumerator-traits-kit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2YyNWIyMmRlYzU1YmVhZDk0YjVlNDljYTdmMmY2ODI4OWYyZDY0Yg==
5
+ data.tar.gz: !binary |-
6
+ ZDg2MmNiMGZlODA5Y2FmMGMxY2E2YjJmZTUyYTI4MTNlYjRjZDMyMQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ OTNiMmY1NzYzZDI2YjcxYzM5YTRjMzJlYzg1MzZhMjVjMjYzNmJmNWVkNzZm
10
+ YjRiYTVkM2RjYmNmMGIwMzFhODZlNzA3OWY4MmMwNDM5MzFmMjBlZjk5YWE3
11
+ OTc3YTI5NzAzZWNjOWJjN2RlNzhmNWFlYjEzZmRjMTJjYzcyZGY=
12
+ data.tar.gz: !binary |-
13
+ ZGI3ZDE2MjE5NzE5YWQ5MDY1NjNlNmMxYjg4NGVkMjA1M2Y2Yzk0Njg1NTE5
14
+ YzllMjI5MmVlMjY4YzAwN2NkNzFjNmQwODM5Mjg1MzA5MjEyNTU4NDUyNDI3
15
+ YzUwYjcwZjU1YmZiZjBjZjg2NWJlNjUwYTQ4NmVhOTE1N2MyMTc=
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in enumerator_traits_kit.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'enumerator-comparable'
8
+ gem 'rake', '>= 10'
9
+ gem 'rspec', '~> 2.12'
10
+ gem 'debugger'
11
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Bill
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # EnumeratorTraitsKit
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'enumerator_traits_kit'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install enumerator_traits_kit
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'enumerator_traits_kit/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "enumerator-traits-kit"
8
+ gem.version = EnumeratorTraitsKit::VERSION
9
+ gem.authors = ["Bill"]
10
+ gem.email = ["bill.burcham@gmail.com"]
11
+ gem.description = %q{a collection of useful Ruby sequence traits and operations}
12
+ gem.summary = %q{Leverages a family of monotonic traits to build an intersection operator (&) on sequences}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_runtime_dependency 'enumerator-traits'
21
+ end
@@ -0,0 +1,4 @@
1
+ require 'enumerator_traits'
2
+ require 'enumerator_traits_kit/version'
3
+ require 'enumerator_traits_kit/monotonic'
4
+ require 'enumerator_traits_kit/initializers'
@@ -0,0 +1 @@
1
+ require_relative 'initializers/enumerator'
@@ -0,0 +1,45 @@
1
+ class Enumerator
2
+
3
+ # Returns a sequence that is the intersection of two sequences.
4
+ # Assumes this sequence (and the other):
5
+ # 1. both produce comparable and orderable objects
6
+ # 2. both sequences are monotonically increasing or monotonically decreasing
7
+ def &(other)
8
+ # we have to be monotonic and we have to already know our direction
9
+ # and we have to agree on our direction
10
+ ensure_trait(EnumeratorTraitsKit::Monotonic)
11
+ other.ensure_trait(EnumeratorTraitsKit::Monotonic)
12
+ raise EnumeratorTraitsKit::MonotonicityConflict \
13
+ if self.direction.nil? || self.direction != other.direction
14
+ direction = self.direction
15
+
16
+ # TODO: make this lazy!
17
+ Enumerator.new do |yielder|
18
+ # Look at front of both sequences
19
+ # allow StopIteration to be raised if either is at end
20
+ mine = self.next
21
+ theirs = other.next
22
+ loop do
23
+ case mine <=> theirs
24
+ when 0
25
+ yielder << mine
26
+ mine = self.next
27
+ theirs = other.next
28
+ when -1
29
+ if direction == EnumeratorTraitsKit::MonotonicIncreasing
30
+ mine = self.next while mine < theirs
31
+ else # direction == MonotonicDecreasing
32
+ theirs = other.next while theirs < mine
33
+ end
34
+ when 1
35
+ if direction == EnumeratorTraitsKit::MonotonicIncreasing
36
+ theirs = other.next while theirs < mine
37
+ else # direction == MonotonicDecreasing
38
+ mine = self.next while mine < theirs
39
+ end
40
+ end # case
41
+ end # loop
42
+ end.declare_trait(direction) # we have same direction as our inputs
43
+ end
44
+
45
+ end
@@ -0,0 +1,95 @@
1
+ # see also Enumerator#declare_trait, ensure_trait
2
+
3
+ module EnumeratorTraitsKit
4
+
5
+ # The intersection operator (&) requires both self and the other sequence
6
+ # to be monotonically increasing and to agree on the direction: either
7
+ # both are monotonically increasing, or both are monotonically decreasing.
8
+ # If they disagree, then intersection will raise this exception.
9
+ class MonotonicityConflict < Exception;end
10
+
11
+
12
+ module Monotonic
13
+ def self.ensure_with; EnsureMonotonic; end
14
+
15
+ def direction; nil; end
16
+ end
17
+
18
+ module MonotonicIncreasing # < Monotonic
19
+ include Monotonic
20
+
21
+ def self.ensure_with; EnsureMonotonicIncreasing; end
22
+
23
+ def direction; MonotonicIncreasing; end
24
+ end
25
+
26
+ module MonotonicDecreasing # < Monotonic
27
+ include Monotonic
28
+
29
+ def self.ensure_with; EnsureMonotonicDecreasing; end
30
+
31
+ def direction; MonotonicDecreasing; end
32
+ end
33
+
34
+ class NonMonotonic < Exception;end
35
+ class NonMonotonicIncreasing < Exception;end
36
+ class NonMonotonicDecreasing < Exception;end
37
+
38
+ # A mixin for an enumerator instance. This enumerator passes through the value stream
39
+ # from the other enumerator while determining the "direction" of the values
40
+ # i.e. monotonically increasing (1) or monotonically decreasing (-1) and throws
41
+ # an exception if the direction changes.
42
+ # Call like: some_enumerator.extend(Enumerator::Monotonic)
43
+ module EnsureMonotonic # < Monotonic
44
+ include Monotonic
45
+
46
+ def next
47
+ super.tap do |val|
48
+ if defined?(@previous)
49
+ case val <=> @previous
50
+ when 1 then new_direction = MonotonicIncreasing
51
+ # when 0 @direction remains undefined
52
+ when -1 then new_direction = MonotonicDecreasing
53
+ end
54
+ if defined?(@direction) && defined?(new_direction)
55
+ raise NonMonotonic,
56
+ "direction changed from #{@direction} to #{new_direction} with value #{val}" \
57
+ if new_direction != @direction
58
+ end
59
+ if defined?(new_direction)
60
+ @direction = new_direction
61
+ end
62
+ end
63
+ @previous = val
64
+ end
65
+ end
66
+
67
+ # nil for unknown/undefined, otherwise 1 or -1
68
+ def direction
69
+ @direction
70
+ end
71
+ end
72
+
73
+ module EnsureMonotonicIncreasing
74
+ include EnsureMonotonic
75
+
76
+ def next
77
+ super.tap do |val|
78
+ raise NonMonotonicIncreasing, "at value #{val}" \
79
+ unless direction == MonotonicIncreasing
80
+ end
81
+ end
82
+ end
83
+
84
+ module EnsureMonotonicDecreasing
85
+ include EnsureMonotonic
86
+
87
+ def next
88
+ super.tap do |val|
89
+ raise NonMonotonicDecreasing, "at value #{val}" \
90
+ unless direction == MonotonicDecreasing
91
+ end
92
+ end
93
+ end
94
+
95
+ end
@@ -0,0 +1,3 @@
1
+ module EnumeratorTraitsKit
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+ require 'enumerator_comparable'
3
+
4
+ describe EnumeratorTraitsKit do
5
+
6
+ def seq(s)
7
+ s.each_char
8
+ end
9
+ def seq_up(s)
10
+ seq(s).declare_trait(EnumeratorTraitsKit::MonotonicIncreasing)
11
+ end
12
+
13
+ describe 'intersection' do
14
+ describe 'empty inputs' do
15
+ let(:a){seq_up('')}
16
+ let(:b){seq_up('')}
17
+ it 'should produce empty intersection' do
18
+ (a & b).should == seq_up('')
19
+ end
20
+ end
21
+ describe 'left empty input' do
22
+ let(:a){seq_up('')}
23
+ let(:b){seq_up('a')}
24
+ it 'should produce empty intersection' do
25
+ (a & b).should == seq_up('')
26
+ end
27
+ end
28
+ describe 'right empty input' do
29
+ let(:a){seq_up('a')}
30
+ let(:b){seq_up('')}
31
+ it 'should produce empty intersection' do
32
+ (a & b).should == seq_up('')
33
+ end
34
+ end
35
+ describe 'non-empty non-intersecting inputs' do
36
+ let(:a){seq_up('ab')}
37
+ let(:b){seq_up('cd')}
38
+ it 'should produce empty intersection' do
39
+ (a & b).should == seq_up('')
40
+ end
41
+ end
42
+ describe 'identical single' do
43
+ let(:a){seq_up('a')}
44
+ let(:b){seq_up('a')}
45
+ it 'should produce "a"' do
46
+ (a & b).should == seq_up('a')
47
+ end
48
+ end
49
+ describe 'identical double' do
50
+ let(:a){seq_up('ab')}
51
+ let(:b){seq_up('ab')}
52
+ it 'should produce "ab"' do
53
+ (a & b).should == seq_up("ab")
54
+ end
55
+ end
56
+ describe 'intersecting double' do
57
+ let(:a){seq_up('ab')}
58
+ let(:b){seq_up('bc')}
59
+ it 'should produce "b"' do
60
+ (a & b).should == seq_up('b')
61
+ end
62
+ end
63
+ describe 'intersecting double' do
64
+ let(:a){seq_up('ab')}
65
+ let(:b){seq_up('bc')}
66
+ it 'should produce "b"' do
67
+ (a & b).should == seq_up('b')
68
+ end
69
+ end
70
+ describe 'repeats' do
71
+ let(:a){seq_up('abb')}
72
+ let(:b){seq_up('aab')}
73
+ it 'should produce "ab"' do
74
+ (a & b).should == seq_up('ab')
75
+ end
76
+ end
77
+ end
78
+
79
+ end
@@ -0,0 +1,44 @@
1
+ require 'ruby-debug'
2
+
3
+ # require 'simplecov'
4
+ # SimpleCov.start do
5
+ # add_group "Calendrical", "lib/calendrical"
6
+ # end
7
+
8
+ $:.unshift(File.join( File.dirname(__FILE__), '../lib'))
9
+
10
+ # http://anti-pattern.com/bundler-setup-vs-bundler-require
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+
14
+ # when we run via plain old "ruby" command instead of "rspec", this
15
+ # line tells ruby to run the examples
16
+ require 'rspec/autorun'
17
+
18
+ # This is the present Ruby Gem: the one we are spec-ing/testing
19
+ require 'enumerator_traits_kit'
20
+
21
+ # Grab all the rspec support files: utility classes, custom matchers etc.
22
+ $LOAD_PATH.unshift(*Dir[File.join( File.dirname(__FILE__), 'support/**')])
23
+
24
+ require 'spec_helper_methods'
25
+
26
+ RSpec.configure do |config|
27
+
28
+ # Run specs in random order to surface order dependencies. If you find an
29
+ # order dependency and want to debug it, you can fix the order by providing
30
+ # the seed, which is printed after each run.
31
+ # --seed 1234
32
+ config.order = "random"
33
+
34
+ # Use color in STDOUT
35
+ config.color_enabled = true
36
+
37
+ # Use color not only in STDOUT but also in pagers and files
38
+ config.tty = true
39
+
40
+ # Use the specified formatter
41
+ config.formatter = :progress # :documentation :progress, :html, :textmate
42
+
43
+ config.include SpecHelperMethods
44
+ end
@@ -0,0 +1,2 @@
1
+ module SpecHelperMethods
2
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enumerator-traits-kit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Bill
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: enumerator-traits
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: a collection of useful Ruby sequence traits and operations
28
+ email:
29
+ - bill.burcham@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - .gitignore
35
+ - Gemfile
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - enumerator_traits_kit.gemspec
40
+ - lib/enumerator_traits_kit.rb
41
+ - lib/enumerator_traits_kit/initializers.rb
42
+ - lib/enumerator_traits_kit/initializers/enumerator.rb
43
+ - lib/enumerator_traits_kit/monotonic.rb
44
+ - lib/enumerator_traits_kit/version.rb
45
+ - spec/lib/enumerator_traits_kit_spec.rb
46
+ - spec/spec_helper.rb
47
+ - spec/spec_helper_methods.rb
48
+ homepage: ''
49
+ licenses: []
50
+ metadata: {}
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 2.0.3
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Leverages a family of monotonic traits to build an intersection operator
71
+ (&) on sequences
72
+ test_files:
73
+ - spec/lib/enumerator_traits_kit_spec.rb
74
+ - spec/spec_helper.rb
75
+ - spec/spec_helper_methods.rb