Random method return two values without duplicate - c#

I created two methods that take random values from database table
This method will return an integer random value
private int GetDayValue()
{
Random rnd = new Random();
List<int> days = GetDays();
int r = rnd.Next(days.Count);
return days[r];
}
This method will return also an integer random value
private int GetPeriodValue(string grd_id)
{
Random rnd = new Random();
List<int> periods = GetPeriods(grd_id);
int r = rnd.Next(periods.Count);
return periods[r];
}
Here there is a for loop will take random value from two methods
for (int z = 0; z <= secPortion; z++)
{
//here the random value of day
day = GetDayValue();
//here the random value of period
period = GetPeriodValue(grd_id);
//this method will insert the value on database table
SetFirstShot(teacher, sub, sec, period, day);
}
My question:
I want to create method will return random value of day and period together for example random value (ex: 3,5 ... 4,6 .... 1,1) and not repeated during the loop for example 4,6 will generated once time then another random value but if it 4,6 the method will create again a random value.

You can use a hash function instead that has a good random distribution aspect to it. A hash function with return the same value for the same inputs each time, while the results will "seem" random, which might be all the "randomness" you need.
using System;
using System.IO;
using System.Security.Cryptography;
// ...
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
using (var hash = MD5.Create())
{
writer.Write(day);
writer.Write(period);
var data = md5Hash.ComputeHash(stream.ToArray());
var randomNumber = BitConverter.ToInt32(data);
}
The added benefit is that you don't have to store previously-computed values in any sort of database. Any two agents with the same hashing algorithm will generate the same hashes. The values may not be completely unique, but they should vary wildly from input to input while also being deterministic with no hidden state. Truly unique would require querying outside state and probably introduce race conditions if your system is distributed.

It appears that GetDays() and GetPersiodValue() returns two int lists, so I'm writing two mock methods for those.
static List<int> GetDays()
{
return new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
}
static List<int> GetPeriods()
{
return new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
}
First thing you need to do is move the new Random() out of the methods (so that it's outside the loop). Otherwise when you iterate so fast it will keep giving you the same number.
static int GetRandomDay(Random rnd)
{
var days = GetDays();
return days[rnd.Next(days.Count)];
}
static int GetRandomPeriod(Random rnd)
{
var periods = GetPeriods();
return periods[rnd.Next(periods.Count)];
}
Then I'll do something like this to see if the generated pair of random values were generated before. Add to a list (or DB in your case) if not.
static void Main(string[] args)
{
var RandomList = new List<Tuple<int, int>>();
Random rnd = new Random();
for (int i =0; i < 10; i++)
{
bool isUnique = false;
do
{
int day = GetRandomDay(rnd);
int period = GetRandomPeriod(rnd);
if(RandomList.Where(x => x.Item1 == day && x.Item2 == period).FirstOrDefault() == null)
{
RandomList.Add(new Tuple<int, int>(day, period));
isUnique = true;
}
} while (!isUnique);
}
Console.ReadLine();
}

I tried to use KeyValuePair and I solved, its works well !
Here the code that I used:
// I created a list contain two pairs..
List<KeyValuePair<int, int>> dictionary = new List<KeyValuePair<int, int>>();
for (int z = 0; z < secPortion; z++)
{
day = GetDayValue();
period = GetPeriodValue(grd_id);
//here I pass the value of day and period to the pairs
KeyValuePair<int, int> myItem = new KeyValuePair<int, int>(day, period);
//here I created a list which is the list of values for the random key, if it is exist or not.
List<int> values = (from kvp in dictionary where kvp.Key == day select kvp.Value).ToList();
// this is a bool variable its value by default is true, once there is a duplicated value it will be changed to false....
bool FirstChecker = true;
if (values.Contains(period))
{
FirstChecker = false;
z--;
}
else
{
dictionary.Add(myItem);
SetFirstShot(teacher, sub, sec, period, day);
}
}

I think this is what you need.
Although the example is a solution for a one-dimensional array, actually in your case the two list days and periods can be mapped to one sequence whose length is days.Count * periods.Count. Or you can do this for each list separately but some cases will be missed.

Related

How to find out all permutations of numbers that sum to 100

I am trying to figure out an efficient way to create a method that takes a dictionary containing several lists of sequential integers (each list must start above 0 or higher and end on 100 or lower, but the exact numbers may vary) and returns a list of dictionaries containing all the permutations where the sum of all numbers amount to 100.
E.g., for 4 categories: 10 + 20 + 10 + 60 = 100
Each dictionary in the resulting list should store with a single integer value for each key.
Here's some code I came up with to illustrate my question:
using System;
using System.Collections.Generic;
using System.Linq;
namespace recursiveTest
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, List<int>> data = new Dictionary<string, List<int>>();
data.Add("A", Enumerable.Range(0, 100).ToList());
data.Add("B", Enumerable.Range(0, 100).ToList());
data.Add("C", Enumerable.Range(0, 100).ToList());
data.Add("D", Enumerable.Range(0, 100).ToList());
// I would like to add a few entries more...
List<Dictionary<string, int>> permutations = new List<Dictionary<string, int>>();
foreach (var a in data["A"])
{
foreach (var b in data["B"])
{
foreach (var c in data["C"])
{
foreach (var d in data["D"])
{
if (a + b + c + d == 100)
{
var current = new Dictionary<string, int>()
{
["A"] = a,
["B"] = b,
["C"] = c,
["D"] = d,
};
permutations.Add(current);
}
}
}
}
}
Console.WriteLine($"Found (foreach): {permutations.Count()}");
Console.ReadKey();
}
}
}
An alternative using LINQ:
List<Dictionary<string, int>> permutations2 = (from a in data["A"]
from b in data["B"]
from c in data["C"]
from d in data["D"]
where a + b + c + d == 100
let current = new Dictionary<string, int>()
{
["A"] = a,
["B"] = b,
["C"] = c,
["D"] = d,
}
select current).ToList();
Console.WriteLine($"Found (LINQ): {permutations2.Count()}");
Console.ReadKey();
It was not a very complicated task before the number of categories (dictionary keys) and numbers started to grow... Since the number of dictionary keys (categories) may vary, this seems to be a potential candidate for recursion, but I wasn't able to make it work. These two versions have a few obvious drawbacks:
As soon as the number of items and/or categories increases, suddenly the performance degrades.
Arrow shaped code seems like a recipe for disaster.
It tries to traverse all the possible combinations, while in fact just a few are useful (those that sum to 100).
What is the best way to achieve the intended result, with short and readable code and good performance?
Is there a way to filter out unnecessary loops while trying to find out those 100 sum values?
EDIT:
For clarification, My idea is to be able to define a method with a signature like this:
private static List<Dictionary<string, int>> GetValidPermutations(Dictionary<string, List<int>> data)
Then call it like this:
List<Dictionary<string, int>> permutations = GetValidPermutations(data);
To enhance performance, the key is to reduce the number of unnecessary iterations:
static List<Dictionary<string, int>> GetValidPermutations(int target, Dictionary<string, List<int>> data)
{
return GetValidPermutations(target, data, 0, new int[data.Count])
.Select(perm => CreateDictionary(data.Keys, perm))
.ToList();
}
static Dictionary<string, int> CreateDictionary(IEnumerable<string> keys, IEnumerable<int> values)
{
return keys.Zip(values, KeyValuePair.Create)
.ToDictionary(pair => pair.Key, pair => pair.Value);
}
static IEnumerable<int[]> GetValidPermutations(int target, Dictionary<string, List<int>> data, int level, int[] sequence)
{
if (level < sequence.Length)
{
var currentList = data.ElementAt(level).Value;
var subsequentLists = data.Skip(level + 1).Select(x => x.Value);
int start = Math.Max(currentList[0], target - subsequentLists.Sum(x => x.Last()));
int end = Math.Min(currentList.Last(), target - subsequentLists.Sum(x => x[0]));
for (sequence[level] = start; sequence[level] <= end; sequence[level]++)
{
int subTarget = target - sequence[level];
foreach (var perm in GetValidPermutations(subTarget, data, level + 1, sequence))
{
yield return perm;
}
}
}
else
{
var perm = sequence.Append(target);
System.Diagnostics.Debug.Assert(perm.Sum() == 100);
yield return perm.ToArray();
}
}
The start and end above is carefully calculated to include the necessary iterations only. Other values are skipped because they cannot form the permutation.
Then you can call the method like this:
var p4 = GetValidPermutations(100, data);
Console.WriteLine($"Found (Recursion): {p4.Count()}");
It may be difficult to understand the recursion version in the first place, there is the for loop equivalent, you can see that some code sections are repeated:
const int TARGET = 100;
var permutations3 = new List<Dictionary<string, int>>();
int aStart = Math.Max(data["A"][0], TARGET - data["B"].Last() - data["C"].Last() - data["D"].Last());
int aEnd = Math.Min(data["A"].Last(), TARGET - data["B"][0] - data["C"][0] - data["D"][0]);
for (int a = aStart; a <= aEnd; a++)
{
int bStart = Math.Max(data["B"][0], TARGET - a - data["C"].Last() - data["D"].Last());
int bEnd = Math.Min(data["B"].Last(), TARGET - a - data["C"][0] - data["D"][0]);
for (int b = bStart; b <= bEnd; b++)
{
int cStart = Math.Max(data["C"][0], TARGET - a - b - data["D"].Last());
int cEnd = Math.Min(data["C"].Last(), TARGET - a - b - data["D"][0]);
for (int c = cStart; c <= cEnd; c++)
{
var perm = new Dictionary<string, int>
{
{ "A", a },
{ "B", b },
{ "C", c },
{ "D", TARGET - a - b - c }
};
System.Diagnostics.Debug.Assert(perm["D"] >= data["D"][0] && perm["D"] <= data["D"].Last());
permutations3.Add(perm);
}
}
}
Console.WriteLine($"Found (for): {permutations3.Count()}");
The skipping logic can be illustrated by the following examples:
Suppose the maximum values of B, C, D are 10, 20, 30 respectively, then A needs to be at least 40 to have a sum of 100. Such that A can start from 40 and 0-39 are skipped (if available).
Similar logic can be applied to skipping higher ranges. Suppose the minimum values of B, C, D are 5, 10, 15 respectively, then A cannot exceed 70. Because the sum will exceed 100 if so. So we can stop looping when A exceeds 70.
Applying the skipping logic for all categories can result in the above code. In addition, the last category can be directly calculated without looping.

Can I represent a given word (String) as a number?

Suppose I have a list of words e.g.
var words = new [] {"bob", "alice", "john"};
Is there a way to represent each of those words as numbers so that one could use such numbers to sort the words.
One use-case which I think this can be used for is to use Counting Sort to sort a list of words. Again I am only interested in whether this is at all possible not that it may not be the most efficient way to sort a list of words.
Do note this is not about hash-codes or different sorting algorithms. I am curious to find out if a string can be represented as a number.
You can use a dictionary instead of an array.
public class Program
{
static void Main(string[] args)
{
IDictionary<int, string> words = new Dictionary<int, string>();
words.Add(0, "bob");
words.Add(1, "alice");
words.Add(2, "john");
foreach (KeyValuePair<int, string> word in words.OrderBy(w => w.Key))
{
Console.WriteLine(word.Value);
}
Console.ReadLine();
}
}
NOTE: It's better to work with collections in place of arrays is easier to use for most developers.
I don't understand the down votes but hey this is what I have come up with so far:
private int _alphabetLength = char.MaxValue - char.MinValue;
private BigInteger Convert(string data)
{
var value = new BigInteger();
var startPoint = data.Length - 1;
for (int i = data.Length - 1; i >= 0; i--)
{
var character = data[i];
var charNumericValue = character;
var exponentialWeight = startPoint - i;
var weightedValue = new BigInteger(charNumericValue * Math.Pow(_alphabetLength, exponentialWeight));
value += weightedValue;
}
return value;
}
Using the above to convert the following:
var words = new [] {"bob", "alice", "john" };
420901224533 // bob
-9223372036854775808 // alice
29835458486206476 // john
Despite the overflow the output looks sorted to me, I need to improve this and test it properly but at least it is a start.

algorithm for selecting N random elements from a List<T> in C# [duplicate]

This question already has answers here:
Randomize a List<T>
(28 answers)
Closed 6 years ago.
I need a quick algorithm to select 4 random elements from a generic list. For example, I'd like to get 4 random elements from a List and then based on some calculations if elements found not valid then it should again select next 4 random elements from the list.
You could do it like this
public static class Extensions
{
public static Dictionary<int, T> GetRandomElements<T>(this IList<T> list, int quantity)
{
var result = new Dictionary<int, T>();
if (list == null)
return result;
Random rnd = new Random(DateTime.Now.Millisecond);
for (int i = 0; i < quantity; i++)
{
int idx = rnd.Next(0, list.Count);
result.Add(idx, list[idx]);
}
return result;
}
}
Then use the extension method like this:
List<string> list = new List<string>() { "a", "b", "c", "d", "e", "f", "g", "h" };
Dictionary<int, string> randomElements = list.GetRandomElements(3);
foreach (KeyValuePair<int, string> elem in randomElements)
{
Console.WriteLine($"index in original list: {elem.Key} value: {elem.Value}");
}
something like that:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
int n = 4;
var rand = new Random();
var randomObjects = new List<int>();
for (int i = 0; i<n; i++)
{
var index = rand.Next(list.Count);
randomObjects.Add(list[index]);
}
}
}
You can store indexes in some list to get non-repeated indexes:
List<T> GetRandomElements<T>(List<T> allElements, int randomCount = 4)
{
if (allElements.Count < randomCount)
{
return allElements;
}
List<int> indexes = new List<int>();
// use HashSet if performance is very critical and you need a lot of indexes
//HashSet<int> indexes = new HashSet<int>();
List<T> elements = new List<T>();
Random random = new Random();
while (indexes.Count < randomCount)
{
int index = random.Next(allElements.Count);
if (!indexes.Contains(index))
{
indexes.Add(index);
elements.Add(allElements[index]);
}
}
return elements;
}
Then you can do some calculation and call this method:
void Main(String[] args)
{
do
{
List<int> elements = GetRandomelements(yourElements);
//do some calculations
} while (some condition); // while result is not right
}
Suppose that the length of the List is N. Now suppose that you will put these 4 numbers in another List called out. Then you can loop through the List and the probability of the element you are on being chosen is
(4 - (out.Count)) / (N - currentIndex)
funcion (list)
(
loop i=0 i < 4
index = (int) length(list)*random(0 -> 1)
element[i] = list[index]
return element
)
while(check == false)
(
elements = funcion (list)
Do some calculation which returns check == false /true
)
This is the pseudo code, but i think you should of come up with this yourself.
Hope it helps:)
All the answers up to now have one fundamental flaw; you are asking for an algorithm that will generate a random combination of n elements and this combination, following some logic rules, will be valid or not. If its not, a new combination should be produced. Obviously, this new combination should be one that has never been produced before. All the proposed algorithms do not enforce this. If for example out of 1000000 possible combinations, only one is valid, you might waste a whole lot of resources until that particular unique combination is produced.
So, how to solve this? Well, the answer is simple, create all possible unique solutions, and then simply produce them in a random order. Caveat: I will suppose that the input stream has no repeating elements, if it does, then some combinations will not be unique.
First of all, lets write ourselves a handy immutable stack:
class ImmutableStack<T> : IEnumerable<T>
{
public static readonly ImmutableStack<T> Empty = new ImmutableStack<T>();
private readonly T head;
private readonly ImmutableStack<T> tail;
public int Count { get; }
private ImmutableStack()
{
Count = 0;
}
private ImmutableStack(T head, ImmutableStack<T> tail)
{
this.head = head;
this.tail = tail;
Count = tail.Count + 1;
}
public T Peek()
{
if (this == Empty)
throw new InvalidOperationException("Can not peek a empty stack.");
return head;
}
public ImmutableStack<T> Pop()
{
if (this == Empty)
throw new InvalidOperationException("Can not pop a empty stack.");
return tail;
}
public ImmutableStack<T> Push(T item) => new ImmutableStack<T>(item, this);
public IEnumerator<T> GetEnumerator()
{
var current = this;
while (current != Empty)
{
yield return current.head;
current = current.tail;
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
This will make our life easier while producing all combinations by recursion. Next, let's get the signature of our main method right:
public static IEnumerable<IEnumerable<T>> GetAllPossibleCombinationsInRandomOrder<T>(
IEnumerable<T> data, int combinationLength)
Ok, that looks about right. Now let's implement this thing:
var allCombinations = GetAllPossibleCombinations(data, combinationLength).ToArray();
var rnd = new Random();
var producedIndexes = new HashSet<int>();
while (producedIndexes.Count < allCombinations.Length)
{
while (true)
{
var index = rnd.Next(allCombinations.Length);
if (!producedIndexes.Contains(index))
{
producedIndexes.Add(index);
yield return allCombinations[index];
break;
}
}
}
Ok, all we are doing here is producing random indexees, checking we haven't produced it yet (we use a HashSet<int> for this), and returning the combination at that index.
Simple, now we only need to take care of GetAllPossibleCombinations(data, combinationLength).
Thats easy, we'll use recursion. Our bail out condition is when our current combination is the specified length. Another caveat: I'm omitting argument validation throughout the whole code, things like checking for null or if the specified length is not bigger than the input length, etc. should be taken care of.
Just for the fun, I'll be using some minor C#7 syntax here: nested functions.
public static IEnumerable<IEnumerable<T>> GetAllPossibleCombinations<T>(
IEnumerable<T> stream, int length)
{
return getAllCombinations(stream, ImmutableStack<T>.Empty);
IEnumerable<IEnumerable<T>> getAllCombinations<T>(IEnumerable<T> currentData, ImmutableStack<T> combination)
{
if (combination.Count == length)
yield return combination;
foreach (var d in currentData)
{
var newCombination = combination.Push(d);
foreach (var c in getAllCombinations(currentData.Except(new[] { d }), newCombination))
{
yield return c;
}
}
}
}
And there we go, now we can use this:
var data = "abc";
var random = GetAllPossibleCombinationsInRandomOrder(data, 2);
foreach (var r in random)
{
Console.WriteLine(string.Join("", r));
}
And sure enough, the output is:
bc
cb
ab
ac
ba
ca

How to pick a random string from string array only once

I'm trying to make Hangman in C#, and in the beginning of a game you will need a word to guess, and so the game wont be boring you can get many words (only one at a time). But when you start a new game you wont get a word you've already guessed. So i have to choose a random string that i havent chosen already.
I've tried multiple methods to solve this, but none have succeded.
Method #1:
Here I run the NewWord-function, and then add 1 to numberOfTries.
string[] wordArr = { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO" };
int numberOfTries = 0;
int randomNumber = -1;
protected string NewWord()
{
if (!(numberOfTries >= wordArr.Length))
{
randomNumber = RandomNumberFromTo(0, (wordArr.Length - numberOfTries));
ChangeWord(((wordArr.Length - numberOfTries)-1), randomNumber);
return wordArr[(randomNumberl)];
}
else
{
return "There are no more new words!! :(";
}
}
private int RandomNumberFromTo(int NumberA, int NumberB)
{
System.Threading.Thread.Sleep(2);
Random minRandomGenerator = new Random();
System.Threading.Thread.Sleep(3);
return minRandomGenerator.Next(NumberA, NumberB);
}
protected void ChangeWord (int NumberA, int NumberB)
{
string cashe1 = wordArr[NumberA];
wordArr[NumberA] = wordArr[NumberB];
wordArr[NumberB] = cashe1;
return;
}
Method #2 I've found here on StackOverflow but it didn't work.
Here I also run the NewWord-function, and then add 1 to numberOfTries.
string[] wordArr = { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO" };
int numberOfTries = 0;
Random random = new Random();
protected string NyttOrd()
{
if (!(numberOfTries >= wordArr.Length))
{
var names = new List<string> { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO" };
System.Threading.Thread.Sleep(3);
int index = random.Next(names.Count);
var name = names[index];
names.RemoveAt(index);
return name;
}
else
{
return "There are no more new words!! :(";
}
}
I have also tried a version where I had two different arrays, one an Int-Array and the second a String-Array. It was really messy and did not work.
I am also very new to C# i only know of the basics, like +-/*, convert, functions, and arrays.
Conceptually, you either keep track of strings you already used, or you remove strings from the list of optional strings as you use them.
To implement the first method, you can keep a hashtable of strings you've already used, and when pulling a new string - see if it is present in the hashtable (and if so, pick another one, until a "fresh" string is picked).
To implement the second method, just remove the strings you picked from the list as you pick them.
If you shuffle your word array:
var r = new Random();
var shuffledWords = wordArr.OrderBy(_ => r.Next());
then push your words into a Stack:
var wordStack = new Stack<string>(shuffledWords);
now you have a structure that will hand you random word from the collection while simultaneously removing it from the collection by using the Pop method of Stack<T> (considerably more efficiently than removing items from the front/middle of a List<T>, although your collection is so small, it hardly matters).
var someWord = wordStack.Pop();
static readonly List<string> Words = new List<string>(wordArr);
static readonly Random Rnd = new Random();
public string Next()
{
if(Words.Count < 1)
return "There are no more new words!! :(";
var index = Rnd.Next(0, Words.Length);
var result = Words[index];
Words.RemoveAt(index);
return result;
}
Use KeyValuePair.
The key will be your word, the value will be how many times it's been used, then just take the least used word and increment its counter.
List<KeyValuePair<string, int>>
You should represent your WordArr as a list. It's easier to work with to suit your needs.
Here's an easy way to randomize your list:
List<string> wordArr = new List<string>()
{
"PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO"
};
Random random = new Random();
wordArr = wordArr.OrderBy(x => random.Next()).ToList();
Then just always take the first word in the list so that you can simply remove each word that you use like this:
wordArr.RemoveAt(0);
When the wordArr is empty then you are done.
Since you've said you're new to programming, I'll explain the key line quickly:
.Except() compares your array to the other array and returns only unique elements.
.OrderBy(x => rn.Next()) will return the array in a random order.
.FirstOrDefault() will get the first entry from the array or, if the array is empty, return null.
public void GenerateWord()
{
Random rn = new Random();
string[] attemptedWords = LoadUsedWords();
string[] wordArr = { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO" };
string word = wordArr.Except(attemptedWords).OrderBy(x => rn.Next()).FirstOrDefault();
if (string.IsNullOrEmpty(word))
{
Console.WriteLine("Oh no");
}
else
{
Console.WriteLine(word);
}
}
public string[] LoadUsedWords()
{
return new string[] { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL" };
}

access the value of a random element of an list c#

I'm trying to access the value of a random element of an list. At the moment my code seems to be returning the element rather than the value.
int x = _randMoveDecider.Count;
//makes sure x is never more than the array size
if(x != 0)
{
x = x - 1 ;
}
Random _r = new Random();
_move = _r.Next(_randMoveDecider[x]);
return _randMoveDecider[_move];
at the moment if _randMoveDecider holds the values 2, 5 and 9 it will return 0, 1 or 2 rather than the values in the list, where am I going wrong?
[edit] I guess I should have said, the length of _randMoveDecider and the values stored in it change with each run through of the program, but they are always integers.
How about just this?
// as a field somewhere so it's initialised once only
public Random _r = new Random();
// later in your code
var _randList = new List<int>{4,5,8,9};
var _move = _r.Next(_randList.Count);
return _randList[_move];
Even better, here's something that will randomise any list:
public static Random _rand = new Random();
public IEnumerable<T> Randomise<T>(IList<T> list)
{
while(true)
{
// we find count every time since list can change
// between iterations
yield return list[_rand.Next(list.Count)];
}
}
One way of using it in your scenario:
// make this a field or something global
public IEnumerbale<int> randomiser = Randomise(_randList);
// then later
return randomiser.First();
Firstly you should initialize Random once. Make it a field:
private Random _rand = new Random();
Then get a random number from the proper range. if(x!=0) is useless - Next() returns numbersform <0, n) range
return _randMoveDecider[_rand.Next(_randMoveDecider.Count)];
Simply add this extension class inside main class:
public static class Extensions
{
public static int randomOne(this List<int> theList)
{
Random rand = new Random(DateTime.Now.Millisecond);
return theList[rand.Next(0, theList.Count)];
}
}
and then call it:
int value = mylist.randomOne();
EDIT: This is a test program that demonstrates how one would use the method. Note that due to incorrect usage of Random it produces very unbalanced results with more than 50 "random" numbers out of 100 being the same.
class Program
{
static void Main(string[] args)
{
var myList = Enumerable.Range(0, 100).ToList();
var myRandoms = myList.Select(v => new { key = v, value = 0 })
.ToDictionary(e => e.key, e => e.value);
for (int i = 0; i < 100; i++)
{
var random = myList.RandomOne();
myRandoms[random]++;
}
Console.WriteLine(myRandoms.Values.Max());
Console.ReadLine();
}
}
To fix the issue make Random static instance for Extension class or share more broadly in the program. This is discussed in FAQ for Random.
public static class Extensions
{
static Random rand = new Random();
public static int randomOne(this List<int> theList)
{
return theList[rand.Next(0, theList.Count)];
}
}
var random = new Random();
var item = list.ElementAt(random.Next(list.Count()));

Categories