Random divisable at least one of two integers in c# - 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.

Related

Access last 3 elements of the array in c# and perform action in a single statement

For example, I have n number of integer array elements in c#. Can we access the last 3 elements of the array and modify these elements for instance multiple each element by 4. Can we achieve this in a single statement instead of using foreach/for loop(can we use the regular expression)?
Before operation
arr[0] = 3
..
..
arr[n-3] = 1
arr[n-2] = 5
arr[n-1] = 6
After operation
arr[0] = 3
..
..
arr[n-3] = 4
arr[n-2] = 20
arr[n-1] = 24
You can do this:
var arr = new int[] {1, 2, 3, 4, 5};
var result = arr.TakeLast(3).Select(x => x * 4).ToArray();
p.s. this is done in .NET 6
With C# 8 (i.e. dotnet core 3) and later you can also use Ranges to write as a one-liner:
int[] a = { 3, 4, 5, 6, 7, 8, 9, 1, 5, 6 };
var result = a[..^3].Concat(a[^3..].Select(e => e * 4));
a[..^3] does return all elements except the last 3.
a[^3..] does return the last 3 elements, which are then multiplied by 4.
The two arrays are then concatenated.
If you want to use result as an array, add ToArray().
If you do not have a formula that applies to all of them you could use tuples:
int []x = new[] {10, 20, 30, 40, 50, 60};
var len =x.Length;
(x[len-3], x[len-2], x[len-1]) = (6, 7659, 854);
Of course, this only works if the array has at least 3 elements. If you have a formula and need to select a dynamic number of items for update, then #Jim de Vries' answer works best.
You can use arr.Length and sub by 3, 2, 1 Like:
int[] arr = new int[] { 1, 2, 3, 4, 5, 6 };
int arrLength = arr.Length;
Console.WriteLine("Before Operation: {0}", string.Join(", ", arr));
arr[arrLength - 3] *= 4;
arr[arrLength - 2] *= 4;
arr[arrLength - 1] *= 4;
Console.WriteLine("After operation: {0}", string.Join(", ", arr));
You can use LINQ for same. Below is the sample code.
int[] arr = new[] { 1, 3, 3, 3, 5 };
int elementsCount = 3;
int multiplier = 4;
var result = arr.Take(arr.Length - elementsCount).Concat(arr.Skip(arr.Length - elementsCount).Select(a => a * multiplier)).ToArray();

Return number from 1 to 10 based on the number size

Let's say I have some random numbers between 1 and 20 like this:
{3,7,14,8,17,6,12}
Now, I need to obtain a number between 1 and 10 for every number, based on the number size.
So for example the smaller number must return 1 and the greatest must return 10.
How can I achieve this?
EDIT
Here the solution that suits with some small changes, I found here : https://stackoverflow.com/a/7989299/16356535
List<int> list = new List<int> { 3, 7, 14, 8, 17, 6, 12 };
int scaleMin = 10; //the normalized minimum desired
int scaleMax = 1; //the normalized maximum desired
int valueMax = list.Max();
int valueMin = list.Min();
int valueRange = valueMax - valueMin;
int scaleRange = scaleMax - scaleMin;
IEnumerable<int> normalized =
list.Select(i =>
((scaleRange * (i - valueMin))
/ valueRange)
+ scaleMin);
Console.WriteLine(normalized);
You almost have it.
List<int> list = new List<int> { 3, 7, 14, 8, 17, 6, 12 };
int scaleMin = 1; //the normalized minimum desired
int scaleMax = 10; //the normalized maximum desired
int valueMax = list.Max();
int valueMin = list.Min();
int valueRange = valueMax - valueMin;
int scaleRange = scaleMax - scaleMin;
IEnumerable<int> normalized =
list.Select(i =>
((scaleRange * (i - valueMin)) / valueRange) + scaleMin);
Console.WriteLine(string.Join(',', normalized));

Counting huge permutations - counting elements and getting nth element

I am using this library for combinatorics:
https://github.com/eoincampbell/combinatorics/
What I need is to find n-th permutation and count elements of fairly large sets (up to about 30 elements), but I get stopped in my tracks before even starting, check out this code:
int[] testSet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
var permutation = new Permutations<int>(testSet);
var test = permutation.Count;
Everything works peachy just until 20 element large set, once I add 21st, permutations stop working right, eg.
here is what permutation.Count returns:
-4249290049419214848
which is far from being the right number.
I am assuming that it all boils down to how huge numbers I use - overflowing ints/longs that library uses. That is why, I am asking for an advice - is there a library? approach? or a fairly quick to implement way to have combinatorics work on bigintegers?
Thanks!
Get the number of possible permuations.
The number of permutations is defined by nPr or n over r
n!
P(n,r) = --------
(n - r)!
Where:
n = Number of objects
r = the size of the result set
In your example, you want to get all permutations of a given list. In this case n = r.
public static BigInteger CalcCount(BigInteger n, BigInteger r)
{
BigInteger result = n.Factorial() / (n - r).Factorial();
return result;
}
public static class BigIntExtensions
{
public static BigInteger Factorial(this BigInteger integer)
{
if(integer < 1) return new BigInteger(1);
BigInteger result = integer;
for (BigInteger i = 1; i < integer; i++)
{
result = result * i;
}
return result;
}
}
Get the nTh permutation
This one depends on how you create/enumerate the permutations. Usually to generate any permutation you do not need to know all previous permutations. In other words, creating a permutation could be a pure function, allowing you to directly create the nTh permutation, without creating all possible ones.
This, however, depends on the algorithms used. But will potentially be a lot faster to create the permutation only when needed (in contrast to creating all possible permutations up front -> performance and very memory heavy).
Here is a great discussion on how to create permutations without needing to calculate the previous ones: https://stackoverflow.com/a/24257996/1681616.
This is too long for a comment, but wanted to follow up on #Iqon's solution above. Below is an algorithm that retrieves the nth lexicographical permutation:
public static int[] nthPerm(BigInteger myIndex, int n, int r, BigInteger total)
{
int j = 0, n1 = n;
BigInteger temp, index1 = myIndex;
temp = total ;
List<int> indexList = new List<int>();
for (int k = 0; k < n; k++) {
indexList.Add(k);
}
int[] res = new int[r];
for (int k = 0; k < r; k++, n1--) {
temp /= n1;
j = (int) (index1 / temp);
res[k] = indexList[j];
index1 -= (temp * j);
indexList.RemoveAt(j);
}
return res;
}
Here is a test case and the result of calling nthPerm using the code provided by #Iqon.
public static void Main()
{
int[] testSet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
BigInteger numPerms, n, r;
n = testSet.Length;
r = testSet.Length;
numPerms = CalcCount(n, r);
Console.WriteLine(numPerms);
BigInteger testIndex = new BigInteger(1234567890987654321);
int[] myNthIndex = nthPerm(testIndex, (int) n, (int) r, numPerms);
int[] myNthPerm = new int[(int) r];
for (int i = 0; i < (int) r; i++) {
myNthPerm[i] = testSet[myNthIndex[i]];
}
Console.WriteLine(string.Join(",", myNthPerm));
}
// Returns 1,12,4,18,20,19,7,5,16,11,6,8,21,15,13,2,14,9,10,17,3
Here is a link to ideone with working code.
You can useJNumberTools
List<String> list = new ArrayList<>();
//add elements to list;
JNumberTools.permutationsOf(list)
.uniqueNth(1000_000_000) //next 1 billionth permutation
.forEach(System.out::println);
This API will generate the next nth permutation directly in lexicographic order. So you can even generate next billionth permutation of 100 items.
for generating next nth permutation of given size use:
maven dependency for JNumberTools is:
<dependency>
<groupId>io.github.deepeshpatel</groupId>
<artifactId>jnumbertools</artifactId>
<version>1.0.0</version>
</dependency>

How to get all indices of the highest number in an array? [duplicate]

This question already has answers here:
c# Array.FindAllIndexOf which FindAll IndexOf
(10 answers)
Closed 5 years ago.
For example, I have an array
arr[5] = {1, 5, 2, 3, 5}
and the highest number is obviously 5.
My question is how do I get both the indices of the highest number (which is 5).
The expected result is 1 and 4.
var arr = new int[] { 1, 5, 2, 3, 5 };
int max = arr.Max();
List<int> indexes = new List<int>();
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] == max)
indexes.Add(i);
}
int highindex = indexes.LastOrDefault();
Thats how you get all indexes of your highest number
var numbers = new int[] { 1, 5, 2, 3, 5 };
int max = numbers.Max();
var indexes = numbers.Select((c, i) => new
{
character = c, index = i
})
.Where(list => list.character == max)
.ToList();
You can use a LINQ query to find the numbers and index that equal the maximum number :
var arr=new[] {1, 5, 2, 3, 5};
var max = arr.Max();
var indexes= arr.Select( (n,idx)=>n==max?idx:-1)
.Where(idx=>idx!=-1)
.ToArray();
This will return {1,4}.
This query uses the Enumerable.Select overload that provides the index of the current element and returns that index if the number is equal to the maximum.
The original title was a bit confusing - how to find the two largest values. You can use a similar query to get the N largest values by selecting the value and index, ordering the results and taking first N items:
var indexes = arr.Select( (val,idx)=> (val:val,idx:idx) )
.OrderByDescending(p=>p.val)
.Take(2)
.Select(p=>p.idx);
This query uses C# 7 tuples to hold the intermediate results and give them a name

Random number generator choosing only between given few numbers in 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.

Categories