Random number generator choosing only between given few numbers in C# - c#

I know how to choose random numbers between two numbers. However I don't know how to make it to choose a random number that I tell it.
This is what I am trying to do. I have 5 integers.
int Hamburger = 5;
int Sandwich = 7;
int ChickenSalad = 10;
int Pizza = 15;
int Sushi = 20;
5,7,10,15,20 are the prices of each food and I want to make it so that it would choose a random number from these chosen numbers. 5,7,10,15,20.
I am new to C# so I don't really know much about this. I found this
randomNoCorss = arr[r.Next(arr.Length)];
in another post but I don't understand it and I don't know how I can put it in my code.

You have to create an array of your possible values and then randomly generate an index for that array:
int Hamburger = 5;
int Sandwich = 7;
int ChickenSalad = 10;
int Pizza = 15;
int Sushi = 20;
Random r = new Random();
var values = new[] { Hamburger, Sandwich, ChickenSalad, Pizza, Sushi };
int result = values[r.Next(values.Length)];
What this does is it takes all of your given values and places them inside an array. It then generates a random integer between 0 and 4 and uses that integer to get a value from the array using the generated integer as the array's index.

Full code is:
Random r = new Random();
int[] priceArray = new int[] { 5, 7, 10, 15, 20 };
int randomIndex = r.Next(priceArray.Length);
int randomPrice = priceArray[randomIndex];

You need to add your values in an array and then you can choose a random number from that array
int[] myNumbers = new int[] { 5, 7, 10, 15, 20 };
var random = new Random();
var numberResult = myNumbers[random.Next(5)];

You can do this in LINQ:
int[] intArray = new int[] { 5, 7, 10, 15, 20 };
int result = intArray.OrderBy(n => Guid.NewGuid()).Select(x => x).Take(1)
.SingleOrDefault();
The result will be random based on your declared array of integers in variable intArray.
Or you can do this by getting the random index of your array:
int[] intArray = new int[] {5, 7, 10, 15, 20 };
Random rndom = new Random();
int index = rndom.Next(0, intArray.Length - 1); //Since int array always starts at 0.
int intResult = intArray[index];
Let me know if you need more clarifications.

Related

Previous index in an array c#

I have an array initialized as such:
int[] myArray = new int[] {9, 8, 7, 3, 4, 5, 6, 2, 1};
I then have a for() loop searching the array for the highest value each time using:
int maxValue = myArray.Max();
int maxIndex = myArray.ToList().IndexOf(maxValue);
It obviously keeps finding 9 as the highest value.
I want it to first set the previously indexed value to a randomized value below the current maxValue but above -1 and continue searching the array for the next maxValue and print it to console.
(If all values reach a value == 0 then the simulation stops) <- this part I know how to do.
Is this possible? If so, how?
I guess this might be what you want. Let me know how it works for you.
using System;
using System.Linq;
public class Program
{
private static Random random = new Random();
public static void Main()
{
int[] myArray = new int[] {9, 8, 7, 3, 4, 5, 6, 2, 1};
Simulate(myArray);
}
static void Simulate(int[] myArray)
{
int maxValue = myArray.Max();
Console.WriteLine(string.Join(" ",myArray));
var continueSimulation = true;
do{
int maxIndex = myArray.ToList().IndexOf(maxValue);
var randomValue = random.Next(0, maxValue);
myArray[maxIndex] = randomValue;
maxValue = myArray.Max();
if (maxValue == 0)
continueSimulation = false;
Console.WriteLine(string.Join(" ",myArray));
}while(continueSimulation);
}
}
You can check it out on this fiddle.
Hope this helps!
If you want to find the second max, you can mark the position of the first one and continue with your same approach. How can be done? 1- initialize an array of bool with the same length of the array where you want to find the max, then find the first max and mark that position in the second array with true, if you want the second max, make a loop through the array asking for the max and if that element is not marked in the second array of bool. Finally you will get the second max .
Another idea is taking the values in a list and once you find the max, remove the max from the list to continue with the same algorithm but with an array of less values
static int Max(int [] num)
{
int max = num[0];
for(int i = 0; i < num.Length; i ++)
{
if(num[i] > max)
max = num[i];
}
return max;
}
static int SecondMax(int[]a)
{
if(a.Length < 2) throw new Exception("....");
int count = 0;
int max = Max(a);
int[]b = new int[a.Length];
for(int i = 0; i < a.Length; i ++)
{
if(a[i] == max && count == 0)
{
b[i] = int.MinValue;
count ++;
}
else b[i] = a[i];
}
return Max(b);
}
Honestly, the question feels a bit unusual, so if you share why you're trying to do this, maybe someone could suggest a better approach. However, to answer your original question, you can just use .NET's random number generator.
int[] myArray = new int[] { 9, 8, 7, 3, 4, 5, 6, 2, 1 };
Random random = new Random();
for (int max = myArray.Max(); max > 0; max = myArray.Max())
{
int index = myArray.IndexOf(max);
DoSomething(max);
myArray[index] = random.Next(0, max);
}
From the MSDN doco on Random, the upper bound is exclusive, which means that it will generate a random number between 0 and max-1, unless max==0, in which case it will return 0.

Random divisable at least one of two integers in c#

I've got an integer that I'd like to assign a value to by using Random.
The randomly chosen number must be divisable by 2 or 5 (or both).
For divisable only by two I would just multiply the Random result * 2, but it's not an option here.
How to do this?
edit:
I came up with this code, it's probably very inefficient though:
static void Main(string[] args)
{
int[] tab = new int[5];
Random random = new Random();
int i = 0;
while (i < tab.Length)
{
int tempInteger = random.Next(101);
if (tempInteger % 2 == 0 || tempInteger % 5 == 0)
{
tab[i] = tempInteger;
i++;
}
}
}
What about something like:
void Main()
{
var xs = new[] { 2, 5 };
var rand = new Random();
var r = xs[rand.Next(0, xs.Length)] * rand.Next(SOME_UPPER_BOUND);
}
The idea is that we first choose either 2 or 5, then multiply that choice by an arbitrary number between 0 and SOME_UPPER_BOUND.
I tested it with SOME_UPPER_BOUND = 101, and empirically r is either divisible by 2, 5, or 10.
If you want equal probabilities of divisibility by either 2, 5, or both (i.e. 10), then change the first line to var xs = new[] {2, 5, 10}.
It's not explicitly meantioned in the question but I would expect a behavior where each result number is generated with same probability. The solution suggested by #RodrickChapman works well but for example number 10 will appear in the result twice more often than number 6. It's due to the fact, that 10 can be generated as 2*5 and also as 5*2 but number 6 can be only generated as 2*3
First let's make simple observation: each result number must end with number 0, 2, 4, 5, 6 or 8. All we need to do is to randomly choose from these numbers and add this number to some random number which ends with 0 (0, 10, 20, 40, ....).
int upperBound = 100;
var random = new Random();
var choices = new[] { 0, 2, 4, 5, 6, 8 };
var baseNumber = random.Next(0, upperBound / 10) * 10;
var lastDigit = choices[random.Next(choices.Length)];
var result = baseNumber + lastDigit;
Well you could always multiply it by 10 - that way it will always be divisible by 2 and 5.
In that case, I would create two random numbers like this. One is the base one, another one ranges from 0 to 2, which will be mapped to multiply of 2, 5, and 10 respectively, and then multiply the two of them such as this:
Random rand = new Random();
int baseInt = rand.Next(101);
int choiceInt = rand.Next(0, 3);
List<int> mapInts = new List<int>() { 2, 5, 10 };
int finalInt = baseInt * mapInts[choiceInt];
the finalInt would always be divisible by 2, 5 or 10.
Better solution is to multiply random generated number to 2 or 5.
Or you can generate array of number which is divisible and randomly select them from array by randomly generated index.

Using one variable to input 5 integers C#

I am using C# and i am trying to find the the average of 5 values but i can only use 2 variables.
How can you input 5 integers into one variable and display the average of said integers
You can use List like this:
var list = new List<int>(){ 1, 2, 3, 4, 5 };
var average = list.Average();
using Average you'll get average of all values in list
Here you have all functions of Enumerable, you can for e.g. sum all values with Sum
Use a collection like a List<int> and the extension method Enumerable.Average:
List<int> numbers = new List<int>{ 10, 20, 30, 40, 50 };
double average = numbers.Average(); // 30.0
Use List.Add to add single integers:
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
// ...
Take the input values in a Integer list or array then use the following code
List<int> intlist=new List<int>();
intlist.Add(2);
intlist.Add(3);
..
..
var average= intlist.Average();
Using Average will computes the average of a sequence of all the integers in the list.
UPDATE: or if the case is to use integers only then you need to use the following code (Remember to validate the readline() entries)
public decimal Average()
{
int value = 0;
for(int i=0;i<5;i++)
{
value+=ConvertToInt32(Console.ReadLine());
}
return value/5;
}
What about using array? I think array is one variable in your case
int[] input = new int[5];
input[0] = 5;
input[1] = 40;
input[2] = 15;
input[3] = 50;
input[4] = 25;
int sum = 0;
foreach(int i in input)
{
sum = sum + i;
}
sum = sum / input.Length;
Console.WriteLine(sum.ToString());
#up Yeah that's better way!
You dont need arrays, or lists or anything remotely similar. Pseudo-code:
private int sum = 0;
private int count = 0;
while (user inputs valid number)
{
sum += userInput;
count++;
}
return sum / count;
Only two variables.
If you just want solution without List<int> then here it is
int[] arr=new int[5];
arr[0]=10;arr[1]=20;...arr[4]=50;
int sum=0;
foreach(int x in arr)
{
s+=x;
}
s=s/arr.Length;//s is average
If you want list
List<int> list = new List<int>(){ 1, 2, 3, 4, 5 };
var average = list.Average();

How to generate random INT that cannot be a value in a List<int>?

I'm trying to do the following.
Let's say I have a List, and I want to generate a new int in a specific range, but the value cannot be already defined in the List.
List<int> PredefinedIntsList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
int NewRandomValue = rnd.Next(0, 10);
rnd.Next (obviously) comes up with 1, 3, 4, 8 or 9. But I ONLY want it to return 2, 5, 6, 7 or 10.
Any ideas?
As always, LINQ is your friend:
[TestMethod]
public void RandomTest()
{
var except = new[] {1, 2, 3, 5};
GetRandomExcept(1, 5, except).Should().Be(4);
}
private static int GetRandomExcept(int minValue, int maxValue, IEnumerable<int> except)
{
return GetRandoms(minValue, maxValue).Except(except).First();
}
private static IEnumerable<int> GetRandoms(int minValue, int maxValue)
{
var random = new Random();
while (true) yield return random.Next(minValue, maxValue);
}
Just keep in mind that you never should call GetRandoms().ToArray() or .Max() or .OrderBy() and so on, because you will get an endless loop and generate randoms forever.
What you can do though, is call GetRandoms().Take(10).ToArray() to get the next 10 random integers in an array.
Try examining if you can use the contains() method of List class... Simple solution would be to just generate values and checking contains and rejecting values that are already in the List until you get a value that is not. Also it might be more appropriate to use the Set Class because a set can not contain two elements that are equal.
What you need to do sample from other set. Lets say P is your predefinedIntsList and A is {1,2...9}.
You need to create a list, N = A-P. You will randomly sample from this set of numbers. It can be written more elegantly I suppose but see below example.
class Program
{
static void Main(string[] args)
{
List<int> predefinedIntsList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
List<int> newIntsList = new List<int>();
int upperBound = 10;
for (int i = 0; i < upperBound; i++)
{
if (!predefinedIntsList.Contains(i))
{
newIntsList.Add(i);
}
}
for (int i = 0; i < 20; i++)
{
int newRandomValueIndex = rnd.Next(0, newIntsList.Count);
int newRandomValue = newIntsList[newRandomValueIndex];
Console.WriteLine(newRandomValue);
}
}
}
Output
2
0
6
7
5
5
5
7
0
7
6
6
5
5
5
0
6
7
0
7
rnd.Next (obviously) comes up with 1, 3, 4, 8 or 9. But I ONLY want it
to return 2, 5, 6, 7 or 10.
Obviously not, it will return value that is either 0, 1, 2, 3, 4, 5, 6, 7, 8 or 9 :P. If you're looking to include 10, and not 0, you want .Next(1, 11)
There are two choices that can work: either try generating values until you succeed, or if the range is small enough, generate the range, mark elemens that can't be picked, and sort them to last ones, and then pick random between [0..possibleToPickElementsCount]
The first approach would look something like this:
public static class RandomExtensions
{
public static int Next(this Random random,
int minInclusive,
int maxExclusive,
IList<int> values)
{
// this will crash if values contains
// duplicate values.
var dic = values.ToDictionary(val => val);
// this can go into forever loop,
// think about this a bit.
for(;;){
var randomNumber= random.Next(minInclusive, maxExclusive);
if(!dic.ContainsKey(randomNumber))
return randomNumber;
}
}
}
The second approach is this, however it's only to give you an idea:
public static class RandomExtensions
{
class NormalizedPair
{
public int Value {get;set;}
public PairStatus Status {get;set;}
public NormalizedPair(int value){
Value = value;
}
public enum PairStatus {
Free,
NotFree
}
}
private static Random _internalRandom = new Random();
public static int Next(this Random random,
int minInclusive,
int maxExclusive,
IList<int> values)
{
var elements = maxExclusive - minInclusive;
var normalizedArr = new NormalizedPair[elements];
var normalizedMinInclusive = 0;
var normalizedMaxExclusive = maxExclusive - minInclusive;
var normalizedValues = values
.Select(x => x - minInclusive)
.ToList();
for(var j = 0; j < elements; j++)
{
normalizedArr[j] = new NormalizedPair(j){
Status = NormalizedPair.PairStatus.Free
};
}
foreach(var val in normalizedValues)
normalizedArr[val].Status = NormalizedPair.PairStatus.NotFree;
return normalizedArr
.Where(y => y.Status == NormalizedPair.PairStatus.Free) // take only free elements
.OrderBy(y => _internalRandom.Next()) // shuffle the free elements
.Select(y => y.Value + minInclusive) // project correct values
.First(); // pick first.
}
}
Or, if you're fan of sets:
public static int Next2(this Random random,
int minInclusive,
int maxExclusive,
IList<int> values)
{
var rangeSet = new HashSet<int>(
Enumerable.Range(
minInclusive,
maxExclusive - minInclusive));
// remove gibberish
rangeSet.ExceptWith(new HashSet<int>(values));
// this can be swapped out with
// yates shuffle algorithm
return rangeSet.OrderBy(x => _internalRandom.Next())
.First();
}
Rather than write logic to determine whether the random number has already been selected I prefer to generate a second list with the items in a random order.
That is easy to do with LINQ
var originalList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
var secondList = originalList.OrderBy(x=>rnd.NextDouble());
The call to rnd.NextDouble returns a random seed that is used by the OrderBy method to sort each int value.
When I need to run thought the randomized items more than once, with a new sort order each time I walk the list, I will use a Queue to store the items. Then dequeue the items as needed. When the queue is empty it's time to refill.
private Queue<int> _randomizedItems;
private void RandomTest()
{
var originalList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
var temp = originalList.OrderBy(r=>rnd.NextDouble());
_randomizedItems = new Queue<int>(temp);
while (_randomizedItems.Count >0)
{
MessageBox.Show(_randomizedItems.Dequeue().ToString());
}
}

How to set random number to random label

i have int array with 9 numbers and i want to set a random number to a random label, (4 labels). at button click add next random number to next label so i have this code :
int[] CardDeck = new int[9] { 3, 4, 5, 6, 7, 8, 9, 10, 11 };
Random RandomCard = new Random();
int randomIndex = RandomCard.Next(0, CardDeck.Length);
int randomNumber = CardDeck[randomIndex];
if (string.IsNullOrEmpty(L1.Text))
{
L1.Text = Convert.ToString(randomNumber);
return;
}
if (string.IsNullOrEmpty(L2.Text) && Convert.ToInt32(L1.Text) > 0)
{
L2.Text = Convert.ToString(randomNumber);
}
but something is wrong it sets same numbers to two labels.
This is because you are using the same randomNumber variable.
You should generate another random number for the remaining label.
int randomLabel1 = CardDeck[RandomCard.Next(0, CardDeck.Length)];
int randomLabel2 = CardDeck[RandomCard.Next(0, CardDeck.Length)];
Then you should use these two variables with the labels accordingly.
Please note that this approach does not guarantee unique random numbers. Same numbers for both labels may occur.
PS: You can also use the same randomNumber to store a new random number, but remember to do it AFTER setting the first label:
int randomNumber = CardDeck[RandomCard.Next(0, CardDeck.Length)];
//Set first label
randomNumber = CardDeck[RandomCard.Next(0, CardDeck.Length)];
//Set second label

Categories