Files
Gruppe-01-fin/Projekte/common/src/main/java/pp/util/RandomPositionIterator.java
2024-09-18 17:04:31 +02:00

91 lines
2.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Random;
/**
* An iterator that creates a random permutation of positions (x, y) where x and y are integer values
* in the range {0, ..., width-1} x {0, ..., height-1}. All permutations are uniformly distributed
* using the FisherYates shuffle (also known as Knuth shuffle).
*
* @param <T> the type of elements returned by this iterator
*/
public class RandomPositionIterator<T> implements Iterator<T> {
private final Random random = new Random();
private final int height;
private final Map<Integer, T> movedMap = new HashMap<>();
private int remaining;
private final Creator<T> creator;
/**
* Functional interface to create instances of type T.
*
* @param <T> the type of elements created by this creator
*/
public interface Creator<T> {
T create(int x, int y);
}
/**
* Creates a RandomPositionIterator for Position instances with float coordinates.
*
* @param width the width of the rectangle
* @param height the height of the rectangle
* @return a RandomPositionIterator for Position instances
*/
public static RandomPositionIterator<Position> floatPoints(int width, int height) {
return new RandomPositionIterator<>(FloatPoint::new, width, height);
}
/**
* Creates a new permutation iterator generating a random permutation of positions (x, y)
* where x and y are integer values in the range {0, ..., width-1} x {0, ..., height-1}.
*
* @param creator the creator to create instances of type T
* @param width the width of the rectangle
* @param height the height of the rectangle
*/
public RandomPositionIterator(Creator<T> creator, int width, int height) {
this.height = height;
this.remaining = width * height;
this.creator = creator;
}
@Override
public boolean hasNext() {
return remaining > 0;
}
@Override
public T next() {
if (hasNext()) {
final int idx = random.nextInt(remaining--); // note that remaining is decremented
final T result = getWhere(idx);
if (idx < remaining)
movedMap.put(idx, getWhere(remaining));
movedMap.remove(remaining);
return result;
}
throw new NoSuchElementException();
}
private T getWhere(int idx) {
final T movedWhere = movedMap.get(idx);
if (movedWhere != null)
return movedWhere;
final int x = idx / height;
final int y = idx % height;
return creator.create(x, y);
}
}