
com.github.davidmoten.rx.internal.operators.Permutations Maven / Gradle / Ivy
package com.github.davidmoten.rx.internal.operators;
import java.util.Iterator;
import java.util.List;
public final class Permutations {
private Permutations() {
// prevent instantiation
}
public static Iterable> iterable(final List list) {
return new Iterable>() {
@Override
public Iterator> iterator() {
return new PermutationsSwapIterator(list);
}
};
}
public static Iterator> iterator(List list) {
return new PermutationsSwapIterator(list);
}
private static class PermutationsSwapIterator implements Iterator> {
/**
* After
* http://www.cut-the-knot.org/Curriculum/Combinatorics/JohnsonTrotter.
* shtml
*
*/
private final T[] values;
private final DirectedReference[] references;
@SuppressWarnings("unchecked")
public PermutationsSwapIterator(List list) {
this.values = (T[]) list.toArray();
this.references = new DirectedReference[list.size()];
for (int i = 0; i < this.references.length; i++) {
this.references[i] = new DirectedReference(-1, i);
}
}
private boolean isMobile(int index) {
if (index == 0 && references[index].direction == -1) {
return false;
} else if (index == references.length - 1 && references[index].direction == 1) {
return false;
} else if (references[index
+ references[index].direction].reference > references[index].reference) {
return false;
} else {
return true;
}
}
@Override
public boolean hasNext() {
for (int i = 0; i < references.length; i++) {
if (isMobile(i)) {
return true;
}
}
return false;
}
@Override
public Swap next() {
// find the largest mobile reference "chosen"
int chosen = Integer.MIN_VALUE;
int chosenIndex = -1;
for (int i = 0; i < references.length; i++) {
if (isMobile(i) && references[i].reference > chosen) {
chosen = references[i].reference;
chosenIndex = i;
}
}
// swaps it in the indicated direction
int neighbourIndex = chosenIndex + references[chosenIndex].direction;
Swap swap = new Swap(values[references[chosenIndex].reference],
values[references[neighbourIndex].reference]);
DirectedReference tmp = references[chosenIndex];
references[chosenIndex] = references[neighbourIndex];
references[neighbourIndex] = tmp;
// reverse the direction of all references larger than "chosen"
for (int i = 0; i < references.length; i++) {
if (references[i].reference > chosen) {
references[i].reverse();
}
}
return swap;
}
@Override
public void remove() {
throw new UnsupportedOperationException("cannot remove from permutations");
}
}
public static class Swap {
private final T left;
private final T right;
Swap(T left, T right) {
this.left = left;
this.right = right;
}
public T left() {
return left;
}
public T right() {
return right;
}
@Override
public String toString() {
return "Swap [left=" + left + ", right=" + right + "]";
}
}
private static class DirectedReference {
private final int reference;
private int direction;
DirectedReference(int direction, int reference) {
this.direction = direction;
this.reference = reference;
}
public void reverse() {
this.direction = -this.direction;
}
@Override
public String toString() {
String val = String.valueOf(reference);
String result = direction == -1 ? "<" + val : val + ">";
return result + String.valueOf(reference);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy