Algorithm to get 9 different numbers in an array [duplicate] - c#

This question already has answers here:
Is using Random and OrderBy a good shuffle algorithm? [closed]
(13 answers)
Closed 7 years ago.
I need help to create an algorithm to make 9 random numbers. Each number must not be equal to any other. Restated as 9 random numbers from 1-9.
I had something like this in mind:
int[] numlist = new int[9];
Random rand = new Random();
int temp;
foreach (int i in numlist) {
temp = rand.Next(1, 10);
//check if temp is already a value of a lower index in numlist
//if so, rolls another random number and checks it again...
numlist[i] = temp;
}
I had a method that had ifs inside for loops inside while loops inside foreach loops and such...

It sounds to me, like you may be better-off starting with your list of 1..9 - and shuffling it, to get a random order.
Use a Fisher–Yates shuffle
var random = new Random();
int[] array = Enumerable.Range(1, 9).ToArray();
for (int i = array.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
var tmp = array[j];
array[j] = array[i - 1];
array[i - 1] = tmp;
}

If you know what values you're needing then just OrderBy and it will randomise them.
var numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
var shuffled = numbers.OrderBy(a => System.Guid.NewGuid()).ToArray();

Related

random numbers only once in an array c# [duplicate]

This question already has answers here:
Generating random, unique values C#
(17 answers)
Closed 4 years ago.
I want to generate random numbers and put them in an array, but they should only appear once in this array. It's like a mini lotto game.
This is the code I have right now:
int[] arrA = new int[10];
Random random = new Random();
for (int i = 0; i <= arrA.Length -1; i++)
{
arrA[i] = random.Next(1, 15);
Console.WriteLine(arrA[i]);
}
Console.ReadKey();
Random numbers are generated and put in this Array. I only need to know how it's possible to program that they only appeare once.
Use HashSet<T>. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.
Something like this:
using System;
using System.Collections.Generic;
HashSet<int> numbers = new HashSet<int>();
for (int i = 0; i < 10; i++)
{
// Start with a random number
//
int value = random.Next(1,15);
// Check whether you already have that number
// Keep trying until you get a unique
//
while (numbers.Contains(value)) {
value = random.Next(1,15);
}
// Add the unique number to the set
numbers.Add(value);
}
foreach (int i in numbers)
{
Console.Write(" {0}", i);
}
int[] arrA = new int[10];
Random random = new Random();
for (int i = 0; i <= arrA.Length - 1; i++)
{
var number = random.Next(1, 15);
while (arrA.Any(n => n == number))
{
number = random.Next(1, 15);
}
arrA[i] = number;
Console.WriteLine(arrA[i]);
}
Console.ReadKey();
Everytime you generate a new number, instead of putting it in the array right away check the array from the start to the current position (using a for-loop). If it's not there insert the generated number, otherwise generate a new one and repeat the process.

How do I Randomize four numbers without them being the same thing in c#? [duplicate]

This question already has answers here:
Generating random, unique values C#
(17 answers)
Closed 6 years ago.
I'm trying to randomize four numbers without them being the same, or else it breaks my code. What can I do to so that they are all the same?
This is my code:
Random r = new Random();
_unknown1 = r.Next(1, 8);
_unknown2 = r.Next(1, 8);
_unknown3 = r.Next(1, 8);
_unknown4 = r.Next(1, 8);
If I understand your question correctly. You dont want to repeat your random numbers. This might do the trick for you
List<int> randomNumbers = new List<int>();
for (int i=0; i<4; i++)
{
int number;
do
{
number = random.Next(1, 8);
}
while (randomNumbers.Contains(number));
randomNumbers.Add(number);
}
Pull your random numbers from a randomized list:
Random r = new Random();
var set = Enumerable.Range(1, 8)
.OrderBy(x => r.Next())
.Take(4)
.ToList();
_unknown1 = set[0];
_unknown2 = set[1];
_unknown3 = set[2];
_unknown4 = set[3];

C# variable or array with number range (example. 1 - 100)

I'm fairly new to C# and I'm doing a school project, i need to figure out how to get a variable or an array with numbers from 1 to 100 without entering every single number in an array for example int[] numbersArray {1,2,3,4,5,6,7,8,9,10...}; because that takes a long time and doesn't look very efficient.
I'm using C# Visual Studio Express 2010. It would mean alot to me if you could answer this for me. I'm gonna be using it in an if statement like so:
if(numbersArray.Contains(numbersInput))
{
Console.WriteLine("numbersInput was a number from 1 to 100")
}
You can use Enumerable.Range to create a range of numbers:
int[] arr = Enumerable.Range(1, 100).ToArray();
If you're assignment is just to print a message if the input is within a range you simply can do this:
if (numbersInput >= 1 && numbersInput <= 100)
Console.WriteLine("numbersInput was a number from 1 to 100");
But if you really need to create an array with numbers 1..100 you can use a for-loop:
var numbersArray = new int[100];
for (var i = 1; i <= 100; i++)
numbersArray[i - 1] = i;
Or simply use a little Linq:
var numbersArray = Enumerable.Range(1, 100).ToArray();
you could just use a for loop with the iterator of the loop as the counter:
int[] numbersArray = new int[100] // initialise array to 100 elements.
for (int i = 1; i <= 100; i++)
{
numbersArray[i - 1] = i; // note we are using 0-based indexing to access elements of the array
}
Other way...
int[] arr = new int[100];
for(int i = 0; i < arr.Length; ++i)
{
arr[i]=i+1;
}

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();

Re sizing array [duplicate]

This question already has answers here:
Deleting A Specified Element In An Array Using Random Class
(4 answers)
Closed 9 years ago.
int oldLength = numbers.Length;
int[] arrTmp = numbers;
numbers = new int[oldLength - 1];
Array.Copy(arrTmp, numbers, Token);
Array.Copy(arrTmp, r+1, numbers, Token, oldLength - Token - 1);
This all i got to remove a specified element from a value type array but it doesn't work.
I got 4 elements of value type array. I have stored 4 different numbers in it.
array[0] = 2;
array[1] = 4;
array[2] = 6;
array[3] = 8;
i got a random class to randomly pick a number if it is 2 has to be removed from my array in an ascending sequential order each element should be inspected and eliminated.
You would do much easier using the List class
List<int> l = new List<int>();
l.Add(2);
l.Add(4);
...
l.Remove(2);
int oldLength = numbers.Length;
int[] arrTmp = new int[oldLength - 1];
for(int i = 0, j = 0; i < oldLength || j < arrTmp.Length; i++)
{
if(numbers[i] == Token)
continue;
arrTmp[j++] = numbers[i];
}
using linq:
var newArray = numbers.Where(n=> n!= Token).ToArray();
This would be the general approach:
int oldLength = numbers.Length;
int[] arrTmp = numbers;
numbers = new int[oldLength - 1];
Array.Copy(arrTmp, numbers, r);
Array.Copy(arrTmp, r + 1, numbers, r, oldLength - r - 1);
Note the use of r everywhere. Here r would be the index of the element to omit.
If you really need to use plain arrays and copy their contents using Array.Copy (which is not a common way of handling things in .NET), then start by using a pen and write down correct indices and lengths of the array parts you are trying to copy.
Starting to code the solution before you know how to solve it won't get you far.
So, start with an example array and a random index:
// starting array
int[] array = { 0, 1, 2, 3, 4, 5, 6, 7 };
// index to remove
int indexToRemove = new Random().Next(array.Length);
Now, presume that indexToRemove is 3 and try to do it by hand:
Part 1: { 0, 1, 2 } (start = 0, length = 3)
Part 2: { 4, 5, 6, 7 } (start = 4, length = 4)
From this concrete example, you can try to infer the general formula for offset and length of these two array parts:
Part 1: start = 0, length = (indexToRemove - 1)
Part 2: start = (indexToRemove + 1), length = (array.Length - indexToRemove - 1)
The code itself is then trivial:
var len = array.Length;
var newArray = new int[len - 1];
Array.Copy(array, 0, newArray, 0, indexToRemove - 1);
Array.Copy(array, indexToRemove + 1, newArray, indexToRemove, len - indexToRemove - 1);
Additionally, the Array.Copy can be used to copy a part of an array over itself, which means you can just move the second part of the array back by one position, and then resize the initial array using Array.Resize:
// do not create a new array, but simply "move" the 2nd part to left
Array.Copy(array, indexToRemove + 1, array, indexToRemove, len - indexToRemove - 1);
// finally, resize the original array
Array.Resize(ref array, array.Length - 1);
Of course, if you simply used a List<int>, then you would simply use the List<T>.RemoveAt method to remove the item:
var list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int indexToRemove = new Random().Next(list.Count);
list.RemoveAt(indexToRemove);

Categories

Resources