i am trying to generate 5 random numbers in an array and output them, however i don't want 2 values to be the same, what do i need to add to this code to prevent this?
using System;
public class Program
{
public static void Main()
{
int count = 0;
int Randomnum=0;
int[] num = new int[5];
Random r = new Random();
while(count < 5){
Randomnum= r.Next(1,10);
num[count]=Randomnum;
count = count+ 1;
}
foreach(var entry in num)
{
Console.WriteLine(entry);
}
}
}
You could get your full set using Enumerable.Range, order them by a random value and get top 5. ie:
var numberSet = Enumerable.Range(1,10);
var randomSet = numberSet.OrderBy(s => Guid.NewGuid()).Take(5);
foreach (var entry in randomSet)
{
Console.WriteLine(entry);
}
Your current implementation could be edited so that it adds the new random value (and increments the counter) only if num does not already contain the value.
Your variables are defined as follows:
int count = 0;
int randomNum = 0;
int[] num = new int[5];
Random r = new Random();
One way of checking whether or not num contains the new value is by using Array.IndexOf(). This method returns the index at which the value you provide is found in the array that you provide. If the value you provide is not found in the array, the method will return -1.
(Note: Array.IndexOf() specifically returns the lower bound of the array minus 1 when no match is found. Seeing as you populate num starting at index 0, the return value is therefore -1 in your scenario. More about the computation of an array's lower bound here).
The implementation of your while loop could thus be adjusted to:
while (count < 5)
{
randomNum = r.Next(1, 10);
if (Array.IndexOf(num, randomNum) < 0)
{
num[count] = randomNum;
count += 1;
}
}
An alternative to using Array.IndexOf() is to use Enumerable.Contains() from the System.Linq namespace. I find it to be more readable, so I just thought I'd mention it.
//using System.Linq;
while (count < 5)
{
randomNum = r.Next(1, 10);
if (!num.Contains(randomNum))
{
num[count] = randomNum;
count += 1;
}
}
That being said, you may want to consider using a HashSet rather than an array for this scenario. A HashSet can only contain distinct values, which is what you want to achieve.
HashSet's .Add() method actually checks whether your HashSet already contains the value you are trying to add. If it does, the value will not be added again.
Due to this behavior, you can call .Add() for every random value that you generate, without manually having to check for existence beforehand.
Another beneficial side effect of this is that your count and randomNum variables are no longer necessary.
Using a HashSet rather than an array, your code (prior to the code that prints the result to the console) could be implemented as follows:
//using System.Collections.Generic;
HashSet<int> num = new();
Random r = new Random();
while (num.Count < 5)
{
num.Add(r.Next(1, 10));
}
Example fiddle with all three implementations here.
Related
the code:
using System;
using System.Diagnostics;
namespace ConsoleApp1
{
class Program
{
const int maxResult = 120; //this can change but hardcoded for this code
static int poolPos;
static double[] pool = new double[maxResult * 4];
static int maxPos;
static double[] result = new double[maxResult];
static void Main(string[] args)
{
var sw = Stopwatch.StartNew();
for(int i = 0; i < 100_000; ++i)
Unlock();
Console.WriteLine(sw.ElapsedMilliseconds);
//Console.Read();
}
static void Unlock()
{
int total = maxResult;
//reset array
poolPos = 0;
maxPos = 0;
FindLock(4);
while (total-- > 0)
{
int i = 0;
double maxWeight = pool[0];
int pos = 0;
while (++i < poolPos) //O(n), can it be faster?
if (pool[i] >= maxWeight) //can have duplicate value, find latest max inserted
(maxWeight, pos) = (pool[i], i); //keep track
result[maxPos++] = maxWeight; //store the result
pool[pos] = pool[--poolPos]; //remove from array by swapping it with last item in the array
FindLock();
}
}
//simulate what feed the array
//don't look at this unless something should be done at insert time
static Random rnd = new Random(42);
static void FindLock(int add = -1)
{
if(add == -1)
{
add = rnd.Next(1, 4);
}
for(int i = 0;i<add;++i)
{
pool[poolPos++] = rnd.Next(-500, 500) / 100d;
}
}
}
}
profiling result:
based on the profiling, I'm trying to find a way to speed it up, all the solution that I found online use double stack or double queue so they only use head or tail value of the array, the code above can pick any item in the list that meet the requirement so I don't think I can use stack or queue.
With a "priority queue" or "max heap", the table is partially sorted, and many operations are O(log(N)):
max (or min, but not both)
insert one row
delete one row
Item 1 is known to be greater than items 2 and 3. Item 1 is always the max.
Item 2 is known to be greater than items 4 and 5.
Item 3 is known to be greater than items 6 and 7.
etc. In general:
Item [k] is known to be greater than items [2*k] and [2*k+1].
Inserts and deletes get a little tricky since you want to keep the table compact.
One of many references: https://www.techiedelight.com/introduction-priority-queues-using-binary-heaps/
The structure can be handy if items are coming and going a lot, but the important action is to grab the max value. Accessing the max value is O(1), but deleting it is O(N).
By definition, if you're working with an unordered list, finding an item is always going to be O(1) in the best case, and O(n) in the worst case.
You can use a hash table to get better lookup speeds, as well as insert/delete. However the hash algorithm itself can be just as expensive as iterating through your list, so proceed with caution. Depending on the use-case, a hash table might be the way to go.
I am working with Arrays and conditionals statements, little lost right now and was hoping for some input.
So, I created two Arrays
int[] one = new int[] {
4160414, 6610574, 2864453, 9352227, -4750937, -3132620, 2208017,
-2226227, -8415856, -9834062, -3401569, 7581671, 8068562, 7520435,
-9277044, -7821114, -3095212, 966785, 6873349, -8441152, -7015683,
-6588326, -282013, 4051534, 9930123, -3093234 };
int[] two = new int[] {
1099626, 6083415, 8083888, -8210392, 2665304, -8710738, -8708241,
8859200, -1255323, 5604634, 2921294, -7260228, 7261646, 1137004,
5805162, 4883369, 8789460, 9769240, 319012, -7877588, -1573772,
5192333, 1185446, 1302131, 4217472, -3471445};
My next step what i was thinking is i am going to have to loop through each array
for (int i = 0; i < one.Length; i++)
{
int xValue = one[i];
for (int j = 0; j < two.Length; j++)
{
int yValue = two[j];
}
}
Now that i have the index of each Array i need to check wether the index of xValue is less than the index of yValue
if (xValue < yValue)
{
// dO SOMETHING HERE
}
if (yValue < xValue)
{
// Do Something HERE
}
Where i am getting confused at, is with C# from my understanding you can not push new values into an Array, it needs to be a new instance of the array and copy?
So i tried doing
if (xValue < yValue)
{
Array.Copy(one, x, 13);
}
if (yValue < xValue)
{
Array.Copy(two, x, 13)
}
Both Arrays have 26 values, so a new array of 13 would need to be created to insert the checked value, but Array.Copy seems to not be working getting an array out of bounds check lower bounds.
I'm just confused on checking the values of both arrays at their index, then grabbing the smallest value of the checked values then taking that small value and inserting it into a new array, then use a foreach-loop to iterate over it and print the values to the console. FacePalm
You can use LINQ's Zip to achieve this:
int[] smallest = one.Zip(two, (o, t) => Math.Min(o,t)).ToArray();
Essentially, Zip will provide both items to the lambda expression, allowing you to combine them how you see fit. In this case, we just choose the minimum and return it.
Try it online
Basically, you need to define the size of the new array when you declare it. Make it the same size as one. Then add the smallest item from one or two on each iteration by comparing the items in each array at index i.
int[] smallest = new int[one.Length];
for (int i = 0; i < one.Length; i++)
{
if (one[i] < two[i])
{
smallest[i] = one[i];
}
else
{
smallest[i] = two[i];
}
}
This question already has answers here:
Most efficient way to randomly "sort" (Shuffle) a list of integers in C#
(13 answers)
Closed 5 years ago.
I need to create a random array of int with certain parameters.
int[] test = new int[80];
Random random = new Random();
I need to assign 1's and 0's, randomly to the array. I know how to do that.
test[position] = Random.Next(0,2);//obviously with a for loop
But I need to have exactly 20 1's, but they need to be randomly positioned in the array. I don't know how to make sure that the 1's are randomly positioned, AND that there are exactly 20 1's. The rest of the positions in the array would be assigned 0.
I think you need to turn your thinking around.
Consider:
var cnt = 20;
while (cnt > 0) {
var r = Random.Next(0, 80);
if (test[r] != 1) {
test[r] = 1;
cnt--;
}
}
Expanding explanation based on comments from CodeCaster. Rather than generate a random value to place in the array, this code generates and index to set. Since C# automatically initializes the test array to 0 these values are already set. So all you need is to add your 1 values. The code generates a random index, tests it to see if it isn't 1, if so it sets the array element and decrements a count (cnt). Once count reaches zero the loop terminates.
This won't properly function if you need more values than 0 and 1 that is true. Of course the questions explicitly stated that these were the needed values.
"This causes horrible runtime performance". What!? Can you produce any prove of that? There is a chance that the index generated will collide with an existing entry. This chance increases as more 1's are added. Worst case is there is a 19/80 (~23%) chance of collision.
If you know you need exactly 20 of one value, a better way to go about this is to pre-populate the array with the required values and then shuffle it.
Something like this should work:
int[] array = new int[80];
for (int i = 0; i < 80; i++)
{
int val = 0;
if (i < 20)
{
val = 1;
}
array[i] = val;
}
Random rnd = new Random();
int[] shuffledArray = array.OrderBy(x => rnd.Next()).ToArray();
You can do
for (int i = 0; i < 20; i++)
{
var rand = random.Next(0,80);
if (test[rand] == 1)
{
i--;
continue;
}
test[rand] = 1;
}
Remaining are automatically zero.
New to using lists. For automated testing purposes I am generating a list of distinct values. The following is a code block of concern:
Random rnd = new Random();
List<int> lVars = new List<int>();
while (VarsCount < randVarsCount)
{
if(VarsCount > 0)
{
while(lVars.Distinct().Count() != lVars.Count())
{
lRowVars.Insert(VarsCount, rnd.Next(1, 11)); //problem code
}
}
lVars.Add(rnd.Next(1, 11));
MessageBox.Show(lRowVars[aRowVarsCounter].ToString());
aRowVarsCounter++;
}
Basically, how do I check to see if the int being added matches all of the list (as my code doesn't work)....I've tried some other code but ends up being ALOT of extra code and loops; usually when I feel I'm doing something superfluous I find there is an easier way.
When thinking "list with distinct values", think "set" instead if you don't care about ordering (as appears to be the case here). A set only contains a given value at most once. You can do something like
int maxRnd = 11;
int desiredCount = 4;
if (desiredCount > maxRnd) throw new Exception("Impossible.");
HashSet<int> unique = new HashSet<int>();
while (unique.Count < desiredCount)
{
unique.Add(rnd.Next(1, maxRnd));
}
// If needed, convert to a list
var uniqueList = unique.ToList();
I want to produce a selection of random numbers in a range between 1 and 30, ideally this number will alter (to a max of +10) but will always have a range of 1 - 30. I want to be able to do this several times when needed. The numbers that I want to produce within the range will vary in numbers eg maybe I will want only 2 or 5 numbers.
I thought I should produce a static class and use the same random instance with a method that accepts an integer which indicated the total number of numbers I require within the range? Obviously the numbers should be no identical numbers returned from the method for each call. But if one method call produces the same numbers as a previous call then thats fine, but ideally they should differ.
I'm not sure how I would code this or if I'm completely wrong?
Sample code:
public static class getMyNumbers
{
private static Random random = new Random();
public static int[] getThese(int i)
{
int[] wanted = new int[i];
// a loop to generate the numbers???
// this bit I'm not sure about the syntax
// new to c#
return wanted
}
}
Thanks
You just need to loop putting the numbers into the array:
public static int[] getThese(int i)
{
int[] wanted = new int[i];
for (int j = 0; j < i; ++j)
wanted[j] = random.Next(31);
return wanted;
}
Note that the parameter to random.Next() is an exclusive upper range, so passing 31 will generate random numbers between 0 and 30.
As an aside, note that it's customary to use n for a count and i for a loop variable, so it would probably be better to name your variables thus:
public static int[] GetThese(int n)
{
int[] result = new int[n];
for (int i = 0; i < n; ++i)
result[i] = random.Next(31);
return result;
}
Just because everybody loves Linq:
private static Random random = new Random();
public IEnumerable<int> GetRandomInts(int Amount, int Max = 30)
{
return Enumerable.Range(0, Amount).Select(a => random.Next(Max)+1);
}
For no duplicates...
return Enumerable.Range(1, Max).OrderBy(a => random.Next()).Take(Amount);