package net.sf.colossus.util;
/**
* This class is a permutation generator. The permutations are generated
* using Dershowitz's method, meaning that a permutation only differs
* by the previous permutation by a single interchange of two adjacent
* elements. In many problem domains this allows a efficient dynamic
* update of a permutation function.
* @author Peter Unold
* @see "Dershowitz, Nachum. "A simplified loop -
* free algorithm for generating permutations" BIT - 15 1975 158 - 164"
* @see <a href="http://www.daimi.aau.dk/~pjunold/alg/dershowitz.html">
* Dershowitz's Permutation Generator</a>
*/
class PermGen
{
int[] m_p; // permutation
int[] m_l; // location
int[] m_t; // linked list
int[] m_d; // direction
int m_size;
PermGen(int size)
{
m_size = size;
m_p = new int[size];
m_l = new int[size];
m_t = new int[size + 1];
m_d = new int[size];
for (int i = 0; i < size; ++i)
{
m_p[i] = i;
m_l[i] = i;
m_d[i] = -1;
}
for (int j = 1; j <= size; ++j)
{
m_t[j] = j - 1;
}
}
/** generates the next permutation. If the function returns n, then
the elements at position n and n + 1 in the previous permutation
were interchanged to get the new permutation.
@return the index of the lower element which was interchanged or
- 1 if the last permutation has been reached. */
public int getNext()
{
int cur, neig, curpos, neigpos, neigpos2;
// 3
if (m_t[m_size] < 1)
{
return -1;
}
// 4
cur = m_t[m_size];
curpos = m_l[cur];
neigpos = curpos + m_d[cur];
neig = m_p[neigpos];
// 5
m_l[cur] = neigpos;
m_l[neig] = curpos;
m_p[curpos] = neig;
m_p[neigpos] = cur;
// 6
m_t[m_size] = m_size - 1;
// 7
neigpos2 = neigpos + m_d[cur];
if (neigpos2 < 0 || neigpos2 >= m_size || cur < m_p[neigpos2])
{
m_d[cur] = -m_d[cur];
m_t[cur + 1] = m_t[cur];
m_t[cur] = cur - 1;
}
return (curpos < neigpos) ? curpos : neigpos;
}
/** get the current permutation */
public int[] getCurrent()
{
return m_p;
}
// TODO JUnit
/** Unit test for PermGen. */
public static void main(String[] args)
{
if (args.length == 0)
{
System.out.println("Need to provide a size.");
return;
}
int size = Integer.parseInt(args[0]);
int[] perm;
int count = 0;
PermGen pg = new PermGen(size);
do
{
perm = pg.getCurrent();
System.out.print(++count + " : ");
for (int i = 0; i < size; i++)
{
System.out.print(perm[i]);
}
System.out.println();
}
while (pg.getNext() != -1);
}
}