Skip to content

Commit

Permalink
Trac #20008: Implement non-recursive iterator for compositions
Browse files Browse the repository at this point in the history
Compositions currently uses a recursive iterator, which also has extra
overhead of converting between the element classes.

URL: http://trac.sagemath.org/20008
Reported by: tscrim
Ticket author(s): Travis Scrimshaw
Reviewer(s): Darij Grinberg
  • Loading branch information
Release Manager authored and vbraun committed Feb 5, 2016
2 parents cbabbdf + c6ba3e7 commit b0f4ff0
Showing 1 changed file with 33 additions and 6 deletions.
39 changes: 33 additions & 6 deletions src/sage/combinat/composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -1960,13 +1960,40 @@ def __iter__(self):
sage: Compositions(0).list()
[[]]
"""
if self.n == 0:
yield self.element_class(self, [])
return
for c in composition_iterator_fast(self.n):
yield self.element_class(self, c)

def composition_iterator_fast(n):
"""
Iterator over compositions of ``n`` yielded as lists.
TESTS::
for i in range(1,self.n+1):
for c in Compositions_n(self.n-i):
yield self.element_class(self, [i]+list(c))
sage: from sage.combinat.composition import composition_iterator_fast
sage: L = list(composition_iterator_fast(4)); L
[[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
sage: type(L[0])
<type 'list'>
"""
# Special cases
if n < 0:
return
if n == 0:
yield []
return

s = Integer(0) # Current sum
cur = [Integer(0)]
while cur:
cur[-1] += 1
s += 1
# Note that because we are adding 1 every time,
# we will never have s > n
if s == n:
yield list(cur)
s -= cur.pop()
else:
cur.append(Integer(0))

from sage.structure.sage_object import register_unpickle_override
register_unpickle_override('sage.combinat.composition', 'Composition_class', Composition)
Expand Down

0 comments on commit b0f4ff0

Please sign in to comment.