org.ddogleg.combinatorics.Permute Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ddogleg Show documentation
Show all versions of ddogleg Show documentation
DDogleg Numerics is a high performance Java library for non-linear optimization, robust model fitting, polynomial root finding, sorting, and more.
/*
* Copyright (c) 2012-2015, Peter Abeles. All Rights Reserved.
*
* This file is part of DDogleg (http://ddogleg.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ddogleg.combinatorics;
import java.util.ArrayList;
import java.util.List;
/**
*
* Exhaustively computes all the permutations of a set, without recursion. Designed to be memory and speed efficient.
*
*
*
* Example for the set "0123".
*
*
* {@code
* 0123
* 0132
* 0213
* 0231
* 0321
* 0312
* 1023
* 1032
* 1203
* 1230
* 1320
* 1302
* 2103
* 2130
* 2013
* 2031
* 2301
* 2310
* 3120
* 3102
* 3210
* 3201
* 3021
* 3012
* }
*
*
* @param
*/
public class Permute< T >
{
protected List list;
private int indexes[];
private int counters[];
private int total;
private int permutation;
/**
Permute the elements in the list provided
*/
public Permute(List list) {
init( list );
}
public Permute() {
}
/**
* Initializes the permutation for a new list
*
* @param list List which is to be permuted.
*/
private void init( List list ) {
this.list = list;
indexes = new int[ list.size() ];
counters = new int[ list.size() ];
for( int i = 0; i < indexes.length ; i++ ) {
counters[i] = indexes[i] = i;
}
total = 1;
for( int i = 2; i <= indexes.length ; i++ ) {
total *= i;
}
permutation = 0;
}
/**
* Returns the total number of permutations
*/
public int getTotalPermutations() {
return total;
}
/**
* This will permute the list once
*/
public boolean next()
{
if( indexes.length <= 1 || permutation >= total-1 )
return false;
int N = indexes.length-2;
int k = N;
swap(k, counters[k]++);
while( counters[k] == indexes.length ) {
k -= 1;
swap(k, counters[k]++);
}
swap(counters[k], k); //before
while (k < indexes.length - 1) {
k++;
counters[k] = k;
}
permutation++;
return true;
}
/**
* This will undo a permutation.
*/
public boolean previous()
{
if( indexes.length <= 1 || permutation <= 0 )
return false;
int N = indexes.length-2;
int k = N;
while( counters[k] <= k ) {
k--;
}
swap(counters[k], k);
counters[k]--;
swap(k, counters[k]);
int foo = k+1;
while( counters[k+1] == k+1 && k < indexes.length-2) {
k++;
swap(k, indexes.length-1);
}
for (int i = foo; i < indexes.length - 1; i++) {
counters[i] = indexes.length - 1;
}
permutation--;
return true;
}
private void swap( int i , int j ) {
int val = indexes[i];
indexes[i] = indexes[j];
indexes[j] = val;
}
/**
* Returns the size of the list being premuted
*
* @return list size
*/
public int size() {
return list.size();
}
/**
* Returns element 'i' in the current permutation
*
* @param i index
* @return element in permuted list
*/
public T get( int i ) {
return list.get(indexes[i]);
}
/**
* Returns a list containing the current permutation.
*
* @param storage Optional storage. If null a new list will be declared.
* @return Current permutation
*/
public List getPermutation(List storage) {
if( storage == null )
storage = new ArrayList();
else
storage.clear();
for( int i = 0; i < list.size(); i++ ) {
storage.add(get(i));
}
return storage;
}
public static void main(String[] args) {
List list = new ArrayList();
for (int i = 0; i < 4; i++) {
list.add(i);
}
Permute permute = new Permute(list);
print(permute);
while( permute.next() ) {
print(permute);
}
System.out.println();
System.out.println("Reverse");
print(permute);
while( permute.previous() ) {
print(permute);
}
}
private static void print( Permute permute ) {
System.out.print(" * ");
for (int i = 0; i < permute.size(); i++) {
System.out.print(permute.get(i));
}
System.out.println();
}
}