1 /* 2 * Permuter.java 3 * 4 * Created on 3-mar-2006, based on Permutations from Tim Tyler. 5 * 6 * Copyright (C) 2005 Hendrik Maryns <hendrik@sfs.uni-tuebingen.de>. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 2 11 * of the License, or (at your option) any later version. 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 */ 20 package combinatorics; 21 22 /** 23 * A class that permutes a given array of elements. It is an iterator that 24 * returns all permutations, successively. Thanks to Tim Tyler for the 25 * original implementation <a href="http://mandala.co.uk/permutations/"> 26 * http://mandala.co.uk/permutations/</a>. 27 * 28 * @author <a href="mailto:hendrik.maryns@uni-tuebingen.de">Hendrik Maryns</a> 29 * @param <T> The type of the array to be permuted. 30 */ 31 public final class Permuter<T> extends CombinatoricOperator<T> { 32 33 /** 34 * Initialise a new permuter, with given array of elements to permute. 35 * 36 * @param elements 37 * The elements to permute. 38 * @post The total number is set to the factorial of the number of 39 * elements. 40 * | new.getTotal() == factorial(elements.length) 41 * @post The number of permutations left is set to the total number. 42 * | new.getNumLeft() == new.getTotal() 43 */ 44 public Permuter(final T[] elements) { 45 super(elements, elements.length); 46 } 47 48 /** 49 * Compute the total number of elements to return. 50 * 51 * @return The factorial of the number of elements. 52 * | result == factorial(n) 53 * @see CombinatoricOperator#initialiseTotal(int, int) 54 */ 55 @Override 56 protected double initialiseTotal(final int n, final int r) { 57 return CombinatoricOperator.factorial(n); 58 } 59 60 /** 61 * Compute the next array of indices. 62 * 63 * @see CombinatoricOperator#computeNext() 64 */ 65 @Override 66 protected void computeNext() { 67 // find the rightmost element that is smaller than the element at its right 68 int i = this.indices.length - 1; 69 while (this.indices[i - 1] >= this.indices[i]) { 70 i = i - 1; 71 } 72 // find the rightmost element that is bigger then the other one 73 int j = this.indices.length; 74 while (this.indices[j - 1] <= this.indices[i - 1]) { 75 j = j - 1; 76 } 77 // swap them (always is i < j) 78 this.swap(i - 1, j - 1); 79 // now the elements at the right of i are in descending order, so reverse them all 80 i++; 81 j = this.indices.length; 82 while (i < j) { 83 this.swap(i - 1, j - 1); 84 i++; 85 j--; 86 } 87 // TODO: try other algorithms, see http://www.cut-the-knot.org/Curriculum/Combinatorics/JohnsonTrotter.shtml 88 } 89 90 /** 91 * Swap the elements at positions a and b, both from the index array and 92 * from the element array. 93 * 94 * @param a, b 95 * The indices of the elements to be swapped. 96 * @post The elements at indices a and b of the array of indices are 97 * swapped. 98 * | new.indexes[a] = indexes[b] 99 * | new.indexes[b] = indexes[a] 100 */ 101 private void swap(final int a, final int b) { 102 final int temp = this.indices[a]; 103 this.indices[a] = this.indices[b]; 104 this.indices[b] = temp; 105 } 106 107 108 // protected int initialiseTotal(int n, int r) { 109 // throw new UnsupportedOperationException("Not supported yet."); 110 //} 111 112 }