Skip to content

Commit

Permalink
Renamed rearrange to permute--both the class and the method names.
Browse files Browse the repository at this point in the history
However, rearrange is still an alias for the permute method.
Made the entirety of permute a mixin instead of standalone class methods.
Added bits of whitespace all over the commented areas for consistency/cosmetics.
Ensured that YARD examples were complete for all methods that return Enumerators
Organized the spec and lib directory hierarchies to match the permute mixin.
  • Loading branch information
duper committed Feb 17, 2011
1 parent 2c1d517 commit bcbef18
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 273 deletions.
2 changes: 1 addition & 1 deletion lib/combinatorics.rb
Expand Up @@ -4,5 +4,5 @@
require 'combinatorics/extensions'
require 'combinatorics/list_comprehension'
require 'combinatorics/power_set'
require 'combinatorics/rearrange'
require 'combinatorics/permute'
require 'combinatorics/version'
26 changes: 16 additions & 10 deletions lib/combinatorics/cartesian_product/cardinality.rb
@@ -1,18 +1,24 @@
module Combinatorics
module CartesianProduct
#
# Compute the number of elements a Cartesian Product will contain
#
# @param [Fixnum] c1 cardinality of first set
# @param [Fixnum] c2 cardinality of second set
# @raise [RangeError] c1 must be greater than zero
# @raise [RangeError] c2 must be greater than zero
# @return [Fixnum] number of elements in resulting Cartesian product set
# @example Combinatorics::CartesianProduct::cardinality(3, 4) => 12
def cardinality(c1, c2)
raise(RangeError, 'c1 must be greater than zero') if c1 <= 0
raise(RangeError, 'c2 must be greater than zero') if c2 <= 0
# @param [Fixnum] a Cardinality of first set
#
# @param [Fixnum] b Cardinality of second set
#
# @raise [RangeError] Inputs must be greater than zero
#
# @return [Fixnum] Length of enumeration resulting from a Cartesian product
#
# @example Calculate elements in Cartesian product of two equal-size sets
# cardinality(3, 4)
# # => 12
#
def cardinality(a, b)
raise(RangeError, 'inputs must be greater than zero') if a <= 0 or b <= 0

c1 * c2
a * b
end

alias len cardinality
Expand Down
14 changes: 10 additions & 4 deletions lib/combinatorics/cartesian_product/mixin.rb
Expand Up @@ -3,24 +3,30 @@
module Combinatorics
module CartesianProduct
module Mixin
#
# Calculates the Cartesian product of an Enumerable object.
#
# @yield [subset] If a block is given, it will be passed each individual
# subset element from the Cartesian product set as a whole
# @yieldparam [Array] subset A sub-set from the Cartesian product
# @raise ArgumentError enum2 must be non-nil
# @return [Enumerator] The resulting Cartesian product set
#
# @yieldparam [Array] subset The sub-set from the Cartesian product
#
# @raise [ArgumentError] enum2 must be non-nil
#
# @return [Enumerator] Resulting Cartesian product set
#
# @example Cartesian product of an Array
# [1, 2].cartprod([3, 4])
# # => [[1, 3], [2, 3], [1, 4], [2, 4]]
#
# @example Cartesian product over an Array of string Array's
# ['a'].cartprod([['b'], ['c'], ['d']]).to_a
# # => [["a", "b", "c", "d"]]
#
# @example Three-way Cartesian product operation
#
# @see http://en.wikipedia.org/wiki/Cartesian_product
# @see http://en.wikipedia.org/wiki/Arity
#
def cartprod(enum2)
raise(ArgumentError, 'enum2 must be non-nil') if not enum2

Expand Down
48 changes: 35 additions & 13 deletions lib/combinatorics/choose.rb
Expand Up @@ -5,19 +5,28 @@
module Combinatorics
module Choose
include Math

# @param [Fixnum] n the number of elements in the input set
# @param [Fixnum] r cardinality of subsets to choose
#
# @param [Fixnum] n The number of elements in the input set
#
# @param [Fixnum] r Cardinality of subsets to choose
#
# @raise [RangeError] n must be non-negative
#
# @raise [RangeError] r must be non-negative
#
# @raise [RangeError] r must be less than or equal to n
#
# @return [Fixnum] the binomial coefficient of "n-choose-r"
#
# @example C(6, 4)
#
# @see http://en.wikipedia.org/wiki/Binomial_coefficient
#
# @note This method's naming convention reflects well-known notation used
# within fields of academic inquiry such as discrete mathematics and
# set theory. It represents a function returning an integer value
# for the cardinality of a k-combination (i.e. binomial coefficient.)
#
def C(n, r = nil)
raise(RangeError, 'n must be non-negative') if n < 0

Expand All @@ -26,8 +35,7 @@ def C(n, r = nil)
else
raise(RangeError, 'r must be non-negative') if r < 0
raise(RangeError, 'r must be less than or equal to n') if r > n
return 0 if r.zero?
return 1 if n == r
return 1 if n.zero? or n == r

factorial(n) / (factorial(r) * factorial(n - r))
end
Expand All @@ -36,13 +44,19 @@ def C(n, r = nil)
alias cardinality C
alias len cardinality

# @param [Fixnum] c input set cardinality
# @return [Array] elements are cardinalities for each subset 1 .. c
#
# @param [Fixnum] c Input set cardinality
#
# @return [Array] elements are cardinalities for each subset "1" through "c"
#
# @raise [RangeError] c must be non-negative
#
# @example cardinality_all(4)
#
# @note sum of elements will equal factorial(c)
# @see choose
#
# @see http://en.wikipedia.org/wiki/Combinations
#
def cardinality_all(c)
if c.zero?
return []
Expand All @@ -52,22 +66,30 @@ def cardinality_all(c)

ret = [c]

2.upto(c) { |x| ret << P(c, x) }
2.upto(c) { |x| ret << C(c, x) }

ret
end

alias C_all cardinality_all
alias len_all C_all

#
# Get combinations with a specified number of elements from an input set
# @param [Array] s the input set
# @param [Fixnum] k cardinality of chosen subsets
#
# @param [Array] s The input set
#
# @param [Fixnum] k Cardinality of chosen subsets
#
# @raise [TypeError] s must be Enumerable
#
# @return [Enumerator] collection of k-sized combinations within input set
# @example choose([1, 2], 1).to_a => [[1], [2]]
#
# @example choose([1, 2], 1).to_a
# # => [[1], [2]]
#
# @see Array#combination
# @see Combinatorics::Rearrange::rearrange
#
def choose(s, k)
return [[]].enum_for if s.nil?
raise(TypeError, 's must be Enumerable') if not s.is_a?(Enumerable)
Expand Down
19 changes: 14 additions & 5 deletions lib/combinatorics/derange.rb
Expand Up @@ -5,12 +5,20 @@
module Combinatorics
module Derange
include Choose, Math

# @param [Array] a sequence to output derangements for
# @return [Enumerator] set of the derangements for input sequence
# @example derange([1, 2, 3])
#
# @param [Array] a Sequence to output derangements for
#
# @return [Enumerator] Set of the derangements for input sequence
#
# @example Produce the derangements of a three-element Array
# derange([1, 2, 3]).to_a
# # => [[2, 1, 1], [2, 1, 2], [2, 3, 1], [2, 3, 2], [3, 1, 1], [3, 1, 2],
# [3, 3, 1], [3, 3, 2]]
#
# @see http://en.wikipedia.org/wiki/Derangements
#
# @see Array#comprehension
#
def derange(a)
c = []

Expand All @@ -26,6 +34,7 @@ def derange(a)
end

alias cardinality subfactorial
alias D subfactorial # discrete math notation
# @note The letter 'D' is formal discrete math notation for this operation
alias D subfactorial
end
end
7 changes: 7 additions & 0 deletions lib/combinatorics/permute/array_extension.rb
@@ -0,0 +1,7 @@
require 'combinatorics/permute/mixin'

class Array

include Combinatorics::Permute::Mixin

end
112 changes: 112 additions & 0 deletions lib/combinatorics/permute/mixin.rb
@@ -0,0 +1,112 @@
# @author duper <super@manson.vistech.net>

require 'combinatorics/extensions/math'

module Combinatorics
module Permute
module Mixin
include Math
#
# Mathematically determine the number of elements in a r-permutations set
#
# @param [Fixnum] n The number of elements in the input set
#
# @param [Fixnum] r Cardinality of permuted subsets
#
# @raise [RangeError] n must be non-negative
#
# @raise [RangeError] r must be non-negative
#
# @raise [RangeError] r must be less than or equal to n
#
# @return [Fixnum] The product of the first r factors of n
#
# @example Calculate total 4-permutations for a set whose cardinality is 6
# P(6, 4)
# # => 360
#
# @see http://en.wikipedia.org/wiki/Permutations
#
# @note This method's naming convention reflects well-known notation used
# within fields of academic inquiry such as discrete mathematics and
# set theory. It represents a function returning an integer value
# for the cardinality of a r-permutation.
#
def P(n, r = nil)
raise(RangeError, 'n must be non-negative') if n < 0

if r.nil?
factorial(n)
else
raise(RangeError, 'r must be non-negative') if r < 0
raise(RangeError, 'r must be less than or equal to n') if r > n
return 1 if n.zero? or n == r

factorial(n) / factorial(n-r)
end
end

alias cardinality P
alias len cardinality

#
# Compute cardinality of all r-permutations for a set with cardinality c
#
# @param [Fixnum] c Input set cardinality
#
# @return [Array] Elements are cardinalities for each subset 1 .. c
#
# @raise [RangeError] c must be non-negative
#
# @example cardinality_all(4)
# # => [4, 3, 10, 1]
#
# @note sum of elements will equal factorial(c)
#
# @see http://en.wikipedia.org/wiki/Permutations
#
def cardinality_all(c)
if c.zero?
return []
elsif c < 0
raise(RangeError, 'c must be non-negative')
end

ret = [c]

2.upto(c) { |x| ret << P(c, x) }

ret
end

alias P_all cardinality_all
alias len_all P_all

#
# Enumerate distinct r-permutations for a particular sequence of elements
#
# @param [Array] s the input set
#
# @param [Fixnum] r Length of permuted subsets to return
#
# @return [Enumerator] k-permutations of elements from s
#
# @raise [TypeError] s must be Enumerable
#
# @example permute([1, 2], 1).to_a
# # => [[1], [2]]
#
# @see Array#permutation
#
def permute(s, r)
return [[]].enum_for if s.nil?
raise(TypeError, 's must be Enumerable') if not s.is_a?(Enumerable)
return [[]].enum_for if s.empty?

s.permutation(r)
end

alias rearrange permute
end
end
end

0 comments on commit bcbef18

Please sign in to comment.