My function to generate random numbers is this:
public static List<int> GetRandomNumbers(int count)
{
HashSet<int> randomNumbers = new HashSet<int>();
Random random = new Random();
for (int i = 0; i < count; i++)
{
while(!randomNumbers.Add(random.Next(100, 999)));
}
return randomNumbers.ToList();
}
This is how I call it:
private void button1_Click(object sender, EventArgs e)
{
List<int> list = new List<int>();
list = GetRandomNumbers(5);
for (int i = 0; i < list.Count; i++)
{
MessageBox.Show(list[i].ToString());
}
}
Ok, so, what I want to do is, for example, if the list generated is the following:
152 582 254 891 421
I want to make the list be:
152 152 582 582 254 254 891 891 421 421
Basically, each number to be added one more time after itself in the list. How can I do this? (It would be good if you include a simple way to do this considering time not a problem, and maybe a better way to save time)
Thanks
Your question is unclear.
You can take a list (not a HashSet) with repeating elements and move every repetition to immediately follow the first occurrence like this:
var numbers = Enumerable.Range(1, count).Select(i => random.NextInt(0, 300));
return numbers.GroupBy(i => i).SelectMany(s => s).ToList();
You can take an existing list and make each element repeat twice like this:
list.SelectMany(o => Enumerable.Repeat(o, 2));
You could change your function slightly to:
private static Random random = new Random();
public static List<int> GetRandomNumbers(int count)
{
int value;
List<int> values = new List<int>();
HashSet<int> randomNumbers = new HashSet<int>();
for (int i = 0; i < count; i++)
{
while (!randomNumbers.Add(value = random.Next(100, 999)));
values.Add(value);
values.Add(value);
}
return values;
}
I think you just want something like this:
var list2 = new List<int>(list1.Count * 2);
foreach (var n in list1)
{
list2.Add(n);
list2.Add(n);
}
That will loop through the list and put each value into the second list twice.
I think you need to change your function as follows:
public static List<int> GetRandomNumbers(int count)
{
List<int> Result = new List<int>();
Random random = new Random();
for (int i = 0; i < count; i++)
{
int NewNumber = random.Next(100, 999);
Result.Add(NewNumber);
Result.Add(NewNumber);
}
return Result;
}
I tried the function above, it worked just like you said.
Related
This question already has answers here:
Best way to randomize an array with .NET
(19 answers)
Closed 1 year ago.
everyone. So I was trying to practice C# today, but I was stuck in figuring out how I can use the Random class to simply shuffle an array
like this for example:
using System;
public class Program
{
public static void Main()
{
int[] arr = {1,2,3,4,5};
Random rand = new Random();
for(int i =0; i < arr.Length; i++){
int shuffle = rand.Next(arr[i]);
Console.WriteLine(arr[shuffle]);
}
}
}
As you can see I tried to use this int shuffle = rand.Next(arr[i]); as a shuffler, but
I guess it just duplicates some elements in the array.I'm still noob at this, thanks in advance for the response.
You can try implementing Fisher-Yates shuffling algorithm: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Random random = new Random();
...
for (int i = 0; i < array.Length - 1; ++i)
{
int r = random.Next(i, array.Length);
(array[r], array[i]) = (array[i], array[r]);
}
I suggest extracting a method for this:
// Easiest, but not thread safe
private static Random random = new Random();
private static void Shuffle<T>(T[] array)
{
if (array is null)
throw new ArgumentNullException(nameof(array));
for (int i = 0; i < array.Length - 1; ++i)
{
int r = random.Next(i, array.Length);
(array[r], array[i]) = (array[i], array[r]);
}
}
And you can call it from Main:
Shuffle(array);
You can fiddle with the algorithm.
There are a few solutions out there, but the one I had used it to create a random array and sort based on that
static class Program
{
static void Main(string[] args)
{
var array = new[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
Shuffle(ref array);
foreach (var item in array)
{
Console.WriteLine(item);
}
// Fri
// Wed
// Sat
// Thu
// Mon
// Sun
// Tue
}
static readonly Random rng = new Random();
public static void Shuffle<T>(ref T[] array)
{
double[] key = new double[array.Length];
for (int i = 0; i < key.Length; i++)
{
key[i] = rng.NextDouble();
}
Array.Sort(key, array);
}
}
An alternative is to use the following 1 liner LINQ statement
static void Main(string[] args)
{
var array = new[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
var result = array.OrderBy((item) => rng.NextDouble()).ToArray();
}
This type of shuffling is going to require seeding the Randomn class to the size of the array. And with each pass in the for loop, it's going to swap the current number with a random other number in the array.
Here is a sample of what the shuffle can look like:
int[] arr = {1,2,3,4,5};
Random rand = new Random();
for(int i = 0; i < arr.Length; i++){
int shuffle = rand.Next(arr.Length);
int n = arr[i];
arr.SetValue(arr[shuffle], i);
arr.SetValue(n, shuffle);
}
Console.Write('[' + arr[0].ToString());
for(int i = 1; i < arr.Length; i++){
Console.Write("," + arr[i]);
}
Console.Write("]");
I have created a simple program which randomly generates 6 winning numbers. While the program works, I would also like for it to ensure that the same number isn't outputted twice as well as sorting them into numerical order when outputted. How would I go about doing such a thing while sticking to similar techniques already used? My code is down below. Any help is very much appreciated.
int temp;
int[] lotto = new int[6];
Random rand = new Random();
for (int i = 0; i < 6; i++)
{
temp = rand.Next(1, 59);
lotto[i] = temp;
}
Console.Write($"The lotterry winning numbers are: ");
for (int i = 0; i < 6; i++)
{
Console.Write(lotto[i] + " ");
}
Console.ReadKey();
Based on a Fisher-Yates shuffle, but saves some work because we know we don't need all the values (if we only need 6 values out of 10 million potentials, we only need to take the first six iterations of the fisher-yates algorithm).
public IEnumerable<int> DrawNumbers(int count, int MaxNumbers)
{
var r = new Random(); //ideally, make this a static member somewhere
var possibles = Enumerable.Range(1, MaxNumbers).ToList();
for (int i = 0; i < count; i++)
{
var index = r.Next(i, MaxNumbers);
yield return possibles[index];
possibles[index] = possibles[i];
}
}
var lottoNumbers = DrawNumbers(6, 59);
Console.Write("The lotterry winning numbers are: ");
Console.WriteLine(string.Join(" ", lottoNumbers.OrderBy(n => n)));
See it work here:
https://dotnetfiddle.net/NXYkpU
You can use Linq to create sequence [1..59] and order it by random to shuffle it.
Random rand = new Random();
var winners = Enumerable.Range(1, 59)
.OrderBy(x => rand.Next())
.Take(6)
.OrderBy(x => x)
.ToList();
Console.WriteLine(String.Join(" ", winners));
int temp;
int[] lotto = new int[6];
Random rand = new Random();
int i = 0;
while(i < 6)
{
temp = rand.Next(1, 59);
//check if lotto contains just generated number, if so skip that number
bool alreadyExist = false;
foreach (int item in lotto)
{
if (item == temp)
{
alreadyExist = true;
break;
}
}
if (alreadyExist)
continue;
lotto[i] = temp;
i++;
}
Console.Write($"The lotterry winning numbers are: ");
// Sort array in ascending order.
Array.Sort(lotto);
for (int j = 0; j < 6; j++)
{
Console.Write(lotto[j] + " ");
}
Console.ReadKey();
I would probably do it Dmitri's way because it is quick and obvious and performance isn't that important with an array this size.
But just for fun, this is slightly more efficient.
IEnumerable<int> GetNumbers(int min, int max, int count)
{
var random = new Random();
var size = max - min + 1;
var numbers = Enumerable.Range(min, size).ToArray();
while (count > 0)
{
size--;
var index = random.Next(0, size);
yield return numbers[index];
numbers[index] = numbers[size];
count--;
}
}
This solution creates an array containing all possible values and selects them randomly. Each time a selection is made, the array is "shrunk" by moving the last element to replace the element that was chosen, preventing duplicates.
To use:
var numbers = GetNumbers(1, 59, 6).ToList();
foreach (var number in numbers.OrderBy(x => x))
{
Console.WriteLine(number);
}
I have a list of strings containing loads of hashtags with texts.
ex #csharp #java ect.
each hashtag is a own string in a List. I now want to randomly always console.writeline 30 items of that list.
List
List<string> Hashtags = new List<string>();
Writeline
foreach (var x in Hashtags) {
Console.WriteLine(x);
}
Ideally i never wanna have the same hashtag in the random 30.
You should try this:
var rnd = new Random();
foreach (var x in Hashtags.OrderBy(x => rnd.Next()).Take(30))
{
Console.WriteLine(x);
}
This has O(n^2) complexity, but is easily readable.
If you want efficiency try a Fisher-Yates Shuffle, it's O(n), but less readable:
var take = 30;
var rnd = new Random();
for (var i = 0; i < (Hashtags.Count < take ? Hashtags.Count : take); i++)
{
var j = rnd.Next(Hashtags.Count);
(Hashtags[i], Hashtags[j]) = (Hashtags[j], Hashtags[i]);
}
foreach (var x in Hashtags.Take(take))
{
Console.WriteLine(x);
}
Keep in mind, though, that it's best to instantiate Random once per thread, so this would be a better way:
[ThreadStatic]
private static Random rnd = new Random();
This should do. It is efficient, as it shuffles only the required amount of items, not the whole collection. You pass how many elements you want to fetch from the array as parameter(elementCount).
private static Random randomGenerator = new Random();
static void Main()
{
var hashtags = new List<string>() { "c#", "javascript", "ef", "asp.net" };
var result = GetRandomItems<string>(hashtags, 2);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
private static IEnumerable<T> GetRandomItems<T>(IEnumerable<T> collection, int elementCount)
{
var collectionCount = collection.Count();
if (elementCount > collectionCount)
{
elementCount = collectionCount;
}
var collectionCopy = collection.ToList();
var randomIndex = randomGenerator.Next(0, collectionCopy.Count);
for (var index = 0; index < elementCount; index++)
{
var tempElement = collectionCopy[index];
collectionCopy[index] = collectionCopy[randomIndex];
collectionCopy[randomIndex] = tempElement;
randomIndex = randomGenerator.Next(index + 1, collectionCopy.Count);
}
return collectionCopy.Take(elementCount);
}
Call 30 times Random.next
https://learn.microsoft.com/en-us/dotnet/api/system.random.next
var random = new Random();
//calls this n times in a loop:
Console.writeline(Hashtags[random.next(Hashtags.Count])
Got it working myself, little more verbose but hopefully easier to follow.
var random = new Random();
var uniques = Hashtags;
for (var i = 0; i < 30; i++) {
var index = random.Next(0, uniques.Count());
Console.WriteLine(uniques[index]);
uniques.RemoveAt(index);
}
This question already has answers here:
Random number generator with no duplicates
(12 answers)
Closed 2 years ago.
Hi everyone I am trying to generate 6 different numbers on the same line in c# but the problem that i face is some of the numbers are repeating on the same line.Here is my code to
var rand = new Random();
List<int> listNumbers = new List<int>();
int numbers = rand.Next(1,49);
for (int i= 0 ; i < 6 ;i++)
{
listNumbers.Add(numbers);
numbers = rand.Next(1,49);
}
somewhere my output is
17 23 23 31 33 48
Check each number that you generate against the previous numbers:
List<int> listNumbers = new List<int>();
int number;
for (int i = 0; i < 6; i++)
{
do {
number = rand.Next(1, 49);
} while (listNumbers.Contains(number));
listNumbers.Add(number);
}
Another approach is to create a list of possible numbers, and remove numbers that you pick from the list:
List<int> possible = Enumerable.Range(1, 48).ToList();
List<int> listNumbers = new List<int>();
for (int i = 0; i < 6; i++)
{
int index = rand.Next(0, possible.Count);
listNumbers.Add(possible[index]);
possible.RemoveAt(index);
}
listNumbers.AddRange(Enumerable.Range(1, 48)
.OrderBy(i => rand.Next())
.Take(6))
Create a HashSet and generate a unique random numbers
public List<int> GetRandomNumber(int from,int to,int numberOfElement)
{
var random = new Random();
HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < numberOfElement)
{
numbers.Add(random.Next(from, to));
}
return numbers.ToList();
}
Make it a while loop and add the integers to a hashset. Stop the loop when you have six integers.
Instead of using a List, you should use an HashSet. The HashSet<> prohibites multiple identical values. And the Add method returns a bool that indicates if the element was added to the list, Please find the example code below.
public static IEnumerable<int> GetRandomNumbers(int count)
{
HashSet<int> randomNumbers = new HashSet<int>();
for (int i = 0; i < count; i++)
while (!randomNumbers.Add(random.Next()));
return randomNumbers;
}
I've switched your for loop with a do...while loop and set the stopping condition on the list count being smaller then 6.
This might not be the best solution but it's the closest to your original code.
List<int> listNumbers = new List<int>();
do
{
int numbers = rand.Next(1,49);
if(!listNumbers.Contains(number)) {
listNumbers.Add(numbers);
}
} while (listNumbers.Count < 6)
The best approach (CPU time-wise) for such tasks is creating an array of all possible numbers and taking 6 items from it while removing the item you just took from the array.
Example:
const int min = 1, max = 49;
List<int> listNumbers = new List<int>();
int[] numbers = new int[max - min + 1];
int i, len = max - min + 1, number;
for (i = min; i < max; i++) numbers[i - min] = i;
for (i = 0; i < 6; i++) {
number = rand.Next(0, len - 1);
listNumbers.Add(numbers[number]);
if (number != (len - 1)) numbers[number] = numbers[len - 1];
len--;
}
If you are not worried about the min, max, and range then you can use this.
var nexnumber = Guid.NewGuid().GetHashCode();
if (nexnumber < 0)
{
nexnumber *= -1;
}
What you do is to generate a random number each time in the loop. There is a chance of course that the next random number may be the same as the previous one. Just add one check that the current random number is not present in the sequence. You can use a while loop like: while (currentRandom not in listNumbers): generateNewRandomNumber
Paste the below in the class as a new method
public int randomNumber()
{
var random = new Random();
int randomNumber = random.Next(10000, 99999);
return randomNumber;
}
And use the below anywhere in the tests wherever required
var RandNum = randomNumber();
driver.FindElement(By.CssSelector("[class='test']")).SendKeys(**RandNum**);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int[] que = new int[6];
int x, y, z;
Random ran = new Random();
for ( x = 0; x < 6; x++)
{
que[x] = ran.Next(1,49);
for (y = x; y >= 0; y--)
{
if (x == y)
{
continue;
}
if (que[x] == que[y])
{
que[x] = ran.Next(1,49);
y = x;
}
}
}
listBox1.Items.Clear();
for (z = 0; z < 6; z++)
{
listBox1.Items.Add(que[z].ToString());
}
}
}
I want to select a random number from 1 to 99. And then select the number again but this time discard the previous number. Can someone help me.
private List<int> numbers = Enumerable.Range(0, 100).ToList();
private Random rnd = new Random();
public int GetRandomInt()
{
var index = rnd.Next(0, numbers.Length);
var number = numbers[index];
numbers.RemoveAt(index);
return number;
}
Here's what I'd do:
var rnd = new Random();
var numbers = new Stack<int>(Enumerable.Range(1, 99).OrderBy(x => rnd.Next()));
You effectively are randomizing the list of numbers and then adding them to a stack. Now you just have to do this to get each number:
var next = numbers.Pop()
You stop when numbers.Count == 0. Simple.
Here is the revised version of Khanh TO, because it is not correct:
List<int> usedNumbers = new List<int>();
Random rand = new Random(new object().GetHashCode());
int number = 0;
for (int i = 0; i < 99; i++)
{
do
{
number = 1 + rand.Next(0, 99);
} while (usedNumbers.Contains(number));
usedNumbers.Add(number);
}
I usually do it with arrays.
Whenever you create a random number just put on the array. so next time check if the number is already generated by checking in the array.
Try this
IList<int> arr = Enumerable.Range(1, 99).ToList();
int randNum;
Random rnd = new Random();
randNum = rnd.Next(1, arr.Count());
MessageBox.Show(randNum.ToString());
arr = arr.Where(x => x != randNum).ToList();
Can I go for the shortest code, without a nested loop, or removing list elements.
Code 1
class Program
{
static Random rnd=new Random();
static void Main(string[] args)
{
var list=new SortedDictionary<double, int>();
// Fill list
for (int i=1; i<=99; i++)
{
list.Add(rnd.NextDouble(), i);
}
// List Automatically random
var random_int=list.Values.ToArray();
// random_int = {45, 7, 72, .. }
}
}
Code 2
class Program
{
static Random rnd=new Random();
static void Main(string[] args)
{
var list=new int[99];
// Fill list
for (int i=1; i<=99; i++)
{
list[i-1]=i;
}
Comparison<int> any=(x, y) =>
{
var z=2*rnd.NextDouble()-1;
return z.CompareTo(0);
};
// Randomize List
Array.Sort(list, any);
// list = { 49, 59, 21, 7, 18 ...}
}
}