Arraylist Shuffle算法使用一个键
Arraylist Shuffle algorithm using a key
我如何在 C# ArrayList 中编写一个可逆随机播放算法,它使用一个键来随机播放并且可以反转到原始状态?
您可以使用KeyValuePair。您可以在以下网站上获得详细说明:http://www.dotnetperls.com/shuffle
但是如果你想反转它,我建议使用数据表。在第一列中,您可以使用原始排序顺序(可能是整数),在第二列中,您可以创建随机数。在第三列中,您可以拥有需要排序的值。然后使用按第二列排序进行随机播放,然后按第一列排序将其还原。
这里有一个简单的方法,只需要你存储你的"key",并且不改变洗牌算法。
使用哪种随机播放算法并不重要,只要你能重现它,这意味着如果你使用相同的密钥或种子,并且运行两次随机播放算法,它将完全相同地随机播放两次都是这样。
如果您可以使用密钥或随机播放算法的种子来做到这一点,那么您就可以开始了。
为了反转它,你所要做的就是打乱一个整数数组,打乱之前数组中的值对应于每个元素的索引。洗牌后,使用与上面相同的键或种子,您现在有一个洗牌副本,其中每个值都是未洗牌数组中原始位置的索引。
举个例子
假设一个包含 4 个整数的数组,值为 0 到 3(索引 0 处的元素值为 0,索引 1 处的元素值为 1,依此类推)。
将这个打乱,得到这个数组:3,1,2,0。
这意味着打乱后的数组的第一个元素曾经位于索引 3,第二个元素位于索引 1,第三个位于索引 2,第四个位于索引 0。
private class myItem
{
public Int32 ID { get; set; }
public Int32 Rand { get; set; }
public String Value { get; set; }
}
private void Main(object sender, EventArgs e)
{
string[] array = new string[] { "alpha", "beta", "gamma", "delta" };
List<myItem> myArray = addKeys(array);//adds keys to array required for randomization and reversing
string[] randomarray = randomize(myArray);
string[] reversedarray = reverse(myArray);
}
private List<myItem> addKeys(string[] array)
{
Random random = new Random();
List<myItem> myArr = new List<myItem>();
for (int i = 0; i < array.Length; i++)
{
myArr.Add(new myItem { ID = i, Rand = random.Next(), Value = array[i] });
}
return myArr;
}
private string[] randomize(List<myItem> myArray)
{
return (from item in myArray
orderby item.Rand
select item.Value).ToArray();
}
private string[] reverse(List<myItem> myArray)
{
return (from item in myArray
orderby item.ID
select item.Value).ToArray();
}
Shuffling
一个数组是通过多次交换数组内部的元素来完成的。
如果你拿一个数组,交换元素,然后再次交换它们,但以你最初交换它们的相反顺序,你会得到原来的数组。
这些洗牌位置可以从PRNG
(Pseudorandom number generator)生成。对于给定的 seed
,PNRG
将始终生成相同的数字:那将是您的 "key".
下面是一些使用该想法的代码(Fisher Yates 用于随机播放):
public static void Shuffle(ArrayList list, int seed, bool reverse = false)
{
Random rng = new Random(seed);
List<Tuple<int, int>> swaps = new List<Tuple<int, int>>();
int n = list.Count;
//prepare swapping positions
while (n > 1) {
n--;
int k = rng.Next(n + 1);
swaps.Add(new Tuple<int, int>(k, n));
}
//reverse if needed
if(reverse)
swaps.Reverse();
//swap the items
foreach(Tuple<int, int> swap in swaps)
{
object value = list[swap.Item1];
list[swap.Item1] = list[swap.Item2];
list[swap.Item2] = value;
}
}
用法:
ArrayList a = new ArrayList();
int key = 2742;
Shuffle(a, key);
Shuffle(a, key, true);
请注意,如果您不希望密钥是一个整数,而是一个字符串,您可以使用完全相同的方法,但整数使用 "somekey".GetHashCode()
我如何在 C# ArrayList 中编写一个可逆随机播放算法,它使用一个键来随机播放并且可以反转到原始状态?
您可以使用KeyValuePair。您可以在以下网站上获得详细说明:http://www.dotnetperls.com/shuffle
但是如果你想反转它,我建议使用数据表。在第一列中,您可以使用原始排序顺序(可能是整数),在第二列中,您可以创建随机数。在第三列中,您可以拥有需要排序的值。然后使用按第二列排序进行随机播放,然后按第一列排序将其还原。
这里有一个简单的方法,只需要你存储你的"key",并且不改变洗牌算法。
使用哪种随机播放算法并不重要,只要你能重现它,这意味着如果你使用相同的密钥或种子,并且运行两次随机播放算法,它将完全相同地随机播放两次都是这样。
如果您可以使用密钥或随机播放算法的种子来做到这一点,那么您就可以开始了。
为了反转它,你所要做的就是打乱一个整数数组,打乱之前数组中的值对应于每个元素的索引。洗牌后,使用与上面相同的键或种子,您现在有一个洗牌副本,其中每个值都是未洗牌数组中原始位置的索引。
举个例子
假设一个包含 4 个整数的数组,值为 0 到 3(索引 0 处的元素值为 0,索引 1 处的元素值为 1,依此类推)。
将这个打乱,得到这个数组:3,1,2,0。
这意味着打乱后的数组的第一个元素曾经位于索引 3,第二个元素位于索引 1,第三个位于索引 2,第四个位于索引 0。
private class myItem
{
public Int32 ID { get; set; }
public Int32 Rand { get; set; }
public String Value { get; set; }
}
private void Main(object sender, EventArgs e)
{
string[] array = new string[] { "alpha", "beta", "gamma", "delta" };
List<myItem> myArray = addKeys(array);//adds keys to array required for randomization and reversing
string[] randomarray = randomize(myArray);
string[] reversedarray = reverse(myArray);
}
private List<myItem> addKeys(string[] array)
{
Random random = new Random();
List<myItem> myArr = new List<myItem>();
for (int i = 0; i < array.Length; i++)
{
myArr.Add(new myItem { ID = i, Rand = random.Next(), Value = array[i] });
}
return myArr;
}
private string[] randomize(List<myItem> myArray)
{
return (from item in myArray
orderby item.Rand
select item.Value).ToArray();
}
private string[] reverse(List<myItem> myArray)
{
return (from item in myArray
orderby item.ID
select item.Value).ToArray();
}
Shuffling
一个数组是通过多次交换数组内部的元素来完成的。
如果你拿一个数组,交换元素,然后再次交换它们,但以你最初交换它们的相反顺序,你会得到原来的数组。
这些洗牌位置可以从PRNG
(Pseudorandom number generator)生成。对于给定的 seed
,PNRG
将始终生成相同的数字:那将是您的 "key".
下面是一些使用该想法的代码(Fisher Yates 用于随机播放):
public static void Shuffle(ArrayList list, int seed, bool reverse = false)
{
Random rng = new Random(seed);
List<Tuple<int, int>> swaps = new List<Tuple<int, int>>();
int n = list.Count;
//prepare swapping positions
while (n > 1) {
n--;
int k = rng.Next(n + 1);
swaps.Add(new Tuple<int, int>(k, n));
}
//reverse if needed
if(reverse)
swaps.Reverse();
//swap the items
foreach(Tuple<int, int> swap in swaps)
{
object value = list[swap.Item1];
list[swap.Item1] = list[swap.Item2];
list[swap.Item2] = value;
}
}
用法:
ArrayList a = new ArrayList();
int key = 2742;
Shuffle(a, key);
Shuffle(a, key, true);
请注意,如果您不希望密钥是一个整数,而是一个字符串,您可以使用完全相同的方法,但整数使用 "somekey".GetHashCode()