All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javarosa.xform.parse.FisherYates Maven / Gradle / Ivy

The newest version!
package org.javarosa.xform.parse;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Random;

/**
 * This class implements the Fisher-Yates
 * list shuffling algorithm.
 * 

* Combined with the {@link ParkMiller} Random Number Generator * implementation on this library, cross-platform reproducible results * can be guaranteed. *

* Verified compatible libraries are: *

*

* Using other libraries won't guarantee reproducible results. *

* The main difference between this implementation and the native * {@link java.util.Collections#shuffle} consist on the way this one * selects which elements to swap on each iteration. See inlined comments * for more information. */ public class FisherYates { /** * Shuffle the input list of elements using a {@link Random} Random * Number Generator instance to decide which positions get swapped * on each iteration. * * @param input {@link List} of elements to be shuffled * @param Type parameter of the input {@link List} of elements * @return A new {@link List} of elements, containing the same elements * as in the input {@link List}, but in a different order. */ @SuppressWarnings("unchecked") public static List shuffle(List input) { return shuffle(input, new Random()); } /** * Shuffle the input list of elements using a {@link ParkMiller} Random * Number Generator instance to decide which positions get swapped * on each iteration. *

* Use the same seed for the RNGs when reproducible results are required. * * @param input {@link List} of elements to be shuffled * @param seed {@link Long} number to use as seed of the RNG * @param Type parameter of the input {@link List} of elements * @return A new {@link List} of elements, containing the same elements * as in the input {@link List}, but in a different order. */ @SuppressWarnings("unchecked") public static List shuffle(List input, long seed) { return shuffle(input, new ParkMiller(seed)); } /** * Shuffle the input list of elements using a {@link Random} Random * Number Generator instance to decide which positions get swapped * on each iteration. *

* Use the same seed for the RNGs when reproducible results are required. * * Warning: It's recommended to use {@link #shuffle(List, long)} * instead, to ensure you are using a cross-platform RNG like {@link ParkMiller}. * * @param input {@link List} of elements to be shuffled * @param random {@link Random} instance with the RNG to be used * @param Type parameter of the input {@link List} of elements * @return A new {@link List} of elements, containing the same elements * as in the input {@link List}, but in a different order. */ @SuppressWarnings("unchecked") public static List shuffle(List input, Random random) { // The algorithm creates an output array with the shuffled elements int size = input.size(); Object[] inputArr = input.toArray(); Object[] outputArr = new Object[size]; for (int i = 0; i < size; ++i) { // This is the main difference with Collections.shuffle() // To make this version cross-platform, we need to decide the // target index using the next double in our PRNG to let // languages like JavaScript, where numbers are always represented // with IEE754 double precission floating point decimals. int j = Double.valueOf(random.nextDouble() * (i + 1)).intValue(); if (j != i) // Make room for input[i] at output[j] outputArr[i] = outputArr[j]; // Take input[i] outputArr[j] = inputArr[i]; } // Once the output array is created, we set the output list // iterator with the elements in the order they appear List output = new ArrayList<>(input); ListIterator it = output.listIterator(); for (Object e : outputArr) { it.next(); it.set(e); } return output; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy