# Combinatorial Calculation Library
#
# by Shin-ichiro Hara
#
# Version 2.0 (2001.09.14)
module Combinatorial
def power(n, m = n)
if m == 0
yield([])
else
power(n, m - 1) do |x|
(0...n).each do |i|
yield([i] + x)
end
end
end
end
def perm(n, m = n)
if m == 0
yield([])
else
perm(n - 1, m - 1) do |x|
(0...n).each do |i|
yield([i] + x.collect{|j| j < i ? j : j + 1})
end
end
end
end
def comb(n, m = n)
if m == 0
yield([])
else
comb(n, m - 1) do |x|
(((x[0] || -1) + 1)...n).each do |i|
yield([i] + x)
end
end
end
end
def rep_comb(n, m)
if m == 0
yield([])
else
rep_comb(n, m - 1) do |x|
((x.empty? ? 0 : x.last)...n).each do |i|
yield(x+[i])
end
end
end
end
def power0(n, m = n)
0.upto n**m-1 do |i|
yield( (0...m).collect{ (i, = i.divmod n).last } )
end
end
def perm0(n, stack = [])
(0...n).each do |x|
unless stack.include? x
stack.push x
if stack.size < n
perm0(n, stack) do |y|; yield y; end
else
yield stack.self
end
stack.pop
end
end
end
module_function :power, :perm, :comb, :rep_comb, :power0, :perm0
module Diagonal
def diagonal_cone(n, m)
0.upto n do |i|
co_diagonal(i, m) do |a|
yield a
end
end
end
def co_diagonal(n, m)
rep_comb(n+1, m-1) do |a|
yield difference_seq(0, a, n)
end
end
def difference_seq(n0, ary, n1)
x = n0
a = []
ary.each do |y|
a.push y - x
x = y
end
a.push n1 - x
a
end
private :difference_seq
end
include Diagonal
extend Diagonal
module Cubic
# power in order of (point, eadges, surfaces, bodies, ..)
def power_cubic(n, m)
if n < 1
raise "cubic(< 1, m) called"
elsif n == 1
yield( (0...m).collect{0} )# point of origin
else
0.upto m do |dim|
Combinatorial.comb(m, dim) do |s|
power_cubic(n-1, dim) do |a|
yield inject(a, s.sort, m)
end
end
end
end
end
def inject(ary, inds, n = inds.size+1)
(0...n).collect{|i| (k = inds.index(i)) ? 1 + ary[k] : 0}
end
private :inject
end
include Cubic
extend Cubic
end
if __FILE__ == $0
# include Combinatorial
n, dim = ARGV.collect{|x|x.to_i}
# n, dim = 2, 3
# diagonal_cone(n, m) do |a|; p a; end
Combinatorial::power_cubic(n, dim) do |a|
# Combinatorial::power_cubic_nested(n, dim) do |a|
p a
end
# $stderr.puts( (2*n+1)**dim )
end
syntax highlighted by Code2HTML, v. 0.9.1