Skip to content
Permalink
Browse files

Merge pull request #720 from kostya/permutation2

Array permutations
  • Loading branch information
alex committed May 20, 2013
2 parents 97c4cc3 + fbcdc25 commit 925e6b02211cb65eadcbdaafe2daac5f61597751
@@ -396,4 +396,32 @@ def -(other)
other.each { |e| h[e] = true }
self.reject { |e| h.has_key?(e) }
end

def permutation(r = nil, &block)
return self.enum_for(:permutation, r) unless block
r = r ? Topaz.convert_type(r, Fixnum, :to_int) : self.size
Topaz::Array.permutation(self, r, &block)
self
end

def combination(r = nil, &block)
return self.enum_for(:combination, r) unless block
r = r ? Topaz.convert_type(r, Fixnum, :to_int) : self.size
Topaz::Array.combination(self, r, &block)
self
end

def repeated_combination(r, &block)
return self.enum_for(:repeated_combination, r) unless block
r = Topaz.convert_type(r, Fixnum, :to_int)
Topaz::Array.repeated_combination(self, r, &block)
self
end

def repeated_permutation(r, &block)
return self.enum_for(:repeated_permutation, r) unless block
r = Topaz.convert_type(r, Fixnum, :to_int)
Topaz::Array.repeated_permutation(self, r, &block)
self
end
end
@@ -32,11 +32,11 @@ def self.product(args, &block)
end
raise RangeError.new("product result is too large") if sumlen > Topaz::FIXNUM_MAX

yield pool.dup

n = arrs.size
indices = [0] * n

yield pool[0, n]

while true do
i = n - 1
indices[i] += 1
@@ -49,7 +49,119 @@ def self.product(args, &block)
indices[i] += 1
end
pool[i] = arrs[i][indices[i]]
yield pool.dup
yield pool[0, n]
end
end

def self.permutation(iterable, r, &block)
n = iterable.size
return if r > n || r < 0
pool = iterable.dup
cycles = (n - r + 1..n).to_a.reverse
yield pool[0, r]

while true
stop = true
i = r - 1
while i >= 0
cycles[i] -= 1
if cycles[i] == 0
e = pool[i]
j = i + 1
while j < n
pool[j - 1] = pool[j]
j += 1
end
pool[n - 1] = e
cycles[i] = n - i
else
j = cycles[i]
pool[i], pool[-j] = pool[-j], pool[i]
yield pool[0, r]
stop = false
break
end
i -= 1
end

return if stop
end
end

def self.combination(iterable, r, &block)
n = iterable.size
return if r > n || r < 0
copy = iterable.dup
pool = iterable.dup
indices = (0...r).to_a
yield pool[0, r]

while true
stop = true
i = r - 1
while i >= 0
if indices[i] != i + n - r
stop = false
break
end
i -= 1
end

return if stop

indices[i] += 1
pool[i] = copy[indices[i]]
j = i + 1
while j < r
indices[j] = indices[j - 1] + 1
pool[j] = copy[indices[j]]
j += 1
end

yield pool[0, r]
end
end

def self.repeated_combination(iterable, r, &block)
n = iterable.size
return if r < 0 || (n < r && n == 0)
copy = iterable.dup
indices = [0] * r
pool = indices.map { |i| copy[i] }

yield pool[0, r]

while true
stop = true

i = r - 1
while i >= 0
if indices[i] != n - 1
stop = false
break
end
i -= 1
end
return if stop

ii = indices[i]
j = i
while j < r
indices[j] = ii + 1
pool[j] = copy[ii + 1]
j += 1
end
yield pool[0, r]
end
end

def self.repeated_permutation(iterable, r, &block)
n = iterable.size
return if r < 0 || (r != 0 && n == 0)
if r == 0
yield []
else
product([iterable.dup] * r, &block)
end
end
end

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit 925e6b0

Please sign in to comment.
You can’t perform that action at this time.