This question already has answers here:
How do I check if my array has repeated values inside it?
(8 answers)
Closed 5 years ago.
I would like to check the array I passed in the shuffle method for any duplicates.
I would like to also generate a random number that is the size of a.length.
The thing is that I can't figure out how to check if the array has duplicates and if it does it would generate another number until it is unique from the rest.
public int[] Shuffle(int[] a)
{
//check if the array has duplicates
for (int i = 0; i < a.Length; i++)
{
int curValue = random.Next(a.Length);
if(a.Contains(curValue))
{
curValue = random.Next(a.Length);
}
else
{
a[i] = curValue;
}
}
for (int i = 0; i < a.Length; i++)
{
int r = random.Next(a.Length);
int t = a[r];
a[r] = a[i];
a[i] = t;
}
return a;
}
Can anyone help me?
Here is a function that does what you ask as I presume. Include using System.Linq to run it. I went on the basis of your text, because the code did not make your question clear to me. If you meant something differently please clarify.
static int[] Shuffle(int[] a)
{
Random rnd = new Random();
//Remove duplicates from array
int[] distinct = a.Distinct().ToArray();
//Add the same amount of unique numbers that have been removed as duplicates
int len = a.Length - distinct.Length;
int[] newNumbers = new int[len];
int i = 0;
while(i < len)
{
newNumbers[i] = rnd.Next(a.Length); //NOTE: here i put in the length of array a, but with an int array this will always resolve in a shuffled array containing all digits from 0 to the length-1 of the array.
if (!distinct.Contains(newNumbers[i]) && !newNumbers.Take(i).Contains(newNumbers[i]))
{
++i;
}
}
//Randomize the array
int[] b = a.OrderBy(x => rnd.Next()).ToArray();
//Concatenate the two arrays and return it (shuffled numbers and new unique numbers)
return distinct.Concat(newNumbers).ToArray();
}
As I said in the note, if you remain with an integer array and only allow adding of new random replacement number lower than the length of the array, you and up with a shuffled array of all numbers from 0 to the array length.
Since a new array for newNumbers is generated, you also need to check if a newly generated number is not in that array.
Related
string[] n = Console.ReadLine().Split();
for (int i = 1; i <6; i++)
{
int[] a = long.Parse(n[i]);
}
If each number in a row separated with whitespace - you can use your Split more efficiently:
int[] array = Console.ReadLine().Split().Select(int.Parse).ToArray(); // Improved according to #Caius Jard comment
If need array of longs - replace int.Parse with long.Parse and declare variable as long[] array.
You need to add using System.Linq to get access to ToArray extension method.
EDIT.
Insprired by #Caius Jard, non-LINQ version:
// Read input line and split it by whitespace (default)
string[] values = Console.ReadLine().Split();
// Declare arrays for Int or Long values.
// Arrays sizes equals to size of array of input values
int[] arrayOfInts = new int[values.Length];
long[] arrayOfLongs = new long[values.Length];
// Iterate with for loop over amount of input values.
for (int i = 0; i < values.Length; i++)
{
// Convert trimmed input value to Int32
arrayOfInts[i] = int.Parse(values[i].Trim());
// Or to Int64
arrayOfLongs[i] = long.Parse(values[i].Trim());
}
int.Parse and long.Parse may be replaced with Convert.ToInt32 and Convert.ToInt64 if needed.
Please, don't use magic constants: i < 6. Here 6 doesn't necessary equal to n.Length.
You can put it as
string[] n = Console.ReadLine().Split();
List<int> list = new List<int>();
for (int i = 0; i < n.Length; ++i) {
if (int.TryParse(n[i], out int value))
list.Add(value);
else {
// Invalid item within user input, say "bla-bla-bla"
//TODO: either reject the input or ignore the item (here we ignore)
}
}
if (list.Count == a.Length) {
// We have exactly a.Length - 6 valid integer items
for (int i = 0; i < a.Length; ++i)
a[i] = list[i];
}
else {
//TODO: erroneous input: we have too few or too many items
}
I'm studying c# and I was wondering if there is any way to extract positive and negative numbers (integers) from one array to others two, one that contains the positive numbers and the other negative ones
I've tried something like
public static void Main(string[] args)
{
int[] num = new int[50];
Random objeto = new Random();
int i = 0;
for (i = 1; i <= 50; i++)
{
Console.WriteLine("Random numbers:");
num[1] = objeto.Next(-50, 50);
Console.WriteLine(num[1] + "");
}
Console.ReadKey(); here
}
I have to create two other arrays
int[] positive_numbers = int new [N]
int[] negative_numbers = int new [N]
And I guess I should create a method, but I do not know how I have to do it.
You could use LINQ:
var positiveNumbers = numbers.Where(n => n > 0).ToArray();
var negativeNumbers = numbers.Where(n => n < 0).ToArray();
Or an alternative approach is to count how many even and odd numbers you have, create two arrays and then populate them. This assumes that you want the arrays to be exactly the correct length.
// Variables to store counts of positive and negative numbers
int positiveCount = 0;
int negativeCount = 0;
// Because we'll be building new arrays, we need to track our
// position within them, so we create two variables to do that
int positiveIndex = 0;
int negativeIndex = 0;
// loop through once to count the positive and negative numbers
foreach (var number in numbers)
{
if (number > 0)
{
++positiveCount; // same as positiveCount = positiveCount + 1
}
else if (number < 0)
{
++negativeCount;
}
}
// now we know how many +ve and -ve numbers we have,
// we can create arrays to store them
var positiveNumbers = new int[positiveCount];
var negativeNumbers = new int[negativeCount];
// loop through and populate our new arrays
foreach (var number in numbers)
{
if (number > 0)
{
positiveNumbers[positiveIndex++] = number;
// number++ will return the value of number before it was incremented,
// so it will first access positiveNumbers[0] and then positiveNumbers[1], etc.
// each time we enter this code block.
}
else if (number < 0)
{
negativeNumbers[negativeIndex++] = number;
}
}
An alternative approach to the initial count would be to define both arrays to be the same length as the numbers array, and then use positiveIndex and negativeIndex to determine the maximum populated index in the positiveNumbers and negativeNumbers arrays. The downside is that it uses a little more memory (but memory is cheap for such a small set), and the upside is that you only have to loop through once so it's more performant.
If your situation allows, it might be easier to use generic lists instead:
var positiveNumbers = new List<int>();
var negativeNumbers = new List<int>();
foreach (var number in numbers)
{
if (number > 0)
{
positiveNumbers.Add(number);
}
else if (number < 0)
{
negativeNumbers.Add(number);
}
}
Generic lists are basically fancy wrappers around internal arrays. The list starts out with an array of a relatively small size. As you add items to the list, more arrays are generated to store all of your items. You can see the current overall size of the internal arrays by checking the list's .Capacity property. Do not confuse Capacity with Count. Count shows the number of items actually in your list, whereas Capacity shows the number of items your list can hold before expanding.
Note that in these answers, zeroes will be excluded since you only asked for positive and negative numbers, and zero is neither. As highlighted by Max Play's comment, you should change > to >= if you consider zero to be positive.
Assuming you'll handle 0 as positive, add a method to check for positive.
private static bool isNegtive(int number)
{
return number < 0;
}
I'd use list over array for unknown quantities. It'd go something like this:
public static void SeparateRandomNumbers()
{
IList<int> positive_numbers = new List<int>();
IList<int> negative_numbers = new List<int>();
Random objeto = new Random();
for (int i = 0; i < 50; i++)
{
var number = objeto.Next(-50, 50);
if (isNegtive(number))
{
negative_numbers.Add(number);
}
else
{
positive_numbers.Add(number);
}
}
}
How do I store a random number into my array, but only if there is not a duplicate already inside the array? My code below still inputs a duplicate number.
Random rand = new Random();
int[] lotto = new int [6];
for (int i = 0; i < lotto.Length; i++)
{
int temp = rand.Next(1, 10);
while (!(lotto.Contains(temp)))//While my lotto array doesn't contain a duplicate
{
lotto[i] = rand.Next(1, 10);//Add a new number into the array
}
Console.WriteLine(lotto[i]+1);
}
Try this:
Random rand = new Random();
int[] lotto = new int[6];
for (int i = 0; i < lotto.Length; i++)
{
int temp = rand.Next(1, 10);
// Loop until array doesn't contain temp
while (lotto.Contains(temp))
{
temp = rand.Next(1, 10);
}
lotto[i] = temp;
Console.WriteLine(lotto[i] + 1);
}
This way the code keeps generating a number until it finds one that isn't in the array, assigns it and moves on.
There are a lot of ways to 'shuffle' an array, but hopefully this clears up the issue you were having with your code.
What you really want is to shuffle the numbers from 1 to 9 (at least that's what your example is implying) and then take the first 6 elements. Checking for duplicates is adding unnecessary indeterminism and really is not needed if you have a shuffle.
E.g take this accepted answer for a Fisher-Yates shuffle and then take the first 6 elements for lotto.
This would then look like this:
lotto = Enumerable.Range(1,9)
.Shuffle()
.Take(6)
.ToArray();
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
filling a array with uniqe random numbers between 0-9 in c#
I have a array like "page[100]" and i want to fill it with random numbers between 0-9 in c#...
how i can do this?
i used :
IEnumerable<int> UniqueRandom(int minInclusive, int maxInclusive)
{
List<int> candidates = new List<int>();
for (int i = minInclusive; i <= maxInclusive; i++)
{
candidates.Add(i);
}
Random rnd = new Random();
while (candidates.Count > 1)
{
int index = rnd.Next(candidates.Count);
yield return candidates[index];
candidates.RemoveAt(index);
}
}
this way :
int[] page = UniqueRandom(0,9).Take(array size).ToArray();
but it just gave me 9 unique random numbers but i need more.
how i can have a array with random numbers that are not all the same?
How about
int[] page = new int[100];
Random rnd = new Random();
for (int i = 0; i < page.Length; ++i)
page[i] = rnd.Next(10);
Random r = new Random(); //add some seed
int[] randNums = new int[100]; //100 is just an example
for (int i = 0; i < randNums.Length; i++)
randNums[i] = r.Next(10);
You have an array of 100 numbers and draw from a pool of 10 different ones. How would you expect there to be no duplicates?
Don't overcomplicate the thing, just write what needs to be written. I.e.:
Create the array
Loop over the size of it
Put a random number between from [0, 9] in the array.
I was having this discussion with my friend who had this question asked to him in the Interview. The Question goes like this. Write a Function which takes in a byte array(2 dimensional) as input along with an Integer n, The initial assumption is all the elements of M*N byte array is zero and the problem is to fill 'n' Byte array elements with value 1, For instance if M=5 and N=5 and the n value is 10 the Byte array should've 10/25 elements to be 1 and rest of the 15 values to be 0. The values filled should be random and one cell in byte array should be filled only once. I was fascinated to try solving this on my own. I've attached the code I've come up with so far.
public Boolean ByteArrayFiller(int a,int b, int n)
{
int count = n;
int iLocalCount = 0;
byte[,] bArray= new byte[a,b];
for (int i = 0; i <a; i++)
for (int j = 1; j <b; j++)
bArray[i, j] = 0;
Random randa= new Random();
int iRandA = randa.Next(a);
int iRandB = randa.Next(b);
while (iLocalCount < n)
{
if (bArray[iRandA, iRandB] == 0)
{
bArray[iRandA, iRandB] = 1;
iLocalCount++;
}
iRandA = randa.Next(a);
iRandB = randa.Next(b);
continue;
}
//do
//{
// //iRandA = randa.Next(a);
// //iRandB = randa.Next(b);
// bArray[iRandA,iRandB]=1;
// iLocalCount++;
//} while (iLocalCount<=count && bArray[iRandA,iRandB]==0);
return true;
}
The code i wrote is in C# but it's straight forward to understand. It's able to do the purpose of the question( I did some trials runs and results came out correctly) perfectly but I have used Random object in C#(Equivalent to Math.Rand in Java) to fill up the byte array and I keep thinking if Rand returns the same values for a and b. There is a good chance for this to go indefinitely. Is that the purpose of the question? or Does the solution that i came up for this question is good enough!
I am curious to see how experts here solve this problem? I am just looking for new ideas to expand my horizon. Any pointers would be greatly appreciated. Thanks for taking the time to read this post!
A while loop trying random locations until it finds a good one is generally a very bad approach. If n = M*N, then the last one will have a probability of 1/(M*N) of finding a match. If M*N are sufficiently large, this can be extremely inefficient.
If M*N is not too large, I would create a temporary array of M*N size, fill it with the numbers 0 through (M*N)-1, and then permutate it - i.e. you walk through it and swap the current value with that of a random other value.
Then you go to the first n elements in your array and set the appropriate cell. (row = value / columns, col = value % columns).
I would treat the array, logically, as a one-dimensional array. Fill the first n positions with the prescribed value, and then shuffle the array.
Given a byte array, and the number of rows and columns in the array, and assuming that the array is already filled with 0:
int NumElements = NumRows * NumCols;
for (int i = 0; i < NumElementsToFill; ++i)
{
int row = i / NumRows;
int col = i % NumCols;
array[row, col] = 1;
}
// Now shuffle the array
Random rnd = new Random();
for (int i = 0; i < NumElements; ++i)
{
int irow = i / NumRows;
int icol = i % NumCols;
int swapWith = rnd.Next(i+1);
int swapRow = swapWith / NumRows;
int swapCol = swapWith % NumCols;
byte temp = array[irow, icol];
array[irow, icol] = array[swapRow, swapCol];
array[swapRow, swapCol] = temp;
}
The key here is converting the one-dimensional index into row/col values. I used / and %. You could also use Math.DivRem. Or create Action methods that do the get and set for you.
Choose a number, which is larger than both N and M and is prime (or co-prime to both N and M). Let's call this number p.
Loop until you've set x numbers:
Generate a random number less than N*M. Call this number `l`.
Then the next place to put the number will be `p*l%(N*M)`, if that position hasn't been set.
A downside to this approach is that if the array is filling up, you'll have more collisions.
Bascially, you need to choose n unique random numbers from range [0, p) (where p = M * N), and map them to positions of 2-dimensional array.
Naive approaches are 1) generate non-unique numbers with retry 2) fill an array with numbers from 0 to p-1, shuffle it and take first n numbers (takes O(p) time, O(p) memory).
Another approach is to choose them with the following algorithm (O(n2) time, O(n) memory, code in Java):
public Set<Integer> chooseUniqueRandomNumbers(int n, int p) {
Set<Integer> choosen = new TreeSet<Integer>();
Random rnd = new Random();
for (int i = 0; i < n; i++) {
// Generate random number from range [0, p - i)
int c = rnd.nextInt(p - i);
// Adjust it as it was choosen from range [0, p) excluding already choosen numbers
Iterator<Integer> it = choosen.iterator();
while (it.hasNext() && it.next() <= c) c++;
choosen.add(c);
}
return choosen;
}
Mapping of generated numbers to positions of 2-dimensional array is trivial.