Array Of Random Alternate Positive And Negative Number in C# - c#

I would like to generate array of 10 elements with random number between (-10,10).
And scenario is array can contain positive number between (0,10) for odd positions
and contain negative number between(-10,0) for even position
For Example: 1,-2,3,-4,7,-1,3,-3,2,-9
And im totally stucked in generating -ve number at even places because im new in programming.
Any Help Is Appreciated,Thanx In Advance

Ok, i got your point. Try This Code
Random rand = new Random();
int[] arr = new int[10];
for(int i = 0; i < 10; i++)
{
if(i % 2 == 0)
arr[i] = rand.Next(1,10);
else
arr[i] = (rand.Next(1,10)) * -1;
}
for(int i = 0; i < 10; i++)
{
Console.WriteLine(arr[i]);
}
Sample Output
1
-9
9
-8
1
-4
2
-6
4
-9

Try this:
using System;
namespace ConsoleApp
{
class Program
{
static void Main (string[] args)
{
var random = new Random ();
var array = new int[10];
for (int i = 0; i < array.Length; i++)
{
bool isOdd = (i % 2) == 1; // check remainder
int randomNumber = random.Next (0, 11); // 0..10
if (isOdd) randomNumber = -randomNumber; // change sign
array[i] = randomNumber;
}
}
}
}

This is easier than all the posted answers so far. Here is a basic infinite loop from which to base your specific needs.
public IEnumerable<int> RandomAlternatingSequence()
{
var random = new Random();
int sign = -1;
while (true)
{
sign *= -1;
yield return sign * random.Next();
}
}
I realize that the post is 2 years old but this may help others who come looking.

Related

Copy odd numbers from array into another array

Im new to programming and struggling with this task:
In array X [20] random numbers from 1 to 30 are entered, in array Y enter only odd numbers from array X.
Print down Y.
int[] x = new int[20];
Random rnd = new Random();
int counter = 0;
int[] y;
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 30);
if (x[i] % 2 !=0 )
{
y = new int[counter];
counter++;
y[counter] = x[i];
}
}
foreach (int number in y)
{
Console.WriteLine(number);
}
Im having problems to fill Y array with odd numbers without defining length of Y, I tried with adding counter but getting some errors all the time,
If someone can help me with some suggestions that would be helpful, thank you!
This looks like homework, so I guess using a more appropriate collection such as a List<int> is out of the question, just as using Linq.
At y = new int[counter]; you're reinitializing the array. This happens each iteration, so your final array only holds the latest added value, and all values before that will be set to their default: 0.
You could've seen this by debugging your code by setting breakpoints, stepping through the code and inspecting your variables. You could then also have provided a more proper problem description than "getting some errors".
If you know the input is never larger than 20, you can initialize the output array to the same size and keep a counter of how many values you copied (the latter of which you already do).
Then when printing, only print the elements up till that count with a for loop instead of foreach.
So something like this:
int[] x = new int[20];
int[] y = new int[x.Length];
Random rnd = new Random();
int counter = 0;
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 30);
if (x[i] % 2 != 0)
{
y[counter] = x[i];
counter++;
}
}
for (int i = 0; i < counter; i++)
{
Console.WriteLine(y[i]);
}
Your problem is that you create a new y array for each odd number you find. You need to create the array only once and then fill it.
Since you don't know how many odd numbers there will be, I suggest to use a List<int> instead:
int[] x = new int[20];
Random rnd = new Random();
List<int> y = new List<int>(); // create the list before the loop
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 30);
if (x[i] % 2 !=0 )
y.Add(x[i]); // add odd number to list
}
foreach (int number in y)
{
Console.WriteLine(number);
}
See, In your case you are not aware about the number of odd numbers in that random array. so Array will not be a right choice here if you are following the current implementation. If you want the output as array, then Why not a simple LINQ with Where like this example:
First you collect all random numbers to your array as you are doing currently:
int[] randomIntegers = new int[20];
Random rnd = new Random();
for (int i = 0; i < randomIntegers.Length; i++)
{
randomIntegers[i] = rnd.Next(1, 30);
}
Now you have the all random numbers in x now perform the following operation:
int[] oddValues = randomIntegers.Where(a=> a % 2 !=0).ToArray();

What's wrong with this simple method to sample from multinomial in C#?

I wanted to implement a simple method to sample from a multinomial distribution in C# (the first argument is an array of integers we want to sample and the second one is the probabilities of selecting each of those integers).
When I do this with numpy in python, the results make sense.
np.random.choice(np.array([1,2,3,4,5,6]),p=np.array([.624,.23,.08,.04, .02, .006]),size=len(b))
I get a lot of 1's (probability 62%), a bunch of 2's, some 3's etc.
However, when I try the implementation below in C# (pretty straightforward inverse transform sampling for multinomial, only relies on a uniform random variable), I get really weird results. For all 1000 samples, I'll often find all 1's. Sometimes, I'll find all 3's (!!??). The results never look like what you would expect (and what you get from the python function - try running it yourself a few times). This is really scary since we rely on these primitives. Does anyone have insight into what might be wrong with the C# version?
static void Main(string[] args)
{
int[] iis = new int[7];
int[] itms = new int[] { 1, 2, 3, 4, 5, 6 };
double[] probs = new double[] { .624, .23, .08, .04, .02, .006 };
for (int i = 0; i < 1000; i++)
{
iis[MultinomialSample(itms, probs)] += 1;
}
foreach (var ii in iis)
{
Console.Write(ii + ",");
}
Console.Read();
}
private static int MultinomialSample(int[] s, double[] ps)
{
double[] cumProbs = new double[ps.Length];
cumProbs[0] = ps[0];
for (int i = 1; i < ps.Length; i++)
{
cumProbs[i] = cumProbs[i - 1] + ps[i];
}
Random random = new Random();
double u = random.NextDouble();
for (int i = 0; i < cumProbs.Length - 1; i++)
{
if (u < cumProbs[i])
{
return s[i];
}
}
return s[s.Length - 1];
}
You're initializing Random each time you call MultinomialSample. If these calls are very close together, Random will be initialized with the same seed (based on the system clock). Try either making Random a private class field: private static Random random = new Random(); or pass it into the method as an argument from Main, where it would be initialized only once:
private static Random random = new Random();
private static int MultinomialSample(IReadOnlyList<int> sample,
IReadOnlyList<double> probabilities)
{
var cumProbs = new double[probabilities.Count];
cumProbs[0] = probabilities[0];
for (var i = 1; i < probabilities.Count; i++)
{
cumProbs[i] = cumProbs[i - 1] + probabilities[i];
}
for (var i = 0; i < cumProbs.Length - 1; i++)
{
if (random.NextDouble() < cumProbs[i])
{
return sample[i];
}
}
return sample[sample.Count - 1];
}
private static void Main()
{
var iis = new int[7];
var items = new[] {1, 2, 3, 4, 5, 6};
var probabilities = new[] {.624, .23, .08, .04, .02, .006};
for (int i = 0; i < 1000; i++)
{
iis[MultinomialSample(items, probabilities)] ++;
}
Console.WriteLine(string.Join(", ", iis));
Console.WriteLine("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
I used Rufus' code in a simulation I was working on and noticed there is still a problem, even after seeding the random number generator just once (which is the correct thing to do). You will notice that as we are iterating, the call to random.NextDouble() generates a new random number each time. This is wrong.
for (var i = 0; i < cumProbs.Length - 1; i++)
{
if (random.NextDouble() < cumProbs[i])
{
return sample[i];
}
}
The random number should be generated outside of the loop, as follows:
var r = random.NextDouble();
for (var i = 0; i < cumProbs.Length - 1; i++)
{
if (r < cumProbs[i])
{
return sample[i];
}
}
You can compare it to the Excel algorithm given on Wikipedia: https://en.wikipedia.org/wiki/Multinomial_distribution. When I made the above change to Rufus' code, I got the desired frequency distribution as specified by the probabilities array.

Adding specific numbers from one sequence to another

I feel like this task should not be done this way...
My sequenceY length is not equal to number of steam numbers because you can't assign int[] length with int that have 0 as a starting value.
Therefore my sequenceY have a lot of 0 inside and I can't print the whole sequence. I even tried adding this after for loop:
sequenceY = new int[steamnumbercounter];
But it didn't work ... Why ?
My other question is how do programmers deal with sequences that have unknown length?
I managed to print only steam numbers but the task says print sequenceY not only part of it.
// 4. sequenceX[20] is made of random numbers from 1 to 30 ,
// sequenceY is made of steam numbers from sequenceX. Print sequneceY.
int[] nizx = new int[20];
int[] nizy = new int[20];
int n = 0;
int steamnumbercounter = 0;
Random rnd = new Random();
for (int i = 0; i < nizx.Length; i++)
{
nizx[i] = rnd.Next(1, 30);
if (nizx[i]%2==0)
{
nizy[n] = nizx[i];
n++;
steamnumbercounter++;
}
Console.Write("{0} , ", nizx[i]);
}
for (int i = 0; i < steamnumbercounter; i++)
{
Console.WriteLine("{0} , ",nizy[i]);
}
Partial code review along with an answer.
But it didn't work ... Why ?
That code didn't work because you're reassigning sequenceY to a completely new value.
My other question is how do programmers deal with sequences that have unknown length?
So, with that known we can do a few things here: create an array and use Array.Resize, use a List<T>, fill the initial array then swap it for one of the right size which is filled.
I'm going to assume a "steam" number is an even one.
Your naming is not good: nizx and nizy don't convey the meaning or line up with the problem.
I'm going to demonstrate the last option (since you stated that you don't know how to use many of the moderately complex parts of .NET in this class yet, which is fine): fill the initial array and swap it for a new one. This will run in O(n^2) time (sorta).
So, let's start with our source array.
int[] sequenceX = new int[20];
Next we'll define our destination array to be the same size as our source array. (This is the maximum number of values that could be stored in it, we'll shrink it later.)
int[] sequenceY = new int[sequenceX.Length];
Then we need a variable to hold how many numbers we found that meet our criteria:
int steamNumbers = 0;
And lastly, our Random.
Random random = new Random();
Then, we look through all our sequenceX as you did, but we'll update the logic a bit.
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(1, 30);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
So our code looks almost the same as yours, but we have one more thing to do: since you only want sequenceY to contain steamNumbers we have to shrink it or something.
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
Now sequenceY only has your steam numbers in it.
Final code:
int[] sequenceX = new int[20];
int[] sequenceY = new int[sequenceX.Length];
int steamNumbers = 0;
Random random = new Random();
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(1, 30);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
// Print your `sequenceY` here.
You could extract this to a method pretty easily as well:
public int[] GetSteamNumbers(int sequenceCount, int randomMinimum, int randomMaximum)
{
int[] sequenceX = new int[sequenceCount];
int[] sequenceY = new int[sequenceX.Length];
int steamNumbers = 0;
Random random = new Random();
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(randomMinimum, randomMaximum);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
return sequenceY;
}
And then call it with:
int[] steamNumbers = GetSteamNumbers(20, 1, 30);
Of course, for the more advanced users (this doesn't help you, but it may help others) we can do something as follows using LINQ:
var random = new Random();
var sequenceY = Enumerable.Range(1, 20)
.Select(x => random.Next(1, 30))
.Where(x => x % 2 == 0)
.ToArray();
Which should have the same effect. (Just demonstrating that there are still things in C# to look forward to in the future.)
Disclaimer: I wrote this entire answer outside of the IDE and without actually compiling it, I make no guarantees to the accuracy of the code but the procedure itself should be fairly straight forward.
The thing with arrays in C# is that they are of fixed size.
You'll have to iterate through and re-create it or use a IEnumerable that has dynamic sizes, such as Lists.
Solution here would be to use a List that contains your integers and then you would use nizx.Add(rnd.Next(1, 30));
Elaborating on my comment above: You can create a 'fake' list by concatenating the values you need in a string, separated by commas. The string.Split(',') will give you the resulting array that you need.
Given a string of form "a,b,c,d" string.Split(',') will create the array ["a","b,"c","d"]. The code:
{
int[] nizx = new int[20];
string numberString = string.Empty;
int n = 0;
Random rnd = new Random();
for (int i = 0; i < nizx.Length; i++)
{
nizx[i] = rnd.Next(1, 30);
if (nizx[i] % 2 == 0)
{
numberString += nizx[i] + ",";
n++;
}
}
var numberArray = numberString.Split(',');
for (int i = 0; i < n; i++)
{
Console.WriteLine("{0} , ", numberArray[i]);
}
}

Almost Ordered not sorting the exact amount of values i give it

this is a really easy question but i cant figure out a way around it. Apparently the almost ordered has a bug that it might randomize a little bit more than you ask it. the code is rather simple:
public void Section1Task1AlmostOrdered(int arraySize, int percentage)
{
int[] testArray = new int[arraySize];
Console.WriteLine("Ordered List: ");
for (int i = 1; i <= testArray.Length; i++)
{
testArray[i-1] = i;
Console.Write(i + "\t");
}
Console.WriteLine("Almost Ordered List: ");
testArray = shuffler.AlmostOrdered(arraySize, percentage);
for (int i = 0; i < testArray.Length; i++)
{
Console.Write(testArray[i] + "\t");
}
}
The shuffler is this part of the code:
public int[] AlmostOrdered(int n, double p)
{
if (p > 100)
{
throw new InvalidOperationException("Cannot shuffle more than 100% of the numbers");
}
int shuffled = 0;
//Create and Populate an array
int[] array = new int[n];
for(int i = 1; i <= n; i++)
{
array[i-1] = i;
}
//Calculate numbers to shuffle
int numsOutOfPlace = (int) Math.Ceiling(n * (p / 100));
int firstRandomIndex = 0;
int secondRandomIndex = 0;
do
{
firstRandomIndex = this.random.Next(n-1);
// to make sure that the two numbers are not the same
do
{
secondRandomIndex = this.random.Next(n - 1);
} while (firstRandomIndex == secondRandomIndex);
int temp = array[firstRandomIndex];
array[firstRandomIndex] = array[secondRandomIndex];
array[secondRandomIndex] = temp;
shuffled++;
}
while (shuffled < numsOutOfPlace);
return array;
}
When i enter values 10 for array size and 40 for percentage to be shuffled, it is shuffling 5 numbers instead of 4. Is there a way to perfect this method to make it more accurate?
Likely the problem is with the calculation:
int numsOutOfPlace = (int)Math.Ceiling(n * (p / 100));
So if p=40 and n=10, then in theory you should get 4. But you're dealing with floating point numbers. So if (p/100) returns 0.400000000001, then the result will be 4.000000001, and Math.Ceiling will round that up to 5.
You might want to replace Math.Ceiling with Math.Round and see how that works out.

Random number 0's or 1's

I am looking to generate 0's or 1's only for each array like:
int[] x = new int [10];
I would like to generate 10 numbers either 0's or 1's and should not all 0's
It's only like this:
Random binaryrand = new Random(2);
Thank you.
You can do it with Random.Next(Int32, Int32) method like;
int[] x = new int[10];
Random r = new Random();
while (x.Any(item => item == 1) == false)
{
for (int i = 0; i < x.Length; i++)
{
x[i] = r.Next(0, 2);
}
}
for (int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i]);
}
Example output;
0
0
0
1
1
1
0
1
1
0
Here a DEMO.
Remember, on Random.Next(Int32, Int32) method, lower bound is inclusive but upper bound is exclusive.
Your call
Random binaryrand = new Random(2);
creates a Random generator with seed=2, it will produce the same sequence of numbers each time you run this code. The 2 has nothing to do with the range of the generated numbers.
Use
Random binaryrand = new Random(); // auto seed
...
int x = binaryrand.Next(2);
This also ensures that not all are 0
Random binaryrand = new Random();
List<int> l = new List<int>();
while (l.Find(x => x == 1) != 1)
{
for (int i = 0; i < 10; i++)
{
l.Add(binaryrand.Next(0, 2));
}
}

Categories

Resources