lib/cartesian.rb in Cartesian-0.4.1 vs lib/cartesian.rb in Cartesian-0.4.2
- old
+ new
@@ -1,161 +1 @@
-#
-# The CartesianProduct module provide methods for the calculation
-# of the cartesian producted between two enumberable objects.
-#
-# It can also be easily mixed in into any enumberable class,
-# i.e. any class with Enumerable module mixed in.
-# Notice that the names of the methods for mixin are different.
-#
-# Module:
-# Cartesian::product(foo, bar)
-#
-# Mixin:
-# foo.cartesian( bar )
-#
-# The module is automatically mixed in Array class.
-#
-# == Author
-# Adriano MITRE <adriano.mitre@gmail.com>
-#
-# == Example
-#
-# as module
-# require 'cartesian'
-# foo = [1, 2]
-# bar = ["a", "b"]
-# Cartesian::product(foo, bar) #=> [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]
-# as mixin
-# require 'cartesian'
-# foo = [1, 2]
-# bar = ["a", "b"]
-# foo.cartesian(bar) #=> [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]
-#
-
-require 'cartesian_iterator'
-
-module Cartesian
-
- # Produces the cartesian product of self and other.
- # The result is an array of pairs (i.e. two-element arrays).
- #
- # Cartesian::product( [1,2], %w(A B) ) #=> [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
- #
- # or, if mixed in into Array,
- #
- # [1,2].cartesian %w(A B) #=> [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
- #
- def Cartesian.product(first, second)
- first.x(second).to_a
- end
-
- # Behaves as product, except for the elements are joined.
- #
- # Cartesian::joined_cartesian( [1,2], %w(A B) ) #=> ["1A", "1B", "2A", "2B"]
- #
- # or, if mixed in into Array,
- #
- # [1,2].joined_cartesian %w(A B) #=> ["1A", "1B", "2A", "2B"]
- #
- def Cartesian.joined_product(first, second)
- product(first, second).map {|pair| pair.join }
- end
-
- # Cartesian.joined_product for mixin.
- #
- def joined_cartesian(other)
- Cartesian.joined_product(self, other)
- end
-
- # Convenient way of iterating over the elements.
- # Preferable when the cartesian product array
- # is not needed, for the consumption of memory
- # is fixed and very small, in contrast with the
- # exponential memory requirements of the
- # conventional approach.
- #
- # for row, col in (1..10).x(1..30)
- # Matrix[row, col] = row**2 + col**3
- # end
- #
- # Of course, calls can be chained as in
- #
- # for x, y, z in (1..10).x(1..10).x(1..10)
- # # ... do something ...
- # end
- #
- #--
- # for letter, number in %w{a b c}.x(1..3)
- # ... do something ...
- # end
- #++
- #
- # Beware that both +self+ and +other+ must implement
- # +to_a+, i.e., be convertible to array.
- #
- def x(other)
- case other
- when CartesianIterator
- other.left_product(self)
- else
- CartesianIterator.new(self, other)
- end
- end
- alias cartesian x
- alias right_product x
-
- def left_product(other)
- case other
- when CartesianIterator
- other.right_product(self)
- else
- CartesianIterator.new(other, self)
- end
- end
-
- # Concise way of iterating multi-dimensionally
- # over the same array or range.
- #
- # For instance,
- #
- # for x,y,z in [0,1]**3
- # puts [x, y, z].join(',')
- # end
- #
- # produces the following output
- #
- # 0,0,0
- # 0,0,1
- # 0,1,0
- # 0,1,1
- # 1,0,0
- # 1,0,1
- # 1,1,0
- # 1,1,1
- #
- # It also works with Range objects.
- #
- def **(fixnum)
- if fixnum < 0
- raise ArgumentError, "negative power"
- elsif fixnum == 0
- return []
- elsif fixnum == 1
- return self
- else
- iter = CartesianIterator.new(self, self)
- (fixnum-2).times do
- iter.product!(self)
- end
- iter
- end
- end
- alias :power! :**
-end
-
-class Array
- include Cartesian
-end
-
-class Range
- include Cartesian
-end
\ No newline at end of file