What I need is:
e.g:
Sum should be equal to:
120 (user input)
Number of numbers/items:
80 (user input)
Range of numbers to be used in set(from):
0 (user input)
Range of numbers to be used in set(to):
4 (user input)
Output:
1,1,3,2,1,1,0,0,1,1,2,1,0,2,3,3,1,2,0,0,0,1,3,2,3,1,0,0,2,3,2,3,2,2,1,1,0,0,2,0,1,0,1,1,3,3,1,3,1,0,0,3,2,1,0,0,2,1,2,3,0,3,1,1,3,3,2,2,1,1,3,1,3,3,3,3,3,1,2,0
These are all numbers that are between 0 and 4, their sum is 120 and are 80 in total.
What i've done is:
static void Main(string[] args)
{
bool loopOn = true;
Program p = new Program();
Console.WriteLine("____________________________________________________________________________");
Console.WriteLine("");
Console.WriteLine("Sum should be equal to:");
int sum = int.Parse(Console.ReadLine());
Console.WriteLine("Number of items:");
int items = int.Parse(Console.ReadLine());
Console.WriteLine("Range(from):");
int from = int.Parse(Console.ReadLine());
Console.WriteLine("Range(to):");
int to = int.Parse(Console.ReadLine());
while (loopOn == true)
{
List<int> number_list = p.createNumberSet(items, from, to);
if (number_list.Sum() == sum)
{
loopOn = false;
Console.WriteLine("____________________________________________________________________________");
Console.WriteLine("Start");
number_list.ForEach(Console.WriteLine);
Console.WriteLine("Stop");
Console.WriteLine("____________________________________________________________________________");
}
}
Console.WriteLine("Press any key to exit....");
Console.ReadLine();
}
public List<int> createNumberSet(int itemNumber, int range_from, int range_to)
{
List<int> number_set = new List<int>();
Random r = new Random();
for (int i = 0; itemNumber > i; i++)
{
number_set.Add(r.Next(range_from, range_to));
}
return number_set;
}
But this seems extremely in-efficent and doesn't seem to work with a lot of other examples. Does anyone have a better way of doing this?
Well, I am a bit lazy right now, so this is just an idea
Keep the first part:
bool loopOn = true;
Program p = new Program();
Console.WriteLine("____________________________________________________________________________");
Console.WriteLine("");
Console.WriteLine("Sum should be equal to:");
int sum = int.Parse(Console.ReadLine());
Console.WriteLine("Number of items:");
int items = int.Parse(Console.ReadLine());
Console.WriteLine("Range(from):");
int from = int.Parse(Console.ReadLine());
Console.WriteLine("Range(to):");
int to = int.Parse(Console.ReadLine());
Now, first of all, check is a solution exists:
if (from * items > sum) {
// There is no solution, handle accordingly
}
Let's focus on the interesting part now:
First create the list of necessary items
int[] number_set = new int[items];
for(int i = 0; i < items; i++) {
number_set[i] = from;
}
Find the difference between the wanted sum and the current sum of the list
int left_to_add = sum - from * items;
int idx = 0;
Random r = new Random();
while(left_to_add > 0) {
int toAdd = 0;
if (left_to_add < range_to - range_from) {
toAdd = r.Next(1, left_to_add);
} else {
toAdd = r.Next(1, range_to - range_from);
}
left_to_add -= toAdd;
number_set[idx] += toAdd;
idx++;
}
What's left to do is, convert the array to a list and shuffle it.
(I forgot that you actually can access list items by index, so there is no need to use an array as I did here)
At the algorithm level, this is what I would try:
Determine the number of each element, n[0], n[1], n[2], n[3] in your example (i.e. number of 0, number of 1 ...) and then generate a simple sequence by concatenating n[0] "0", n[1] "1", n[2] "2" and n[3] "3". Finally, a random sequence is obtained by performing a random permutation on this simple sequence.
The problem is therefore to determine the n[i].
The first step is to determine the average values of these n[i]. It your example, it is simple, as we can take average n_av[i]=20 for all index i.
In a more general case, we have to insure that
sum_i n_av[i]*i = sum_target (120 here) (1)
knowing that
sum_i (n[i]) = n = 80 here. (2)
In the general case, there is no necessary one unique good solution. I will try to propose an example of solution here if you provide an example of a difficult scenario.
The second step consists in selecting some random n[i] values around these average values. One possibility is to generate rounded Gaussian variables: we already know the averages, we just need to determine the variances. One possibility is to consider the variance that we will get if we were generating directly the random values, i.e. by considering the variance of the corresponding binomial variable :
var = n p(1-p). Here p[i] = n_av[i]/n
The last step consists in adjusting the values of the n[i] such that the sum of the n[i] is equal to the target. This is simply obtained by slightly increasing or decreasing some n[i] values.
I have a situation in which I must generate a random number, this number must be either zero or one
So, the code is something like this:
randomNumber = new Random().Next(0,1)
However, the business requirements state that there is just 10% probability that the generated number is zero and 90% probability that the generated number is 1
However can I include that probability in generating the random number please?
What I thought of is:
Generate array of integer that includes 10 zeros and 90 ones.
Generate a random index between 1 and 100
Take the value that corresponds to that index
But I don't know if this way is the correct way, plus, I think that C# should have something ready for it
You can implement it like that:
// Do not re-create Random! Create it once only
// The simplest implementation - not thread-save
private static Random s_Generator = new Random();
...
// you can easiliy update the margin if you want, say, 91.234%
const double margin = 90.0 / 100.0;
int result = s_Generator.NextDouble() <= margin ? 1 : 0;
to get true with a probability of 10%:
bool result = new Random().Next(1, 11) % 10 == 0;
to get true with a probability of 40%:
bool result = new Random().Next(1, 11) > 6;
First of all, you should save the reference to the random instance in order to get a proper random sequence of numbers:
Random randGen = new Random();
The second thing to know, is that the max of the random is exclusive, so to properly solve the issue you should do:
int eitherOneOrZero = randGen.Next(1, 11) % 10;
To generalize it to any variation of chances, you can do:
Random randGen = new Random();
var trueChance = 60;
int x = randGen.Next(0, 100) < trueChance ? 1 : 0;
Testing:
Random randGen = new Random();
var trueChance = 60;
var totalCount = 1000;
var trueCount = 0;
var falseCount = 0;
for (int i = 0; i < totalCount; i++)
{
int x = randGen.Next(0, 100) < trueChance ? 1 : 0;
if (x == 1)
{
trueCount++;
}
else
{
falseCount++;
}
}
Output:
True: 60.30 %
False: 39.70 %
Hi guy i try to generate 50 number with 5 digit depend on user total summary. For example, User give 500000 and then i need to random number with 5 digit by 50 number equal 500000
i try this but it isn't 5 digit number
int balane = 500000;
int nums = 50;
int max = balane / nums;
Random rand = new Random();
int newNum = 0;
int[] ar = new int[nums];
for (int i = 0; i < nums - 1; i++)
{
newNum = rand.Next(0, max);
ar[i] = newNum;
balane -= newNum;
max = balane / (nums - i - 1);
ar[nums - 1] = balane;
}
int check = 0;
foreach (int x in ar)
{
check += x;
}
i tried already but value inside my array have negative value i want to get only
positive value
Please help me, how to solve this and thank for advance.
I once asked a similar question on codereview.stackexchange.com. I have modified my answer to produce a five digit sequence for you.
Furthermore, this code is fast enough to be used to create tens of thousands of codes in a single request. If you look at the initial question and answer (linked to below) you will find that it checks to see whether the code has been used or not prior to inserting it. Thus, the codes are unique.
void Main()
{
Console.WriteLine(GenerateCode(CodeLength));
}
private const int CodeLength = 10;
// since Random does not make any guarantees of thread-safety, use different Random instances per thread
private static readonly ThreadLocal<Random> _random = new ThreadLocal<Random>(() => new Random());
// Define other methods and classes here
private static string GenerateCode(int numberOfCharsToGenerate)
{
char[] chars = "0123456789".ToCharArray();
var sb = new StringBuilder();
for (int i = 0; i < numberOfCharsToGenerate; i++)
{
int num = _random.Value.Next(0, chars.Length);
sb.Append(chars[num]);
}
return sb.ToString();
}
Original question and answer: https://codereview.stackexchange.com/questions/142049/creating-a-random-code-and-saving-if-it-does-not-exist/142056#142056
Perhaps try this:
var rnd = new Random();
var numbers = Enumerable.Range(0, 50).Select(x => rnd.Next(500_000)).OrderBy(x => x).ToArray();
numbers = numbers.Skip(1).Zip(numbers, (x1, x0) => x1 - x0).ToArray();
numbers = numbers.Append(500_000 - numbers.Sum()).ToArray();
Console.WriteLine(numbers.Count());
Console.WriteLine(numbers.Sum());
This outputs:
50
500000
This works by generating 50 random numbers between 0 and 499,999 inclusively. It then sorts them ascendingly and then gets the difference between each successive pair. This by definition produces a set of 49 values that almost adds up to 500,000. It's then just a matter of adding the one missing number by doing 500_000 - numbers.Sum().
I am assigning employees a random integer percentage of 100. This percentage is based on how many employees we have and must total to 100.
If we have 4 employees, I would perhaps want to generate a split such as 80-10-5-5.. if we had 2 employees. The more random the percentages are, the better.
I'm not sure how to accomplish this elegantly without a ton of different if statements but even then the randomness would be limited I feel.
Just assign each employee a random number in a certain range (range ist up to you). Than calculate the sum of the random numbers. Last step: devide each random number by the sum which gives you the percentage.
Example: random number 3, 9, 7
Sum = 19
Percentages: 3/19=16%, 9/19=47%, 7/19=37%
(Values are rounded.)
I have written a sample code for this:
int no_of_employees = 4;
int total_percentage = 100;
List<int> tempNumberList = new List<int>();
List<int> finalNumberList = new List<int>();
Random random = new Random();
for (int i = 0; i < no_of_employees; i++)
{
tempNumberList.Add(random.Next(total_percentage));
}
int sum = tempNumberList.Sum();
foreach(int number in tempNumberList)
{
finalNumberList.Add((number * total_percentage) / sum);
}
if(finalNumberList.Sum() != total_percentage)
{
finalNumberList[0] = finalNumberList[0] + (total_percentage - finalNumberList.Sum());
}
Please feel free to improve the logic if necessary at all.
This should work:
var random = new Random();
var percentages = new List<int>();
int remainder = 100;
for (int i = 0; i < employeesCount; i++)
{
int percentage = random.Next(remainder);
percentages.Add(percentage);
remainder -= percentage;
}
percentages[percentages.Count - 1] += remainder;
Note that
the last line solves the rounding issue in case the percentages' sum is not 100
a solution using only LINQ is also doable although less readable and probably with an impact on performance (using Aggregate for instance introduces the creation of an anonymous type)
I'm not 100% sure this solution guarantees equal probability (especially the last employee's case)
So my professor wants us to make a program that takes in a number than spit out the square root for it. The catch is we aren't allowed to use Math.Sqrt or else there will be a 50% score penalty. So instead I'm using the following method from here...
Guess a number for the sqrt.
Divide the number by the guess.
Average the original guess and the new guess.
Make this average the current guess, and revert to step 2.
The thinking is once you do it 3-4 times (or more?) it should get closer, and closer to the actual sqrt.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void calculateSqr_Click(object sender, RoutedEventArgs e)
{
decimal wantedSqrt = Decimal.Parse(input.Text); //Takes the number from the textbox, and converts it to an int.
Random rnd = new Random(); //We're going to pick a random number.
decimal guess = rnd.Next(1, 100); //Pick a number between 1-100.
for (int i = 0; i <10; i++)
{
decimal divHolder = wantedSqrt / guess; //Divide.
decimal avgVal = (guess + divHolder) / 2; //Average.
avgVal = guess; //Make the average our new guess.
Console.WriteLine(guess); //Seems like all it does is write the number 10 times.
}
string wantedSqrtString = wantedSqrt.ToString();
MessageBox.Show(wantedSqrtString);
}
}
As you can tell the issue is in my for loop. I thought that it would work so that it takes the wantedSqrt, dive it, average it with the guess, and then the new average would become the guess, and it would loop. Instead it just repeats the number 10 times in the output. What is going wrong here?
I fixed your code here:
decimal wantedSqrt = Decimal.Parse(input.text); //Takes the number from the textbox, and converts it to an int.
Random rnd = new Random(); //We're going to pick a random number.
decimal guess = rnd.Next(1, 100); //Pick a number between 1-100.
for (int i = 0; i <10; i++)
{
decimal divHolder = wantedSqrt / guess; //Divide.
guess = (guess + divHolder) / 2; //Average.
//Make the average our new guess.
Console.WriteLine(guess); //Seems like all it does is write the number 10 times.
}
string wantedSqrtString = wantedSqrt.ToString();
Console.WriteLine(wantedSqrtString);