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();
Related
This question already has answers here:
2d Array in C# with random numbers
(2 answers)
Closed 4 years ago.
How do you print and save random values in array using Random.
So I need to have 10x10 table of rows containing random values from 0-9 but I seem to can't find a way how to get them printed!
int[,] mas = new int[9,9];
Random rand = new Random();
for (int i = 0; i <mas.Length; i++)
{
mas[i] = rand.Next(0,9);
Console.WriteLine(mas[i]);
for (int k = 0; k < mas.Length; k++)
{
mas[k] = rand.Next(0,9);
Console.WriteLine(mas[k]);
}
}
You have a small issue in your code: The array you create has two dimensions (int[9,9]). Therefore, whenever you want to read or write a cell, you need to provide two coordinates. You only set mas[i] or mas[k].
You should use max[i,k] instead in the inner loop. That way, every combination of coordinates will be tried out.
Unrelated: You mention you want a 10x10 grid of cells, but declare int[9,9]. While array indexing starts at 0, the size starts at 1. For example, if you create an array a = int[2], then it only contains entries at int[0] and int[1].
Similarly, the maximum parameter of the Random.Next(...) function is exclusive, so to get the value 9, you need to pass the maximum value 10.
If you want 2D array (i.e. you have two coordinates: lines - i and columns - j), nested loops is usual choice:
Random rand = new Random();
int[,] mas = new int[9, 9];
for (int i = 0; i < mas.GetLength(0); ++i)
for (int j = 0; j < mas.GetLength(1); ++j)
mas[i, j] = rand.Next(0, 10); // 10 will not be included, range [0..9]
Let's print the array:
for (int i = 0; i < mas.GetLength(0); ++i) {
for (int j = 0; j < mas.GetLength(1); ++j) {
Console.Write(mas[i, j]);
Console.Write(' '); // <- delimiter between columns
}
Console.WriteLine(); // <- delimiter between lines
}
Also, note that mas.length returns the overall length of the array, which will give you an IndexOutOfRangeException using your Code. Use mas.GetLength instead of mas.length
myArray.GetLength(0) -> Gets first dimension size
myArray.GetLength(1) -> Gets second dimension size
So your Code would look like this:
int[,] mas = new int[9, 9];
Random rand = new Random();
for (int i = 0; i < mas.GetLength(0); i++)
{
for (int k = 0; k < mas.GetLength(1); k++)
{
mas[i, k] = rand.Next(0, 9);
Console.Write(mas[i, k] + " ");
}
Console.WriteLine();
}
Probably like this
int[,] mas = new int[10, 10];
Random rand = new Random();
for (int i = 0; i < mas.GetLength(0); i++)
{
for (int k = 0; k < mas.GetLength(1); k++)
{
mas[i,k] = rand.Next(0, 9);
Console.Write(mas[i,k]);
}
Console.WriteLine("\n");
}
There are many things wrong with your code,
You dont know how indexing works - you want array of 10 times 10 but you create one with 9 times 9.
You need to specify both dimenstion when adding number to array.
Also,
Consolo.Writeline(string);
Will always write new line, something you dont want since you want to print 10 numbers, then new line with another then etc.
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]);
}
}
For some coursework I need to generate a normal magic square through brute force, this is part of the code. fyi; I'm not allowed to use any classes other than the commonly used. (I'm probably pushing my luck with Math.Pow)
I have the following method to generate a 2 dimensional of size NxN:
static int[,] GenerateSquare(int n)
{
int[,] sqarray = new int[n,n];
int[] rndarray = new int[n];
//puts completely random integers from 1 to n^2 in all elements of the square array (sqarray)
for (int i = 0; i < n; i++)
{
rndarray = FullRndArray(n);
for (int j = 0; j < n; j++)
{
sqarray[i, j] = rndarray[j];
}
}
return sqarray;
}
The FullRndArray() method is below:
static int[] FullRndArray(int n)
{
//creates an array of size n and fills with random intigers between 1 and n^2
int[] rndarray = new int[n];
Random rnd = new Random();
int ntothe2 = Convert.ToInt32(Math.Pow(n, 2));
for (int i = 0; i < n; i++)
rndarray[i] = rnd.Next(1, ntothe2 + 1);
return rndarray;
}
The problem is that when i run this code, the contents of each line is random, but each line of the square is the same as the last (ie 1-1, 1-2, 1-3 are the same as 2-1, 2-2, 2-3 and the same as 3-1, 3-2, 3-3 respectively). Yet when i go through debugger line by line, i end up with a perfectly random set of numbers in every space. Can anyone explain this error to me please?
This is the culprit:
Random rnd = new Random();
Random numbers are generated starting from a seed: same seed means same not-so-random sequence of numbers. Random uses the current time as seed, so when you run your code it runs so fast that you are creating two Randoms with the same seed, which then produce two identical rows. On the other hand, when you are debugging you let enough time pass and everything goes as expected.
The solution is to create an instance of Random, static or at the beginning of GenerateSquare, and use that one for the whole process.
I got exactly the same behavior that you describe.
This seems to work :
static int[,] GenerateSquare(int n)
{
int[,] sqarray = new int[n, n];
int[] rndarray = new int[n];
Random rnd = new Random();
//puts completely random integers from 1 to n^2 in all elements of the square array (sqarray)
for (int i = 0; i < n; i++)
{
rndarray = FullRndArray(n, rnd);
for (int j = 0; j < n; j++)
{
sqarray[i, j] = rndarray[j];
}
}
return sqarray;
}
static int[] FullRndArray(int n, Random rnd)
{
//creates an array of size n and fills with random intigers between 1 and n^2
int[] rndarray = new int[n];
int ntothe2 = Convert.ToInt32(Math.Pow(n, 2));
for (int i = 0; i < n; i++)
rndarray[i] = rnd.Next(1, ntothe2 + 1);
return rndarray;
}
I understand we must use the Random.Next() method on the same instance in order to be "really" random (as described in the BlackBear answer).
It probably worked during debug because you induced time laps between steps.
System.Random generator = new Random(DateTime.Now.Millisecond);
int[] lotteryNumber = new int[7];
Console.WriteLine("Your lottery numbers: ");
for (int i = 0; i<7; i++)
{
lotteryNumber[i] = generator.Next(1, 37);
Console.Write("{0} ",lotteryNumber[i]);
}
Console.ReadLine();
I need to make a program that prints 7 lottery numbers, but without duplicates. The code above prints 7 random numbers in the range of (1-37), but duplicates appaer. I need a way to prevent duplicate numbers from appearing.
The simplest approach IMO would be to generate a sequence of all the possible numbers (i.e. 1-37), shuffle the collection, then take the first seven results.
Searching on Stack Overflow for "Fisher-Yates shuffle C#" will find lots of examples.
In fact, you could modify the Fisher-Yates shuffle to yield results as you took them, so you could write a method such as:
var numbers = Enumerable.Range(1, 37).Shuffle().Take(7).ToList();
You could take a dictionary but make sure that you prevent duplicate key insertion. Keys of dictionary would serve as the unique numbers you need
You could toss them into a HashSet<int>. If you Add and it returns false, generate a new number.
If you're trying to pick numbers from a range without repetitions, you need to create an array of all the possible numbers and then "shuffle" a random selection out:
int[] allPossibleNumbers = Enumerable.Range(1, 37).ToArray();
int[] lotteryNumber = new int[7];
for (int i = 0; i < 7; i++)
{
int index = r.Next(i, 37);
lotteryNumber[i] = allPossibleNumbers[index];
allPossibleNumbers[index] = allPossibleNumbers[i];
// This step not necessary, but allows you to reuse allPossibleNumbers
// rather than generating a fresh one every time.
// allPossibleNumbers[i] = lotteryNumber[i];
}
Generate a list with your 37 items.
Then in your for, select one and delete the selected
Maybe this could help, if you get the existing number just try to find new one that isn't in the array:
static void Main(string[] args)
{
System.Random generator = new Random(DateTime.Now.Millisecond); int[] lotteryNumber = new int[7];
Console.WriteLine("Your lottery numbers: ");
for (int i = 0; i < 7; i++)
{
int lNumber = 0;
do
{
lNumber = generator.Next(1, 37);
}
while (lotteryNumber.Contains(lNumber));
lotteryNumber[i] = lNumber;
Console.Write("{0} ", lotteryNumber[i]);
}
Console.ReadLine();
}
HashSet<int> set = new HashSet<int>();
System.Random generator = new Random(DateTime.Now.Millisecond);
while(set.Count < 7){
set.Add(generator.Next(1,37);
}
That should work, since a HashSet will automatically ignore duplicates. Just loop until the set reaches the number of units you need. Only potential problem is it has the POTENTIAL (unlikely) to loop for a long time, but it should eventually respond.
so I took your original code...found some logic errors and added the fix you were looking for to prevent random number duplicates.
Enjoy!
System.Random generator = new Random(DateTime.Now.Millisecond);
int[] lotteryNumber = new int[7];
int lowerBounds = 1;
int upperBounds = 8;
int maxNumberLotteryValues = 7;
if ( ( upperBounds - lowerBounds ) < (maxNumberLotteryValues))
{
Console.Write("Warning: Adjust your upper and lower bounds...there are not enough values to create a unique set of Lottery numbers! ");
}
else
{
Console.WriteLine("Your lottery numbers: ");
for (int i = 0; i < maxNumberLotteryValues; i++)
{
int nextNumber = generator.Next(lowerBounds, upperBounds);
int count = lowerBounds; //Prevent infinite loop
while ((lotteryNumber.Contains(nextNumber))
&& (count <= upperBounds))
{
nextNumber = generator.Next(lowerBounds, upperBounds);
count++; //Prevent infinite loop
}
lotteryNumber[i] = nextNumber;
Console.Write("{0} ", lotteryNumber[i]);
}
}
Console.ReadLine();
const int nBalls = 37;
const int nPicks = 6;
int[] balls = new int[nPicks];
Random rnd = new Random(DateTime.Now.Millisecond);
int remainingBalls=nBalls;
int remainingPicks=nPicks;
for (int i = 1; i <= nBalls; i++)
{
if (rnd.Next(1, remainingBalls+1) <= remainingPicks)
balls[--remainingPicks]=i;
remainingBalls--;
}
Console.WriteLine(string.Join(",",balls));
Will outperform Shuffle and HashSet methods as nPicks/nBalls gets larger.
What i try to to, is generate an array of random int values, where the random values are taken between a min and a max.
So far i came up with this code:
int Min = 0;
int Max = 20;
int[] test2 = new int[5];
Random randNum = new Random();
foreach (int value in test2)
{
randNum.Next(Min, Max);
}
But its not fully working yet.
I think i might be missing just 1 line or something.
Can anyone help me out pushing me in the right direction ?
You are never assigning the values inside the test2 array. You have declared it but all the values will be 0. Here's how you could assign a random integer in the specified interval for each element of the array:
int Min = 0;
int Max = 20;
// this declares an integer array with 5 elements
// and initializes all of them to their default value
// which is zero
int[] test2 = new int[5];
Random randNum = new Random();
for (int i = 0; i < test2.Length; i++)
{
test2[i] = randNum.Next(Min, Max);
}
alternatively you could use LINQ:
int Min = 0;
int Max = 20;
Random randNum = new Random();
int[] test2 = Enumerable
.Repeat(0, 5)
.Select(i => randNum.Next(Min, Max))
.ToArray();
You need to assign the random.next result to the currrent index of your array within the loop