I want a class, that take in a possitive integer and produce a iterator that let me iterate through all possible of permutation of a list of possitive numbers under the positive
try this:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.IntStream;
public class Paermulator {
private final List<int[]> list = new ArrayList<>();
public Paermulator(int i) {
int[] array = IntStream.iterate(0, x -> x + 1)
.limit(i)
.toArray();
populateList(array, 0);
}
private void populateList(int[] array, int index) {
if (index >= array.length - 1) {
int[] temp = new int[array.length];
System.arraycopy(array, 0, temp, 0, array.length);
list.add(temp);
return;
}
for (int i = index; i < array.length; i++) {
int temp = array[index];
array[index] = array[i];
array[i] = temp;
populateList(array, index + 1);
temp = array[index];
array[index] = array[i];
array[i] = temp;
}
}
public List<int[]> getList() {
return list;
}
public Iterator<int []> getItrator() {
return list.iterator();
}
// main method is for testing output
public static void main(String[] args) {
//printing output
new Paermulator(5).getList().stream().forEach(x -> System.out.println(Arrays.toString(x)));
}
}
This class accepts an int in constructor and creates an array and pass the array to populateList
method this method populate the list with all possible permutations.
and you can get Iterator
using getIterator
method .
This is a better solution, inspired by https://stackoverflow.com/a/10117424/312172
To achieve, instead of getting a list of elements that are jumbled, we focus on the choices we make when deducting elements from the list. give the function a size, and a number that is smaller than factorial(size); it will return a sequence of choices we need to make to get the permutation.
for example:
getTheIndexOfSelection(100,5)-> for a list of 5 elements, we want the 100th permutation.
it should output: [4, 0, 2, 0, 0]
it means, remove the element at index 4, for the list that got removed, remove element at 0 ....
if the list is[1,2,3,4,5]; this will be the procujure:
[1,2,3,4,5] remove index 4 -> 5
[1,2,3,4] remove index 0 -> 1
[2,3,4] remove index 2 -> 4
[2,3] rovmove index 0 -> 2
[3] remove index 0 -> 3
all the element we removed sequentially is the permutation.
/**
* Feed this function a number, it gives you a sequence of choices
* to make a permutation.
* <br>
* if this return [0,0,0,0]
* it means remove element at 0, and then remove again... until
* reaches the end.
* @return
*
* @param
* len: the length of the list
* n: the number that got match to a certain permutation.
*/
public static int[] getTheIndexOfSelection(int n, int size)
{
int[] lst = new int[size];
return getTheIndexOfSelection( n, size, 0, lst);
}
private static int[] getTheIndexOfSelection(int n, int size, int index, int[] lst)
{
if(size==1)
{
int[] result = {0}; // a list of one element, you can only choose the one that is in it
// which is at index 0;
return result;
}
if(n >= factorial(size))return null; // This is not possible to do.
size-=1;
int firstchoice = n/factorial(size);
lst[index] = firstchoice;
n = n-firstchoice*factorial(size);
if(size>1)return getTheIndexOfSelection(n ,size, index+1, lst);
return lst;
}
This is a better solution because:
An implementation using Heap's Algorithm. It compute next permutations on the fly. And have only one array copying
import java.util.Arrays;
import java.util.Iterator;
class Permutator<E> implements Iterator<E[]>{
E[] arr1 = null;
E[] arr2 = null;
int size;
int[] stack = null;
int index = 0;
public Permutator( E[] arr ){
if( arr.length > 0 ){
arr1 = arr;
size = arr1.length;
arr2 = Arrays.copyOf(arr1, size);
stack = new int[size];
Arrays.fill(stack, 0);
}
}
@Override
public boolean hasNext() {
return (null != arr1 && arr1.length > 0);
}
@Override
public E[] next() {
// start computing.
// We will return original array as value of last permutation.
// This is to make "hasNext() " implementation easy.
updateValue();
return arr2;
}
protected void updateValue(){
boolean bret = false;
for( ; index < size ; ){
if( stack[index] < index ){
if( index %2 == 0 ){
swap(0, index);
}else{
swap(stack[index], index);
}
stack[index]++;
index = 0;
bret = true;
break;
}else{
stack[index] = 0;
index++;
}
}
if( !bret ){
// No more permutation available.
// Set the original array as return value.
// Also set arr1 = null , so that hasNext() will return false for next test
arr2 = arr1;
arr1 = null;
}
}
private void swap (final int i, final int j) {
E temp = arr2[i];
arr2[i] = arr2 [j];
arr2[j] = temp;
}
}
Usage:
public static void main(String[] args) {
Permutator<Integer> perm = new Permutator<Integer>(new Integer[]{1,2,3, 4, 5});
int count = 0;
while(perm.hasNext()){
System.out.println(Arrays.toString(perm.next()));
count++;
}
System.out.println("total: " + count);
}