Skip to content

Commit

Permalink
+ permutations
Browse files Browse the repository at this point in the history
  • Loading branch information
begriffs committed Jul 7, 2012
1 parent fb84682 commit ae89743
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
30 changes: 30 additions & 0 deletions lib/itertools/combinatoric_generators.rb
Expand Up @@ -7,5 +7,35 @@ def product *iters
Itertools.iter p.product *pools
end

def permutations iter, r=nil
Fiber.new do
pool = array Itertools.iter(iter)
n = pool.length
r ||= n
indices = (0...n).to_a
cycles = ((n-r+1)..n).to_a.reverse
exhausted if n == 0

Fiber.yield indices.slice(0,r).map { |i| pool[i] }
while true
finished = true
(r-1).downto(0) do |i|
cycles[i] -= 1
if cycles[i] == 0
indices = indices.slice(0,i) + indices.slice(i+1,n) + [indices[i]]
cycles[i] = n - i
else
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
Fiber.yield indices.slice(0,r).map { |i| pool[i] }
finished = false
break
end
end
exhausted if finished
end
end
end

end
end
24 changes: 24 additions & 0 deletions spec/combinatoric_generators_spec.rb
Expand Up @@ -15,4 +15,28 @@
end
end
end
context "#permutations" do
context "with a string and a length" do
it "permutes" do
seq = Itertools.permutations "ABCD", 2
seq.should begin_with [['A','B'], ['A','C'], ['A','D'], ['B','A'],
['B','C'], ['B','D'], ['C','A'], ['C','B'],
['C','D'], ['D','A'], ['D','B'], ['D','C']]
seq.should be_exhausted
end
end
context "with a string but no length" do
it "defaults to the length of the string" do
seq = Itertools.permutations "ABC"
seq.should begin_with [['A','B','C'], ['A','C','B'], ['B','A','C'],
['B','C','A'], ['C','A','B'], ['C','B','A']]
seq.should be_exhausted
end
end
context "with an empty array" do
it "gives nothing" do
Itertools.permutations([]).should be_exhausted
end
end
end
end

0 comments on commit ae89743

Please sign in to comment.