cartesian 0.5.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/History.txt ADDED
@@ -0,0 +1,42 @@
1
+ === 0.5.0 2011-01-03
2
+
3
+ * 1 major enhancements:
4
+ * Workaround for weird splat behaviour on Ruby <= 1.8.7, so now all tests (100% coverage)
5
+ now run with 100% pass with the following Ruby versions:
6
+ * MRI 1.8.6-p399, 1.8.7-p22, 1.8.7-p330, 1.9.1-p378, and 1.9.2-p136
7
+ * JRuby 1.5.3, 1.5.5, and 1.5.6
8
+ * Ruby Enterprise Edition 1.8.7-2010.02
9
+ * rubinius 1.2.0
10
+
11
+ * 5 minor enhancements:
12
+ * gem "renamed" (changed from Cartesian to cartesian)
13
+ * removed unused alias to CartesianIterator#to_a method (#to_ary)
14
+ * removed own #to_a implementation
15
+ + #to_a and others are now provided by Enumerable mixin
16
+ * removed unused Iterable#start alias for #restart (conflicted with Array#start provided by Rubinius)
17
+ * now build with newgem 1.5.3
18
+
19
+ === 0.4.1 04-11-2008 03:18
20
+
21
+ * 1 major enhancement:
22
+ * mainly bugfixes and some refactoring. new features: left_product and non-destructive #product methods
23
+
24
+ === 0.3.0 29-10-2007 05:49
25
+
26
+ [undocumented changes]
27
+
28
+ === 0.2.3 13-01-2007 20:50
29
+
30
+ * 1 minor enhancement:
31
+ * power! (aliased as "**") method added
32
+
33
+ === 0.2.1 13-01-2007 01:44
34
+
35
+ * 1 major enhancement:
36
+ * Method ".x(enum)" added, which has constant memory requirements, in contrast with the exponential memory usage of the conventional approach.
37
+
38
+ === 0.1.0 24-11-2006 05:35
39
+
40
+ * 1 major enhancement:
41
+ * first public release
42
+
data/Manifest.txt ADDED
@@ -0,0 +1,25 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ Wishlist.txt
7
+ config/hoe.rb
8
+ config/requirements.rb
9
+ lib/cartesian.rb
10
+ lib/cartesian/grid_search.rb
11
+ lib/cartesian/version.rb
12
+ lib/cartesian_iterator.rb
13
+ lib/grid_search.rb
14
+ lib/recursive.rb
15
+ script/console
16
+ script/destroy
17
+ script/generate
18
+ test/benchmark.rb
19
+ test/extensions.rb
20
+ test/test_cartesian.rb
21
+ test/test_cartesian_iterator.rb
22
+ test/test_extensions.rb
23
+ test/test_grid_search.rb
24
+ test/test_helper.rb
25
+ test/test_suite.rb
data/PostInstall.txt ADDED
@@ -0,0 +1,7 @@
1
+
2
+ For more information on cartesian, see http://cartesian.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
data/README.rdoc ADDED
@@ -0,0 +1,81 @@
1
+ = cartesian
2
+
3
+ * http://github.com/adrianomitre/cartesian
4
+
5
+ == DESCRIPTION:
6
+
7
+ Provides methods for the calculation of the cartesian producted between two
8
+ or more enumerable objects. Includes grid search optimization methods.
9
+ It can also be easily and conveniently mixed in into any enumerable class.
10
+
11
+ == FEATURES:
12
+
13
+ The module is automatically mixed in Array class, but the names of the methods for mixin are different.
14
+
15
+ Module:
16
+ Cartesian::product(foo, bar)
17
+ Mixin:
18
+ foo.cartesian( bar )
19
+
20
+ == SYNOPSIS:
21
+
22
+ One can use the Cartesian module directly
23
+ require 'cartesian'
24
+ foo = [1, 2]
25
+ bar = ["a", "b"]
26
+ Cartesian::product(foo, bar) #=> [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]
27
+
28
+ or use the methods provided by the mixin in the Array classees
29
+ require 'cartesian'
30
+ foo = [1, 2]
31
+ bar = ["a", "b"]
32
+ foo.cartesian(bar) #=> [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]
33
+
34
+ which include the short and sweet _x_ method
35
+ v = [] #=> []
36
+ for a,b in [1,2].x [3,4]
37
+ v << [a,b]
38
+ end #=> true
39
+ v #=> [[1, 3], [1, 4], [2, 3], [2, 4]]
40
+
41
+ The '**' operator provides a convenient way of iterating multi-dimensionally over the same array or range
42
+ v = [0,1]**3 #=> #<CartesianIterator:0x7f2fb8e54978 @tot_iter=8, @lists=[[0, 1], [0, 1], [0, 1]]>
43
+ v.to_a #=> [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
44
+
45
+ Finally, the grid search methods
46
+ require 'grid_search'
47
+ [-1, 0, 1, 2].argmax {|x| x**2 } #=> 2
48
+ [-1, 0, 1, 2].argmin {|x| x.abs } #=> 0
49
+
50
+ == REQUIREMENTS:
51
+
52
+ * None, besides the Ruby interpreter and standard library. This gems was successfully tested on all relevant Ruby versions: MRI/YARV, JRuby, Rubinius, and REE. For details, see History.txt.
53
+
54
+ == INSTALL:
55
+
56
+ * sudo gem install cartesian
57
+
58
+ == LICENSE:
59
+
60
+ (The MIT License)
61
+
62
+ Copyright (c) 2011 Adriano Mitre <adriano.mitre@gmail.com>
63
+
64
+ Permission is hereby granted, free of charge, to any person obtaining
65
+ a copy of this software and associated documentation files (the
66
+ 'Software'), to deal in the Software without restriction, including
67
+ without limitation the rights to use, copy, modify, merge, publish,
68
+ distribute, sublicense, and/or sell copies of the Software, and to
69
+ permit persons to whom the Software is furnished to do so, subject to
70
+ the following conditions:
71
+
72
+ The above copyright notice and this permission notice shall be
73
+ included in all copies or substantial portions of the Software.
74
+
75
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
76
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
77
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
78
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
79
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
80
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
81
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/cartesian'
6
+
7
+ Hoe.plugin :newgem
8
+ # Hoe.plugin :website
9
+ # Hoe.plugin :cucumberfeatures
10
+
11
+ # Generate all the Rake tasks
12
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
13
+ $hoe = Hoe.spec 'cartesian' do
14
+ self.developer 'Adriano Mitre', 'adriano.mitre@gmail.com'
15
+ self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
16
+ self.rubyforge_name = self.name # TODO this is default value
17
+ # self.extra_deps = [['activesupport','>= 2.0.2']]
18
+
19
+ end
20
+
21
+ require 'newgem/tasks'
22
+ Dir['tasks/**/*.rake'].each { |t| load t }
23
+
24
+ # TODO - want other tests/tasks run by default? Add them to the list
25
+ # remove_task :default
26
+ # task :default => [:spec, :features]
data/Wishlist.txt ADDED
@@ -0,0 +1 @@
1
+ * Release GridSearch as a separate, independent gem. Note that 'lib/grid_search.rb' is already independent.
data/config/hoe.rb ADDED
@@ -0,0 +1,81 @@
1
+ require 'cartesian/version'
2
+
3
+ AUTHOR = 'Adriano Mitre' # can also be an array of Authors
4
+ EMAIL = "adriano@mitre.com.br"
5
+ DESCRIPTION = <<EOS
6
+ Provides methods for the calculation of the cartesian producted between two
7
+ or more enumerable objects. Includes grid search optimization methods.
8
+ It can also be easily and conveniently mixed in into any enumerable class.
9
+ EOS
10
+ GEM_NAME = 'cartesian' # what ppl will type to install your gem
11
+ RUBYFORGE_PROJECT = 'cartesian' # The unix name for your project
12
+ HOMEPATH = "http://adrianomitre.github.com/cartesian/website/index.html"
13
+ DOWNLOAD_PATH = "https://github.com/adrianomitre/cartesian/archives/master"
14
+ EXTRA_DEPENDENCIES = [
15
+ # ['activesupport', '>= 1.3.1']
16
+ ] # An array of rubygem dependencies [name, version]
17
+
18
+ @config_file = "~/.rubyforge/user-config.yml"
19
+ @config = nil
20
+ RUBYFORGE_USERNAME = "unknown"
21
+ def rubyforge_username
22
+ unless @config
23
+ begin
24
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
25
+ rescue
26
+ puts <<-EOS
27
+ ERROR: No rubyforge config file found: #{@config_file}
28
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
29
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
30
+ EOS
31
+ exit
32
+ end
33
+ end
34
+ RUBYFORGE_USERNAME.replace @config["username"]
35
+ end
36
+
37
+
38
+ REV = nil
39
+ # UNCOMMENT IF REQUIRED:
40
+ # REV = YAML.load(`svn info`)['Revision']
41
+ VERS = Cartesian::VERSION::STRING + (REV ? ".#{REV}" : "")
42
+ RDOC_OPTS = ['--quiet', '--title', 'cartesian documentation',
43
+ "--opname", "index.html",
44
+ "--line-numbers",
45
+ "--main", "README",
46
+ "--inline-source"]
47
+
48
+ class Hoe
49
+ def extra_deps
50
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
51
+ @extra_deps
52
+ end
53
+ end
54
+
55
+ # Generate all the Rake tasks
56
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
57
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
58
+ p.developer(AUTHOR, EMAIL)
59
+ p.description = DESCRIPTION
60
+ p.summary = DESCRIPTION
61
+ p.url = HOMEPATH
62
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
63
+ p.test_globs = ["test/**/test_*.rb", "test/**/tc_*.rb"]
64
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
65
+
66
+ #~ p.files = FileList["{tests,lib}/**/*"].exclude("rdoc").to_a
67
+
68
+
69
+ # == Optional
70
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
71
+ #p.extra_deps = EXTRA_DEPENDENCIES
72
+
73
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
74
+ p.spec_extras = {:files => FileList["{tests,lib}/**/*"].exclude("rdoc").to_a}
75
+ end
76
+
77
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
78
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
79
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
80
+ $hoe.rsync_args = '-av --delete --ignore-errors'
81
+ #~ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
data/lib/cartesian.rb ADDED
@@ -0,0 +1,166 @@
1
+ #
2
+ # The CartesianProduct module provide methods for the calculation
3
+ # of the cartesian producted between two enumerable objects.
4
+ #
5
+ # It can also be easily mixed in into any enumerable class,
6
+ # i.e. any class with Enumerable module mixed in.
7
+ # Notice that the names of the methods for mixin are different.
8
+ #
9
+ # Module:
10
+ # Cartesian::product(foo, bar)
11
+ #
12
+ # Mixin:
13
+ # foo.cartesian( bar )
14
+ #
15
+ # The module is automatically mixed in Array class.
16
+ #
17
+ # == Author
18
+ # Adriano MITRE <adriano.mitre@gmail.com>
19
+ #
20
+ # == Example
21
+ #
22
+ # as module
23
+ # require 'cartesian'
24
+ # foo = [1, 2]
25
+ # bar = ["a", "b"]
26
+ # Cartesian::product(foo, bar) #=> [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]
27
+ # as mixin
28
+ # require 'cartesian'
29
+ # foo = [1, 2]
30
+ # bar = ["a", "b"]
31
+ # foo.cartesian(bar) #=> [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]
32
+ #
33
+
34
+ $:.unshift(File.dirname(__FILE__)) unless
35
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
36
+
37
+ require 'cartesian_iterator'
38
+
39
+ module Cartesian
40
+
41
+ VERSION = '0.5.0'
42
+
43
+ # Produces the cartesian product of self and other.
44
+ # The result is an array of pairs (i.e. two-element arrays).
45
+ #
46
+ # Cartesian::product( [1,2], %w(A B) ) #=> [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
47
+ #
48
+ # or, if mixed in into Array,
49
+ #
50
+ # [1,2].cartesian %w(A B) #=> [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
51
+ #
52
+ def Cartesian.product(first, second)
53
+ first.x(second).to_a
54
+ end
55
+
56
+ # Behaves as product, except for the elements are joined.
57
+ #
58
+ # Cartesian::joined_cartesian( [1,2], %w(A B) ) #=> ["1A", "1B", "2A", "2B"]
59
+ #
60
+ # or, if mixed in into Array,
61
+ #
62
+ # [1,2].joined_cartesian %w(A B) #=> ["1A", "1B", "2A", "2B"]
63
+ #
64
+ def Cartesian.joined_product(first, second)
65
+ product(first, second).map {|pair| pair.join }
66
+ end
67
+
68
+ # Cartesian.joined_product for mixin.
69
+ #
70
+ def joined_cartesian(other)
71
+ Cartesian.joined_product(self, other)
72
+ end
73
+
74
+ # Convenient way of iterating over the elements.
75
+ # Preferable when the cartesian product array
76
+ # is not needed, for the consumption of memory
77
+ # is fixed and very small, in contrast with the
78
+ # exponential memory requirements of the
79
+ # conventional approach.
80
+ #
81
+ # for row, col in (1..10).x(1..30)
82
+ # Matrix[row, col] = row**2 + col**3
83
+ # end
84
+ #
85
+ # Of course, calls can be chained as in
86
+ #
87
+ # for x, y, z in (1..10).x(1..10).x(1..10)
88
+ # # ... do something ...
89
+ # end
90
+ #
91
+ #--
92
+ # for letter, number in %w{a b c}.x(1..3)
93
+ # ... do something ...
94
+ # end
95
+ #++
96
+ #
97
+ # Beware that both +self+ and +other+ must implement
98
+ # +to_a+, i.e., be convertible to array.
99
+ #
100
+ def x(other)
101
+ case other
102
+ when CartesianIterator
103
+ other.left_product(self)
104
+ else
105
+ CartesianIterator.new(self, other)
106
+ end
107
+ end
108
+ alias cartesian x
109
+ alias right_product x
110
+
111
+ def left_product(other)
112
+ case other
113
+ when CartesianIterator
114
+ other.right_product(self)
115
+ else
116
+ CartesianIterator.new(other, self)
117
+ end
118
+ end
119
+
120
+ # Concise way of iterating multi-dimensionally
121
+ # over the same array or range.
122
+ #
123
+ # For instance,
124
+ #
125
+ # for x,y,z in [0,1]**3
126
+ # puts [x, y, z].join(',')
127
+ # end
128
+ #
129
+ # produces the following output
130
+ #
131
+ # 0,0,0
132
+ # 0,0,1
133
+ # 0,1,0
134
+ # 0,1,1
135
+ # 1,0,0
136
+ # 1,0,1
137
+ # 1,1,0
138
+ # 1,1,1
139
+ #
140
+ # It also works with Range objects.
141
+ #
142
+ def **(fixnum)
143
+ if fixnum < 0
144
+ raise ArgumentError, "negative power"
145
+ elsif fixnum == 0
146
+ return []
147
+ elsif fixnum == 1
148
+ return self
149
+ else
150
+ iter = CartesianIterator.new(self, self)
151
+ (fixnum-2).times do
152
+ iter.product!(self)
153
+ end
154
+ iter
155
+ end
156
+ end
157
+ alias :power! :**
158
+ end
159
+
160
+ class Array
161
+ include Cartesian
162
+ end
163
+
164
+ class Range
165
+ include Cartesian
166
+ end
@@ -0,0 +1,10 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..'))
2
+
3
+ require 'cartesian'
4
+ require 'grid_search'
5
+
6
+ class CartesianIterator
7
+ include GridSearch
8
+ end
9
+
10
+
@@ -0,0 +1,9 @@
1
+ module Cartesian #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 5
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,99 @@
1
+ class CartesianIterator
2
+
3
+ def initialize(foo, bar)
4
+ @lists = []
5
+ @tot_iter = 1
6
+ product!(foo)
7
+ product!(bar)
8
+ end
9
+
10
+ def dup
11
+ Marshal.load(Marshal.dump(self))
12
+ end
13
+
14
+ def equal(other)
15
+ self.instance_variables.each do |var_name|
16
+ return false if self.instance_variable_get(var_name) != other.instance_variable_get(var_name)
17
+ end
18
+ true
19
+ end
20
+ alias == equal
21
+
22
+ def product!(other)
23
+ @lists << other.to_a.dup
24
+ @tot_iter *= @lists[-1].size
25
+ self
26
+ end
27
+ alias right_product! product!
28
+ alias x! product!
29
+
30
+ def left_product!(other)
31
+ @lists.unshift other.to_a.dup
32
+ @tot_iter *= @lists[-1].size
33
+ self
34
+ end
35
+
36
+ def product(other)
37
+ (result = self.dup).product!(other)
38
+ result
39
+ end
40
+ alias right_product product
41
+ alias x product
42
+
43
+ def left_product(other)
44
+ (result = self.dup).left_product!(other)
45
+ result
46
+ end
47
+
48
+ def each
49
+ return false if @tot_iter < 1
50
+
51
+ elems = []
52
+ for list in @lists
53
+ elems << list.restart_and_raw_next
54
+ end
55
+ if RUBY_VERSION <= '1.9.1'; yield *elems.map {|x| x }; else; yield *elems; end
56
+
57
+ last_list_index = @lists.size-1
58
+ n = last_list_index
59
+ loop do
60
+ if elems[n] = @lists[n].raw_next
61
+ if RUBY_VERSION <= '1.9.1'; yield *elems.map {|x| x }; else; yield *elems; end
62
+ n = last_list_index
63
+ next
64
+ elsif n > 0
65
+ elems[n] = @lists[n].restart_and_raw_next
66
+ n -= 1
67
+ else
68
+ return true
69
+ end
70
+ end
71
+ end
72
+
73
+ include Enumerable
74
+
75
+ end
76
+
77
+ module Iterable
78
+ def restart
79
+ @next_index = -1
80
+ true
81
+ end
82
+
83
+ def next
84
+ restart unless @next_index
85
+ raw_next
86
+ end
87
+
88
+ def raw_next
89
+ self[@next_index += 1]
90
+ end
91
+
92
+ def restart_and_raw_next
93
+ self[@next_index = 0]
94
+ end
95
+ end
96
+
97
+ class Array
98
+ include Iterable
99
+ end
@@ -0,0 +1,40 @@
1
+ module GridSearch
2
+
3
+ # Finds the argument which maximizes the function given in the block trhu grid-search maximization.
4
+ # [-1,0,1,2].argmax {|x| x**2 } #=> 2
5
+ #
6
+ def argmax(&block)
7
+ argbest(:>, &block)
8
+ end
9
+
10
+ # Finds the argument which minimizes the function given in the block trhu grid-search minimization.
11
+ # [-1,0,1,2].argmin {|x| x**2 } #=> 0
12
+ #
13
+ def argmin(&block)
14
+ argbest(:<, &block)
15
+ end
16
+
17
+ private
18
+
19
+ def argbest(cmp)
20
+ best_arg, best_val = nil, nil
21
+ self.each do |*curr_arg|
22
+ curr_val = yield(*curr_arg)
23
+ if best_val.nil? || curr_val.send(cmp, best_val)
24
+ best_val = curr_val
25
+ best_arg = curr_arg
26
+ end
27
+ end
28
+ best_arg
29
+ end
30
+
31
+ end
32
+
33
+ module Enumerable
34
+ include GridSearch
35
+ end
36
+
37
+ class Array
38
+ include GridSearch
39
+ end
40
+
data/lib/recursive.rb ADDED
@@ -0,0 +1,8 @@
1
+ # Code by Brian Schröäer
2
+ # source: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/151857
3
+ #
4
+ def cartprod(base, *others)
5
+ return base.map { |a| [a] } if others.empty?
6
+ others = cartprod(*others)
7
+ base.inject([]) { | r, a | others.inject(r) { | r, b | r << ([a,*b]) } }
8
+ end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/cartesian.rb'}"
9
+ puts "Loading cartesian gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
data/test/benchmark.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'cartesian'
2
+ require 'benchmark'
3
+
4
+ MULTIPLIER = 3
5
+ letras = ("a"*MULTIPLIER.."z"*MULTIPLIER).to_a
6
+ numeros = (0..10**1).to_a
7
+
8
+ Benchmark.bmbm do |x|
9
+ letras_numeros = nil
10
+ x.report("product") { letras_numeros = Cartesian.product(letras, numeros) }
11
+ x.report("product 2") { for x,y in letras_numeros; end }
12
+
13
+ x.report(".x") { letras_numeros = letras.x(numeros) }
14
+ x.report(".x 2") { for x,y in letras_numeros; end }
15
+ end
16
+
17
+ #~ x.report("productZip") { Cartesian.productZip(letras, numeros) }
18
+
19
+ #~ def Cartesian.productZip(first, second)
20
+ #~ result = []
21
+ #~ first.each do |a|
22
+ #~ aaa = Array.new(second.size) { a }
23
+ #~ result += aaa.zip(second)
24
+ #~ end
25
+ #~ result
26
+ #~ end
@@ -0,0 +1,12 @@
1
+ class Object
2
+
3
+ # Syntax sugar for "is this object among this array?"
4
+ #
5
+ # 1.among? [1,2,3] #=> true
6
+ # 0.among? [4,5] #=> false
7
+ #
8
+ def among?(ary)
9
+ ary.include? self
10
+ end
11
+
12
+ end
@@ -0,0 +1,67 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
+ require 'cartesian'
3
+
4
+ class TestCartesian < Test::Unit::TestCase
5
+
6
+ def test_arrays
7
+ foo = [1,2,3]
8
+ bar = %w{a b c}
9
+ expected = [[1, "a"], [1, "b"], [1, "c"], [2, "a"], [2, "b"],
10
+ [2, "c"], [3, "a"], [3, "b"], [3, "c"]]
11
+ assert(foo.x(bar).to_a == expected)
12
+ assert(Cartesian.product(foo,bar) == expected)
13
+ end
14
+
15
+ def test_ranges
16
+ foo = 1..3
17
+ bar = 4..6
18
+ expected = [[1, 4], [1, 5], [1, 6], [2, 4], [2, 5],
19
+ [2, 6], [3, 4], [3, 5], [3, 6]]
20
+ assert(foo.x(bar).to_a == expected)
21
+ assert(Cartesian.product(foo,bar) == expected)
22
+ end
23
+
24
+ def test_product
25
+ c = [1].x([2])
26
+ c.x([3])
27
+ assert_equal [1].x([2]), c
28
+ end
29
+
30
+ def test_left_product
31
+ c = [1].right_product([2])
32
+ d = [1].left_product([2])
33
+ e = [2].left_product([1])
34
+ assert_not_equal c, d
35
+ assert_equal c, e
36
+ c = [1].x([2]).right_product([3])
37
+ d = [1].x([2]).left_product([3])
38
+ e = [2].x([3]).left_product([1])
39
+ assert_not_equal c, d
40
+ assert_equal c, e
41
+ end
42
+
43
+ def test_mixed
44
+ foo = 1..3
45
+ bar = %w{a b c}
46
+ expected = [[1, "a"], [1, "b"], [1, "c"], [2, "a"], [2, "b"],
47
+ [2, "c"], [3, "a"], [3, "b"], [3, "c"]]
48
+ assert(foo.x(bar).to_a == expected)
49
+ assert(Cartesian.product(foo,bar) == expected) ##################
50
+ end
51
+
52
+ def test_power
53
+ ary = [1,2,3]
54
+ assert_raise(ArgumentError) { ary**(-1) }
55
+ assert_equal [], ary**0
56
+ assert_equal ary, ary**1
57
+ expected = [[0, 0, 0], [0, 0, 1], [0, 1, 0],\
58
+ [0, 1, 1], [1, 0, 0], [1, 0, 1],\
59
+ [1, 1, 0], [1, 1, 1]]
60
+ assert_equal expected, ([0,1]**3).to_a
61
+ end
62
+
63
+ def test_joined_cartesian
64
+ assert_equal ["1A", "1B", "2A", "2B"], [1,2].joined_cartesian(%w<A B>)
65
+ end
66
+
67
+ end
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
+ require 'cartesian'
3
+
4
+ class TestCartesianIterator < Test::Unit::TestCase
5
+
6
+ def test_equal
7
+ assert_equal [1].x([2]), [1].x([2])
8
+ assert_not_equal [1].x([2]), [1].x([3])
9
+ end
10
+
11
+
12
+ def test_dup
13
+ c = [1,2].x([3,4])
14
+ d = c.dup
15
+ e = d.x([5,6])
16
+ assert_not_equal(e, c)
17
+ assert_equal(c, d)
18
+ end
19
+
20
+ def test_iterator_next_and_restart
21
+ foo = [1,2]
22
+ assert_equal 1, foo.next
23
+ assert_equal 2, foo.next
24
+ assert_equal nil, foo.next
25
+ foo.restart
26
+ assert_equal 1, foo.next
27
+ end
28
+
29
+ end
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
+ require File.join(File.dirname(__FILE__), 'extensions.rb')
3
+
4
+ class TestExtensions < Test::Unit::TestCase
5
+ def test_among?
6
+ assert 1.among?([1,2,3])
7
+ assert ! 7.among?([1,2,3])
8
+ assert (3.0).among?([1,2,3])
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
+ require File.join(File.dirname(__FILE__), 'extensions.rb')
3
+
4
+ require 'cartesian/grid_search'
5
+
6
+ class TestCartesian < Test::Unit::TestCase
7
+ def test_argmin
8
+ assert_equal 0, *[-1,0,1].argmin {|x| x**2 }
9
+ assert_equal [0,0], ((-3..3)**2).argmin {|x,y| x**2+y**2 }
10
+ end
11
+
12
+ def test_argmax
13
+ assert_equal 0, *[-2,-1,0].argmax {|x| x**3 }
14
+ values = []
15
+ -3.step(3, 0.25) {|val| values << val }
16
+ x, y = (values**2).argmax {|x,y| x**2+y**2 }
17
+ assert x.among?([-3,3])
18
+ assert y.among?([-3,3])
19
+ end
20
+
21
+ end
@@ -0,0 +1,5 @@
1
+ require 'test/unit'
2
+
3
+ require 'rubygems'
4
+
5
+ $:.unshift(File.join(File.dirname(__FILE__), '../lib/'))
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Dir.chdir(File.dirname(__FILE__))
4
+
5
+ class String
6
+ def same_file?(other)
7
+ File.expand_path(self) == File.expand_path(other)
8
+ end
9
+ end
10
+
11
+ candidates = Dir.glob('test_*.rb')
12
+ to_exclude = [__FILE__, 'test_helper.rb']
13
+
14
+ test_files = candidates.reject {|f| to_exclude.any? {|ex| f.same_file?(ex) } }
15
+
16
+ test_files.each do |tf|
17
+ system "ruby #{tf}"
18
+ end
19
+
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cartesian
3
+ version: !ruby/object:Gem::Version
4
+ hash: 11
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
11
+ platform: ruby
12
+ authors:
13
+ - Adriano Mitre
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-04 00:00:00 -02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: hoe
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 47
30
+ segments:
31
+ - 2
32
+ - 8
33
+ - 0
34
+ version: 2.8.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: |-
38
+ Provides methods for the calculation of the cartesian producted between two
39
+ or more enumerable objects. Includes grid search optimization methods.
40
+ It can also be easily and conveniently mixed in into any enumerable class.
41
+ email:
42
+ - adriano.mitre@gmail.com
43
+ executables: []
44
+
45
+ extensions: []
46
+
47
+ extra_rdoc_files:
48
+ - History.txt
49
+ - Manifest.txt
50
+ - PostInstall.txt
51
+ - Wishlist.txt
52
+ files:
53
+ - History.txt
54
+ - Manifest.txt
55
+ - PostInstall.txt
56
+ - README.rdoc
57
+ - Rakefile
58
+ - Wishlist.txt
59
+ - config/hoe.rb
60
+ - config/requirements.rb
61
+ - lib/cartesian.rb
62
+ - lib/cartesian/grid_search.rb
63
+ - lib/cartesian/version.rb
64
+ - lib/cartesian_iterator.rb
65
+ - lib/grid_search.rb
66
+ - lib/recursive.rb
67
+ - script/console
68
+ - script/destroy
69
+ - script/generate
70
+ - test/benchmark.rb
71
+ - test/extensions.rb
72
+ - test/test_cartesian.rb
73
+ - test/test_cartesian_iterator.rb
74
+ - test/test_extensions.rb
75
+ - test/test_grid_search.rb
76
+ - test/test_helper.rb
77
+ - test/test_suite.rb
78
+ has_rdoc: true
79
+ homepage: http://github.com/adrianomitre/cartesian
80
+ licenses: []
81
+
82
+ post_install_message: PostInstall.txt
83
+ rdoc_options:
84
+ - --main
85
+ - README.rdoc
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 3
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirements: []
107
+
108
+ rubyforge_project: cartesian
109
+ rubygems_version: 1.3.7
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Provides methods for the calculation of the cartesian producted between two or more enumerable objects
113
+ test_files:
114
+ - test/test_helper.rb
115
+ - test/test_extensions.rb
116
+ - test/test_suite.rb
117
+ - test/test_cartesian_iterator.rb
118
+ - test/test_cartesian.rb
119
+ - test/test_grid_search.rb