How can I make random numbers that never repeat in array? - c#

listBox1.Items.Clear();
int[] sayısal = new int[6];
Random rastgele = new Random();
for (int i = 0; i < 6; i++)
{
do
{
sayısal = rastgele.Next(1, 50);
}
while (listBox1.Items.IndexOf(sayısal) != -1);
listBox1.Items.Add(sayısal);
}
When I did like this, I take an error that calls
"Cannot implicitly convert type 'int' to 'int[]' "
in line "sayısal = rastgele.Next(1, 50);". What can I do for it?

You can generate sequence 1..50 and shuffle it (i.e. sort by random value):
Random rastgele = new Random();
int[] sayısal = Enumerable.Range(1, 50) // generate sequence
.OrderBy(i => rastgele.Next()) // shuffle
.Take(6) // if you need only 6 numbers
.ToArray(); // convert to array
Your code is not working, because you are trying to assign generated item to array variable.
sayısal = rastgele.Next(1, 50);
It should be instead:
do {
sayısal[i] = rastgele.Next(1, 50);
} while(listBox1.Items.IndexOf(sayısal[i]) != -1);
As I already pointed in comments, it's better to separate UI logic and array generation. I.e.
// generate array (optionally move to separate method)
int itemsCount = 6;
int[] items = new int[itemsCount]; // consider to use List<int>
Random random = new Random();
int item;
for(int i = 0; i < itemsCount; i++)
{
do {
item = random.Next(1, 50);
} while(Array.IndexOf(items, item) >= 0);
items[i] = item;
}
// display generated items
listBox1.Items.Clear();
for(int i = 0; i < items.Length; i++) // or use foreach
listBox1.Items.Add(items[i]);

Because Random.Next method returns an int, not int[]. And there is no implicit conersation from int[] to int.
Return Value
Type: System.Int32
A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not maxValue. If minValue equals maxValue, minValue is returned.
If you want to fill your array, you can use Enumerable.Range like lazyberezovsky mentioned.

This method takes an integer array and randomly sorts them.
So fill an array with a loop then use this to randomly sort the array.
You should credit one of the others as they were first to post with valid answers. I just thought another way to do this would be good.
amount is the amount of times you want the array to randomize. The higher the number the higher the chance of numbers being random.
private Random random = new Random();
private int[] randomizeArray(int[] i, int amount)
{
int L = i.Length - 1;
int c = 0;
int r = random.Next(amount);
int prev = 0;
int current = 0;
int temp;
while (c < r)
{
current = random.Next(0, L);
if (current != prev)
{
temp = i[prev];
i[prev] = i[current];
i[current] = temp;
c++;
}
}
return i;
}

Be careful in your choice of data structures and algorithms, pick the wrong one and you'll wind up with O(n^2). A reasonable solution IMHO is a typed hash table (i.e. dictionary) which will give you O(n):
Random rnd = new Random();
var numbers = Enumerable
.Range(1, 1000000)
.Aggregate(new Dictionary<int, int>(), (a, b) => {
int val;
do {val = rnd.Next();} while (a.ContainsKey(val));
a.Add(val, val);
return a;
})
.Values
.ToArray();
Still not ideal though as performance depends on the array size being significantly smaller than the set of available numbers and there's no way to detect when this condition isn't met (or worse yet when it's greater, in which case the algorithm will go into an infinite loop).

Related

Adding specific numbers from one sequence to another

I feel like this task should not be done this way...
My sequenceY length is not equal to number of steam numbers because you can't assign int[] length with int that have 0 as a starting value.
Therefore my sequenceY have a lot of 0 inside and I can't print the whole sequence. I even tried adding this after for loop:
sequenceY = new int[steamnumbercounter];
But it didn't work ... Why ?
My other question is how do programmers deal with sequences that have unknown length?
I managed to print only steam numbers but the task says print sequenceY not only part of it.
// 4. sequenceX[20] is made of random numbers from 1 to 30 ,
// sequenceY is made of steam numbers from sequenceX. Print sequneceY.
int[] nizx = new int[20];
int[] nizy = new int[20];
int n = 0;
int steamnumbercounter = 0;
Random rnd = new Random();
for (int i = 0; i < nizx.Length; i++)
{
nizx[i] = rnd.Next(1, 30);
if (nizx[i]%2==0)
{
nizy[n] = nizx[i];
n++;
steamnumbercounter++;
}
Console.Write("{0} , ", nizx[i]);
}
for (int i = 0; i < steamnumbercounter; i++)
{
Console.WriteLine("{0} , ",nizy[i]);
}
Partial code review along with an answer.
But it didn't work ... Why ?
That code didn't work because you're reassigning sequenceY to a completely new value.
My other question is how do programmers deal with sequences that have unknown length?
So, with that known we can do a few things here: create an array and use Array.Resize, use a List<T>, fill the initial array then swap it for one of the right size which is filled.
I'm going to assume a "steam" number is an even one.
Your naming is not good: nizx and nizy don't convey the meaning or line up with the problem.
I'm going to demonstrate the last option (since you stated that you don't know how to use many of the moderately complex parts of .NET in this class yet, which is fine): fill the initial array and swap it for a new one. This will run in O(n^2) time (sorta).
So, let's start with our source array.
int[] sequenceX = new int[20];
Next we'll define our destination array to be the same size as our source array. (This is the maximum number of values that could be stored in it, we'll shrink it later.)
int[] sequenceY = new int[sequenceX.Length];
Then we need a variable to hold how many numbers we found that meet our criteria:
int steamNumbers = 0;
And lastly, our Random.
Random random = new Random();
Then, we look through all our sequenceX as you did, but we'll update the logic a bit.
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(1, 30);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
So our code looks almost the same as yours, but we have one more thing to do: since you only want sequenceY to contain steamNumbers we have to shrink it or something.
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
Now sequenceY only has your steam numbers in it.
Final code:
int[] sequenceX = new int[20];
int[] sequenceY = new int[sequenceX.Length];
int steamNumbers = 0;
Random random = new Random();
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(1, 30);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
// Print your `sequenceY` here.
You could extract this to a method pretty easily as well:
public int[] GetSteamNumbers(int sequenceCount, int randomMinimum, int randomMaximum)
{
int[] sequenceX = new int[sequenceCount];
int[] sequenceY = new int[sequenceX.Length];
int steamNumbers = 0;
Random random = new Random();
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(randomMinimum, randomMaximum);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
return sequenceY;
}
And then call it with:
int[] steamNumbers = GetSteamNumbers(20, 1, 30);
Of course, for the more advanced users (this doesn't help you, but it may help others) we can do something as follows using LINQ:
var random = new Random();
var sequenceY = Enumerable.Range(1, 20)
.Select(x => random.Next(1, 30))
.Where(x => x % 2 == 0)
.ToArray();
Which should have the same effect. (Just demonstrating that there are still things in C# to look forward to in the future.)
Disclaimer: I wrote this entire answer outside of the IDE and without actually compiling it, I make no guarantees to the accuracy of the code but the procedure itself should be fairly straight forward.
The thing with arrays in C# is that they are of fixed size.
You'll have to iterate through and re-create it or use a IEnumerable that has dynamic sizes, such as Lists.
Solution here would be to use a List that contains your integers and then you would use nizx.Add(rnd.Next(1, 30));
Elaborating on my comment above: You can create a 'fake' list by concatenating the values you need in a string, separated by commas. The string.Split(',') will give you the resulting array that you need.
Given a string of form "a,b,c,d" string.Split(',') will create the array ["a","b,"c","d"]. The code:
{
int[] nizx = new int[20];
string numberString = string.Empty;
int n = 0;
Random rnd = new Random();
for (int i = 0; i < nizx.Length; i++)
{
nizx[i] = rnd.Next(1, 30);
if (nizx[i] % 2 == 0)
{
numberString += nizx[i] + ",";
n++;
}
}
var numberArray = numberString.Split(',');
for (int i = 0; i < n; i++)
{
Console.WriteLine("{0} , ", numberArray[i]);
}
}

How do I order the digits 1-10 randomly into an array and then call each part of the array one at a time?

So basically, I need to have the numbers 1-10 randomly ordered upon startup into an array, and on when the form loads, it should load the first number. Each time the user clicks a button, it will load the info associated with the next number.
This is my code, but for some reason it generates a number that is not an integer a lot.
Random rng = new Random(10);
int[] QuestionOrder = new int[10];
for (int i = 0; i < QuestionOrder.Length; i++)
{
int temp = rng.Next(1,10);
while(!(QuestionOrder.Contains(temp)))
{
QuestionOrder[i] = temp;
}
}
each time it generates a number 1 - 10 and checks if it has already been stored in the array, if not, stores it and runs again.
For some reason, its generating numbers that are not integers 1 - 10, and i cant figure out why.
I think you need to overwrite the value of temp inside the while loop and change your range to 1-11 instead of 1-10 and use an if statement before the loop:
int temp = rng.Next(1, 11);
if(!QuestionOrder.Contains(temp)) QuestionOrder[i] = temp;
else
{
while(QuestionOrder.Contains(temp))
{
temp = rng.Next(1, 11);
QuestionOrder[i] = temp;
}
}
You could generate ten random numbers first, then iterate through them.
var rnd = new Random(Environment.TickCount);
var arr = Enumerable.Range(1,10).OrderBy(x => rnd.Next()).ToArray();
this does work nicely
static void Main(string[] args)
{
Random random = new Random();
var range = Enumerable.Range(1, 10).ToList();
int[] rnd = new int[10];
int j = 0;
do
{
int i = random.Next(0, range.Count);
rnd[j++] = range[i];
range.RemoveAt(i);
}
while(range.Count > 1);
rnd[j] = range[0];
}
less cpu intensive than using a contains in a loop
First, your seed is always the same. Either omit it, or use maybe the current date.
Second, you're generating numbers between 1 and 9, so you will never get 10, and one of your array cell will stay empty.
Change temp = rng.Next(1, 11);
As others have pointed out, you're not regenerating a new number when the generated number is already present in the list, leaving you with various default values of 0 in your result.
There are however better ways to 'shuffle' a list of numbers, see Randomize a List in C#:
public static IList<T> Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
Which you can call like this:
IList<int> QuestionOrder = Enumerable.Range(1, 10)
.ToList()
.Shuffle();
The best algorithm to shuffle an array is Knuth-Fisher-Yates, that can be implemented as follows:
public static class Extensions
{
public static void Shuffle<T>(this IList<T> list, Random rand)
{
for (int i = list.Count - 1; i > 0; i--)
{
int n = rand.Next(i + 1);
int tmp = list[i];
list[i] = list[n];
list[n] = tmp;
}
}
}
Usage:
// to get different random sequences every time, just remove the seed (1234)
Random rng = new Random(1234);
// create an array containing 1,2...9,10
int[] questionOrder = Enumerable.Range(1,10).ToArray();
// shuffle the array
questionOrder.Shuffle(rand);
Side note:
To know why Knuth-Fisher-Yates algorithm is better than a naive implementation, read this interesting post by Jeff

Select from a range but exclude certain numbers [duplicate]

This question already has answers here:
How to get a random number from a range, excluding some values
(11 answers)
Closed 9 years ago.
Is it possible to pick a random number from a given range (1-90), but exclude certain numbers. The excluded numbers are dynamically created but lets say they are 3, 8, and 80.
I have managed to create random number generator but couldn't identify any functions that let me fulfill my requirements.
Random r = new Random();
this.num = r.Next(1, 90);
The numbers which are to be excluded are previously generated numbers. So, if the random number is one, this would then get added to the excluded numbers list.
Using some handy extension methods here, you can create a range of numbers and select randomly from that rage. For example, with these extension methods:
public static T RandomElement(this IEnumerable<T> enumerable)
{
return enumerable.RandomElementUsing(new Random());
}
public static T RandomElementUsing(this IEnumerable<T> enumerable, Random rand)
{
int index = rand.Next(0, enumerable.Count());
return enumerable.ElementAt(index);
}
You can apply these to a filtered range of numbers:
var random = Enumerable.Range(1, 90).Except(arrayOfRemovedNumbers).RandomElement();
Create a container which holds the numbers you do not want:
var excludedNumbers = new List<int> { 1, 15, 35, 89 };
Then use do something like:
Random random = new Random();
int number;
do
{
number = r.Next(1, 90);
} while (excludedNumbers.Contains(number));
// number is not in the excluded list now
Might not be the best choice but you can use a while loop to check the numbers you don't want
Random r = new Random();
this.num = r.Next(1, 90);
do
{
this.num = r.Next(1, 90);
}
while (this.num == 3 || this.num == 8 || this.num == 90);
For much numbers you can use an array or a list and loop through them
int[] exclude = { 3, 8, 90, 11, 24 };
Random r = new Random();
this.num = r.Next(1, 90);
do
{
this.num = r.Next(1, 90);
}
while (exclude.Contains(this.num));
Your latest update, which implies that each value can only be selected once, makes the problem easy.
Create a collection of values within the range.
Randomly shuffle the collection.
To"randomly" select an item, just return the first item in the collection, and remove it from the collection.
Random r = new Random();
this.num = r.Next(1, 90);
int excluded[] = new int[] { 3,8,80 }; // list any numbers in this array you want to exclude
for (int i = 0; i < excluded.Length; i++)
{
if (this.num == excluded[i])
{
this.num = r.Next(1, 90); // or you can try doing something else here
}
}
This solution does it in O(n) worst case where n is your list of exclusions, and constant memory. The code is a little longer but might be relevant if you:
Possibly have a huge list of exclusions
Need to run this many times
Have a large range
It preserves the random distribution in the sense that it actually skips the exclusion list and generates a random number within the range excluding the set.
This is the implementation:
private static int RandomInRangeExcludingNumbers(Random random, int min, int max, int[] excluded)
{
if (excluded.Length == 0) return random.Next(min, max);
//array should be sorted, remove this check if you
//can make sure, or sort the array before using it
//to improve performance. Also no duplicates allowed
//by this implementation
int previous = excluded[0];
for (int i = 1; i < excluded.Length; i++)
{
if (previous >= excluded[i])
{
throw new ArgumentException("excluded array should be sorted");
}
}
//basic error checking, check that (min - max) > excluded.Length
if (max - min <= excluded.Length)
throw new ArgumentException("the range should be larger than the list of exclusions");
int output = random.Next(min, max - excluded.Length);
int j = 0;
//set the start index to be the first element that can fall into the range
while (j < excluded.Length && excluded[j] < min) j++;
//skip each number occurring between min and the randomly generated number
while (j < excluded.Length && excluded[j] <= output)
{
j++;
output++;
while (excluded.Contains(output))
output++;
}
return output;
}
And a test function to make sure it works (over 100k elements)
private static void Test()
{
Random random = new Random();
int[] excluded = new[] { 3, 7, 80 };
int min = 1, max = 90;
for (int i = 0; i < 100000; i++)
{
int randomValue = RandomInRangeExcludingNumbers(random, min, max, excluded);
if (randomValue < min || randomValue >= max || excluded.Contains(randomValue))
{
Console.WriteLine("Error! {0}", randomValue);
}
}
Console.WriteLine("Done");
}
Make sure excludedNumbers is a HashSet for best performance.
var random = new Random();
var exludedNumbers = new HashSet<int>(new int[] { 3, 8, 80});
var randomNumber = (from n in Enumerable.Range(int.MinValue, int.MaxValue)
let number = random.Next(1, 90)
where !exludedNumbers.Contains(number)
select number).First();

Generate some unique numbers and put into array

I'm trying to create a method that produces 10 unique random numbers, but the numbers are not unique, I get several duplicates! How can I improve the code to work as I want?
int[] randomNumbers = new int[10];
Random random = new Random();
int index = 0;
do
{
int randomNum = random.Next(0, 10);
if (index == 0)
{
randomNumbers[0] = randomNum;
index++;
}
else
{
for (int i = 0; i < randomNumbers.Length; i++)
{
if (randomNumbers[i] == randomNum)
break;
else
{
randomNumbers[index] = randomNum;
index++;
break;
}
}
}
}
while (index <= 9);
foreach (int num in randomNumbers)
System.Console.Write(num + " ");
EDIT 2: I have corrected all errors now, but this code isn't working becuase the numbers are not unique! I have updated my code above to the latest version. I preciate some help to solve this! Thanks!
The simplest way to have this is to have an array of the numbers you want (i.e. 1-10) and use a random shuffling algorithm.
The Fisher-Yates shuffle is the easiest way to do this.
EDIT:
Here's a link to a C# implementation: http://www.dotnetperls.com/fisher-yates-shuffle
random.next(0, 10) returns a random number between 0 and 10. It can happen, that it returns the same number multiple times in a row and it is not guaranteed, that you get every number between 0 and 10 exactly one time, when you call it 10 times.
What you want is a list of numbers, every number is unique, between 0 and 9 (or 1 and 10). A possible solution to this would be something like this:
//Create the list of numbers you want
var list = new List<int>();
for(var x = 0; x < 10; x++)
{
list.Add(x);
}
var random = new Random();
//Prepare randomized list
var randomizedList = new List<int>();
while(list.Length > 0)
{
//Pick random index in the range of the ordered list
var index = random.Next(0, list.Length);
//Put the number from the random index in the randomized list
randomizedList.Add(list[index]);
//Remove the number from the original list
list.RemoveAt(index);
}
Explained in words, this is what you do:
Create the list with all the numbers, that your final list should contain
Create a second empty list.
Enter a loop. The loop continues, as long as the ordered list still has numbers in it.
Pick a random index between 0 and list.Length
Put this random number in the randomized list
Remove the item at the index position from the ordered list.
Like this you create the set of numbers you want to have in your randomized list and then always pick a random entry from the ordered list. With this technique, you can also achieve, that certain values occur multiple time in the list.
I'm not sure if my code compiles against c#, as I currently do not have visual studio running here, but I think the code should be mostly correct.
Something like this?
const int maxNumbers = 10;
List<int> numbers = new List<int>(maxNumbers);
for (int i = 0; i < maxNumbers; i++)
{
numbers.Add(i);
}
Random r = new Random();
while (numbers.Count > 0)
{
int index = r.Next(numbers.Count);
Console.Write("{0} ", numbers[index]);
numbers.RemoveAt(index);
}
Console.WriteLine();
Edit: For any random numbers:
const int maxNumbers = 10;
const int biggestNumbers = 10000;
List<int> numbers = new List<int>(maxNumbers);
Random r = new Random();
while (numbers.Count < maxNumbers)
{
int index = r.Next(biggestNumbers);
if (numbers.IndexOf(index) < 0)
{
numbers.Add(index);
Console.Write("{0} ", index);
}
}
Console.WriteLine();

Most efficient way to randomly "sort" (Shuffle) a list of integers in C#

I need to randomly 'sort' a list of integers (0-1999) in the most efficient way possible. Any ideas?
Currently, I am doing something like this:
bool[] bIndexSet = new bool[iItemCount];
for (int iCurIndex = 0; iCurIndex < iItemCount; iCurIndex++)
{
int iSwapIndex = random.Next(iItemCount);
if (!bIndexSet[iSwapIndex] && iSwapIndex != iCurIndex)
{
int iTemp = values[iSwapIndex];
values[iSwapIndex] = values[iCurIndex];
values[iCurIndex] = values[iSwapIndex];
bIndexSet[iCurIndex] = true;
bIndexSet[iSwapIndex] = true;
}
}
A good linear-time shuffling algorithm is the Fisher-Yates shuffle.
One problem you'll find with your proposed algorithm is that as you near the end of the shuffle, your loop will spend a lot of time looking for randomly chosen elements that have not yet been swapped. This may take an indeterminate amount of time once it gets to the last element to swap.
Also, it looks like your algorithm will never terminate if there are an odd number of elements to sort.
static Random random = new Random();
public static IEnumerable<T> RandomPermutation<T>(IEnumerable<T> sequence)
{
T[] retArray = sequence.ToArray();
for (int i = 0; i < retArray.Length - 1; i += 1)
{
int swapIndex = random.Next(i, retArray.Length);
if (swapIndex != i) {
T temp = retArray[i];
retArray[i] = retArray[swapIndex];
retArray[swapIndex] = temp;
}
}
return retArray;
}
modified to handle lists or other objects implementing IEnumerable
We can make an extension method out of this to get a Random enumerator for any IList collection
class Program
{
static void Main(string[] args)
{
IList<int> l = new List<int>();
l.Add(7);
l.Add(11);
l.Add(13);
l.Add(17);
foreach (var i in l.AsRandom())
Console.WriteLine(i);
Console.ReadLine();
}
}
public static class MyExtensions
{
public static IEnumerable<T> AsRandom<T>(this IList<T> list)
{
int[] indexes = Enumerable.Range(0, list.Count).ToArray();
Random generator = new Random();
for (int i = 0; i < list.Count; ++i )
{
int position = generator.Next(i, list.Count);
yield return list[indexes[position]];
indexes[position] = indexes[i];
}
}
}
This uses a reverse Fisher-Yates shuffle on the indexes of the list we want to randomly enumerate through. Its a bit of a size hog (allocating 4*list.Count bytes), but runs in O(n).
As Greg pointed out the Fisher-Yates shuffle would be the best approach. Here is an implementation of the algorithm from Wikipedia:
public static void shuffle (int[] array)
{
Random rng = new Random(); // i.e., java.util.Random.
int n = array.length; // The number of items left to shuffle (loop invariant).
while (n > 1)
{
int k = rng.nextInt(n); // 0 <= k < n.
n--; // n is now the last pertinent index;
int temp = array[n]; // swap array[n] with array[k] (does nothing if k == n).
array[n] = array[k];
array[k] = temp;
}
}
The implementation above relies on
Random.nextInt(int) providing
sufficiently random and unbiased
results
I am not sure of the efficiency factor, but I have used something similar to the following, if you aren't opposed to using an ArrayList:
private ArrayList ShuffleArrayList(ArrayList source)
{
ArrayList sortedList = new ArrayList();
Random generator = new Random();
while (source.Count > 0)
{
int position = generator.Next(source.Count);
sortedList.Add(source[position]);
source.RemoveAt(position);
}
return sortedList;
}
Using this, you do not have to worry about the intermediate swapping.
To improve your efficiency you can keep a set of values/indices that have been swapped rather than a boolean for indicating they were swapped. Pick your randomized swap index from the remaining pool. When the pool is 0, or when you made it through the initial list then you are done. You don't have the potential to try to select a random swap index value.
When you do a swap, just remove them from the pool.
For the size of data you are looking at it is no big deal.
itemList.OrderBy(x=>Guid.NewGuid()).Take(amount).ToList()
ICR's answer is very fast, but the resulting arrays aren't distributed normally. If you want a normal distribution, here's the code:
public static IEnumerable<T> RandomPermutation<T>(this IEnumerable<T> sequence, int start,int end)
{
T[] array = sequence as T[] ?? sequence.ToArray();
var result = new T[array.Length];
for (int i = 0; i < start; i++)
{
result[i] = array[i];
}
for (int i = end; i < array.Length; i++)
{
result[i] = array[i];
}
var sortArray=new List<KeyValuePair<double,T>>(array.Length-start-(array.Length-end));
lock (random)
{
for (int i = start; i < end; i++)
{
sortArray.Add(new KeyValuePair<double, T>(random.NextDouble(), array[i]));
}
}
sortArray.Sort((i,j)=>i.Key.CompareTo(j.Key));
for (int i = start; i < end; i++)
{
result[i] = sortArray[i - start].Value;
}
return result;
}
Note that in my tests, this algorithm was 6 times slower than the one ICR provided, however this is the only way I could come up with to get a normal result distribution
Wouldn't something like this work?
var list = new[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
var random = new Random();
list.Sort((a,b)=>random.Next(-1,1));
what about :
System.Array.Sort(arrayinstance, RandomizerMethod);
...
//any evoluated random class could do it !
private static readonly System.Random Randomizer = new System.Random();
private static int RandomizerMethod<T>(T x, T y)
where T : IComparable<T>
{
if (x.CompareTo(y) == 0)
return 0;
return Randomizer.Next().CompareTo(Randomizer.Next());
}
voila!
Here is what I used.
This is surely not the fastest one, but it is probably good enough for most cases and most importantly, it is very simple.
IEnumerable<ListItem> list = ...;
Random random = new Random(); // important to not initialize a new random in the OrderBy() function
return list.OrderBy(i => random.Next());
You can use a NuGet package called ListShuffle (source code) to shuffle a list in a thread-safe way using the Fisher-Yates algorithm, with optional cryptographically-strong random.
var myList = new List<string>();
myList.Add("Item A");
myList.Add("Item B");
myList.Add("Item C");
myList.Shuffle();
or (less performant but cryptographically-strong)
var myList = new List<string>();
myList.Add("Item A");
myList.Add("Item B");
myList.Add("Item C");
myList.CryptoStrongShuffle();
I made a method using a temporary Hashtable, allowing the Hashtable's natural key sort to randomize. Simply add, read and discard.
int min = 1;
int max = 100;
Random random;
Hashtable hash = new Hashtable();
for (int x = min; x <= max; x++)
{
random = new Random(DateTime.Now.Millisecond + x);
hash.Add(random.Next(Int32.MinValue, Int32.MaxValue), x);
}
foreach (int key in hash.Keys)
{
HttpContext.Current.Response.Write("<br/>" + hash[key] + "::" + key);
}
hash.Clear(); // cleanup

Categories

Resources