All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xcsp.common.enumerations.EnumerationOfPermutations Maven / Gradle / Ivy

/**
 * AbsCon - Copyright (c) 2017, CRIL-CNRS - [email protected]
 * 
 * All rights reserved.
 * 
 * This program and the accompanying materials are made available under the terms of the CONTRAT DE LICENCE DE LOGICIEL
 * LIBRE CeCILL which accompanies this distribution, and is available at http://www.cecill.info
 */
package org.xcsp.common.enumerations;

import java.util.Arrays;
import java.util.stream.IntStream;

import org.xcsp.common.Utilities;

/**
 * This class allows us to iterate over all permutations of a given set of integer values. See the Johnson-Trotter algorithm (H. F. Trotter[1962], S.
 * M. Johnson[1963]). Execute the main method for an illustration.
 */
public class EnumerationOfPermutations extends EnumerationAbstract {

	/**
	 * The values used to form permutations.
	 */
	private final int[] values;

	private final boolean[] currDirectionOfIndexes; // false=left ; true =right

	/**
	 * Builds an object that can be used for enumerating permutations, using the specified array of values.
	 * 
	 * @param values
	 *            the values used to form permutations
	 */
	public EnumerationOfPermutations(int... values) {
		super(values.length, IntStream.range(0, values.length).allMatch(i -> i == values[i]));
		this.values = values;
		this.currDirectionOfIndexes = new boolean[values.length];
		Utilities.control(IntStream.of(values).distinct().count() == values.length, "Values should all be different");
		reset();
	}

	/**
	 * Builds an object that can be used for enumerating permutations, using the specified number of values. All values are taken in the range 0 to
	 * {@code nValues-1}.
	 * 
	 * @param nValues
	 *            the number of values used to form permutations
	 */
	public EnumerationOfPermutations(int nValues) {
		this(IntStream.range(0, nValues).toArray());
	}

	@Override
	protected int valAt(int i) {
		return values[currTupleOfIdxs[i]];
	}

	@Override
	protected void computeFirstTuple() {
		for (int i = 0; i < currTupleOfIdxs.length; i++)
			currTupleOfIdxs[i] = i;
		Arrays.fill(currDirectionOfIndexes, false);

	}

	private int findLargestMobileIndexPosition() {
		int best = -1;
		for (int p = 0; p < currTupleOfIdxs.length; p++) {
			int q = currDirectionOfIndexes[p] ? p + 1 : p - 1;
			if (q < 0 || q > currTupleOfIdxs.length - 1)
				continue;
			if (currTupleOfIdxs[p] > currTupleOfIdxs[q])
				if (best == -1 || currTupleOfIdxs[p] > currTupleOfIdxs[best])
					best = p;
		}
		return best;
	}

	@Override
	public boolean hasNext() {
		if (nextTuple != null)
			return nextTuple == Boolean.TRUE;
		int p = findLargestMobileIndexPosition();
		if (p == -1) {
			nextTuple = Boolean.FALSE;
			return false;
		}
		int q = currDirectionOfIndexes[p] ? p + 1 : p - 1;
		int tmp = currTupleOfIdxs[p];
		boolean tmpD = currDirectionOfIndexes[p];
		currTupleOfIdxs[p] = currTupleOfIdxs[q];
		currDirectionOfIndexes[p] = currDirectionOfIndexes[q];
		currTupleOfIdxs[q] = tmp;
		currDirectionOfIndexes[q] = tmpD;
		for (int i = 0; i < currDirectionOfIndexes.length; i++)
			if (currTupleOfIdxs[i] > tmp)
				currDirectionOfIndexes[i] = !currDirectionOfIndexes[i];
		nextTuple = Boolean.TRUE;
		return true;
	}

	// @Override
	// public int[][] toArray() {
	// reset();
	// int nPermutations = Utilities.factorial(values.length);
	// int[][] m = new int[nPermutations][values.length];
	// int cnt = 0;
	// while (hasNext()) {
	// m[cnt] = next().clone();
	// cnt++;
	// }
	// return Stream.of(m).sorted(Utilities.lexComparatorInt).toArray(int[][]::new);
	// }

	public static void main(String[] args) {
		new EnumerationOfPermutations(1, 2, 3, 4, 5).displayAllTuples();
		new EnumerationOfPermutations(3).displayAllTuples();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy