Permutations by swapping: Difference between revisions
Content added Content deleted
m (→{{header|J}}) |
(Small improvements in the first Python entry) |
||
Line 71: | Line 71: | ||
When saved in a file called spermutations.py it is used in the Python example to the [[Matrix arithmetic#Python|Matrix arithmetic]] task. |
When saved in a file called spermutations.py it is used in the Python example to the [[Matrix arithmetic#Python|Matrix arithmetic]] task. |
||
<lang python> |
<lang python>from operator import itemgetter |
||
DEBUG = False # like the built-in __debug__ |
|||
def spermutations(n): |
def spermutations(n): |
||
"""permutations by swapping. Yields: perm, sign""" |
|||
sign = 1 |
sign = 1 |
||
p = [[i, 0 if i==0 else -1] |
p = [[i, 0 if i == 0 else -1] # [num, direction] |
||
for i in range(n)] |
for i in range(n)] |
||
if |
if DEBUG: print ' #', p |
||
yield tuple(pp[0] for pp in p), sign |
yield tuple(pp[0] for pp in p), sign |
||
while any(pp[1] for pp in p): # moving |
while any(pp[1] for pp in p): # moving |
||
i1, |
i1, (n1, d1) = max(((i, pp) for i, pp in enumerate(p) if pp[1]), |
||
key= |
key=itemgetter(1)) |
||
n1, d1 = largest |
|||
sign *= -1 |
sign *= -1 |
||
if d1 == -1: |
if d1 == -1: |
||
# Swap down |
# Swap down |
||
i2 = i1-1 |
i2 = i1 - 1 |
||
p[i1], p[i2] = p[i2], p[i1] |
p[i1], p[i2] = p[i2], p[i1] |
||
# If this causes the chosen element to reach the First or last |
# If this causes the chosen element to reach the First or last |
||
# position within the permutation, or if the next element in the |
# position within the permutation, or if the next element in the |
||
# same direction is larger than the chosen element: |
# same direction is larger than the chosen element: |
||
if i2 == 0 or p[i2-1][0] > n1: |
if i2 == 0 or p[i2 - 1][0] > n1: |
||
# The direction of the chosen element is set to zero |
# The direction of the chosen element is set to zero |
||
p[i2][1] = 0 |
p[i2][1] = 0 |
||
elif d1 == 1: |
elif d1 == 1: |
||
# Swap up |
# Swap up |
||
i2 = i1+1 |
i2 = i1 + 1 |
||
p[i1], p[i2] = p[i2], p[i1] |
p[i1], p[i2] = p[i2], p[i1] |
||
# If this causes the chosen element to reach the first or Last |
# If this causes the chosen element to reach the first or Last |
||
# position within the permutation, or if the next element in the |
# position within the permutation, or if the next element in the |
||
# same direction is larger than the chosen element: |
# same direction is larger than the chosen element: |
||
if i2 == n-1 or p[i2+1][0] > n1: |
if i2 == n - 1 or p[i2 + 1][0] > n1: |
||
# The direction of the chosen element is set to zero |
# The direction of the chosen element is set to zero |
||
p[i2][1] = 0 |
p[i2][1] = 0 |
||
if |
if DEBUG: print ' #', p |
||
yield tuple(pp[0] for pp in p), sign |
yield tuple(pp[0] for pp in p), sign |
||
Line 114: | Line 115: | ||
if n3 > n1: |
if n3 > n1: |
||
pp[1] = 1 if i3 < i2 else -1 |
pp[1] = 1 if i3 < i2 else -1 |
||
if |
if DEBUG: print ' # Set Moving' |
||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
Line 126: | Line 127: | ||
sp.add(i[0]) |
sp.add(i[0]) |
||
print('Perm: %r Sign: %2i' % i) |
print('Perm: %r Sign: %2i' % i) |
||
if |
#if DEBUG: raw_input('?') |
||
# Test |
# Test |
||
p = set(permutations(range(n))) |
p = set(permutations(range(n))) |
||
assert sp == p, 'Two methods of generating permutations do not agree'</lang> |
assert sp == p, 'Two methods of generating permutations do not agree'</lang> |
||
{{out}} |
|||
;Sample output: |
|||
<pre>Permutations and sign of 3 items |
<pre>Permutations and sign of 3 items |
||
Perm: (0, 1, 2) Sign: 1 |
Perm: (0, 1, 2) Sign: 1 |