Sha256: ea6ce241c547e6f84e197c7ae21bdf1318d39b053bb50f35984c1fba464142da

Contents?: true

Size: 1.98 KB

Versions: 5

Compression:

Stored size: 1.98 KB

Contents

require 'epitools/basetypes'

class Array
  
  alias_method :"*_without_permutations", :*
  
  #
  # Overloaded * operator.
  #
  # Original behaviour:
  #   array * number == <number> copies of array
  # Extra behaviour:
  #   array * array = Cartesian product of the two arrays
  #
  def *(other)
    case other
      when Array
        # cross-product
        result = []
        (0...self.size).each do |a|
          (0...other.size).each do |b|
            result << [self[a], other[b]]
          end
        end
        result
      else
        send(:"*_without_permutations", other)
    end
  end
  
  #
  # Multiply the array by itself 'exponent'-times.
  #
  def **(exponent)
    ([self] * exponent).foldl(:*)
  end
  
  def all_pairs(reflexive=false)
    (0...size).each do |a|
      start = reflexive ? a : a+1
      (start...size).each do |b|
        yield self[a], self[b]
      end
    end
  end
  
  enumerable :all_pairs
  
end


#
# Returns all the `size`-sized selections of the elements from an array.
#
# I can't remember why I wrote it like this, but the array you want to
# permute is passed in as a block. For example:
#
#   >> perms(1) { [1,2,3,4] }
#   => [[1], [2], [3], [4]] 
#   >> perms(2) { [1,2,3,4] }
#   => [[1, 1], [1, 2], [1, 3], [1, 4], [2, 1], [2, 2], [2, 3], [2, 4],
#       [3, 1], [3, 2], [3, 3], [3, 4], [4, 1], [4, 2], [4, 3], [4, 4]]
#
# The block also gets passed a parameter: the depth of the recursion.
# I can't remember why I did that either! :D
#
def perms(size, n=0, stack=[], &block)
  ps = yield(n)
  results = []
  if n >= size
    results << stack
  else  
    ps.each do |p|
      results += perms(size, n+1, stack + [p], &block)
    end
  end
  results
end
  

if $0 == __FILE__
  puts "-------------- foldl ---"
  p [:sum, [1,1,1].foldl(:+)]
  p ["[[1,2],[3]].foldl(:+)", [[1,2],[3]].foldl(:+)]
  p [[0,1],[0,1]].foldl(:*)

  puts "-------------- cartesian product ---"
  p ["[0,1]*[2,3]",[0,1]*[2,3]]

  puts "-------------- cartesian exponent ---"
  p [0,1]**3
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
epitools-0.4.20 lib/epitools/permutations.rb
epitools-0.4.19 lib/epitools/permutations.rb
epitools-0.4.18 lib/epitools/permutations.rb
epitools-0.4.17 lib/epitools/permutations.rb
epitools-0.4.16 lib/epitools/permutations.rb