我试图取消混合洗牌列表。我无法弄清楚如何实现这一目标。
public static void main(String[] args) {
// Setup random
Random rand = new Random();
rand.setSeed(5);
// Setup list
ArrayList<Character> list = new ArrayList<Character>(Arrays.asList('v','y','2','w','9','n','8','v','a'));
// Compound shuffle list
for(int i=0;i<5;i++)
Collections.shuffle(list, rand);
// un-shuffle list
// TODO
}
还有我的不洗牌方法。
private static void unshuffle(ArrayList<?> list, Random rand) {
// Create the sequence backwards
int[] seq = new int[list.size()];
for(int i=seq.length; i>1; i--)
seq[i-1] = rand.nextInt(i);
// Traverse the sequence and swapping it inversely
for (int i=0; i<seq.length; i++)
Collections.swap(list, i, seq[i]);
}
编辑:修复ArrayList。
答案 0 :(得分:3)
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList("A", "B", "C", "D", "E", "F", "G"));
compoundShuffle(list, 8, 13);
compoundUnshuffle(list, 8, 13);
System.out.println(list);
}
public static void compoundShuffle(List<?> list, int repetition, long seed) {
Random rand = new Random(seed);
for (int i = 0; i < repetition; i++)
Collections.shuffle(list, rand);
}
public static void compoundUnshuffle(List<?> list, int repetition, long seed) {
helper(list, repetition, seed);
}
private static <E> void helper(List<E> list, int repetition, long seed) {
List<Integer> indices = new ArrayList<Integer>();
int size = list.size();
for (int i = 0; i < size; i++)
indices.add(i);
compoundShuffle(indices, repetition, seed);
List<E> copy = new ArrayList<E>(list);
for (int i = 0; i < size; i++)
list.set(indices.get(i), copy.get(i));
}
}
答案 1 :(得分:2)
您需要了解的两件事情:
如果使用相同的种子创建了两个Random实例,那么 为每个方法调用相同的方法调用,它们将生成和 返回相同的数字序列。
此实现从最后一个向后遍历列表 元素到第二个,反复交换随机选择 元素进入&#34;当前位置&#34;。元素是随机选择的 从列表中从第一个元素到第一个元素的部分 当前位置,包括在内。
凭借这些知识和一两个图表,您应该能够弄清楚如何扭转行为。
答案 2 :(得分:0)
如果您在改组之前知道Random函数的初始种子,那么如果使用相同的种子调用它,确实可以进行去混洗。
事实上,seed
可以被视为此自定义(所以不是一个好的选择)加密算法的加密密钥。
假设您正在使用Fisher-Yates混洗算法(我认为Collections.shuffle显然使用),请尝试以下算法进行混洗和去混洗。它适用于int [],将其更改为Object []。
// implementing Fisher–Yates shuffling using a seed
public static void shuffleArray(int[] ar, int seed) {
Random r = new Random(seed);
for (int i = ar.length - 1; i > 0; i--) {
int index = r.nextInt(i + 1);
// simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
// implementing Fisher–Yates deShuffler
//(you should know the **seed** used for shuffling - this is the decryption key)
public static void deShuffleArray(int[] ar, int seed) {
//rebuild your random number sequence
Random r = new Random(seed);
int[] randoms = new int[ar.length-1];
int j = 0;
for (int i = ar.length - 1; i > 0; i--) {
randoms[j++] = r.nextInt(i + 1);
}
//deShuffling
for (int i = 1; i < ar.length; i++) {
//use the random values backwards
int index = randoms[ar.length - i - 1];
// simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}