I tried to find 2 or more same elements from array x and then that duplicate to add into new array Y
So if i have in x array number like: 2,5,7,2,8 I want to add numbers 2 into y array
int[] x = new int[20];
Random rnd = new Random();
int[] y = new int[20];
int counter = 0;
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 15);
for (int j=i+1; j< x.Length; j++)
{
if (x[i] == x[j])
{
y[counter] = x[i];
Console.WriteLine("Repeated numbers are " + y[counter]);
counter++;
}
else
{
Console.WriteLine("There is no repeated numbers, numbers that are in x are " + x[i]);
}
break;
}
}
But having problems with that, when it come to the if loop it doesn't want to proceed with executing if loop (even if condition is true)
If someone could give me some suggestion, that would be helpful, thank you
There are various logical errors in your use of for. You should work more on your logic, because while libraries can be learnt by rote, logical errors are more something that is inside you.
int[] x = new int[20];
Random rnd = new Random(5);
// You don't know the length of y!
// So you can't use arrays
List<int> y = new List<int>();
// First initialize
for (int i = 0; i < x.Length; i++)
{
x[i] = rnd.Next(1, 15);
}
// Then print the generated numbers, otherwise you won't know what numbers are there
Console.WriteLine("Numbers that are in x are: ");
for (int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i]);
}
// A blank line
Console.WriteLine();
// Then scan
for (int i = 0; i < x.Length; i++)
{
for (int j = i + 1; j < x.Length; j++)
{
if (x[i] == x[j])
{
y.Add(x[i]);
Console.WriteLine("Repeated numbers is " + x[i]);
}
}
}
// Success/failure in finding repeated numbers can be decided only at the end of the scan
if (y.Count == 0)
{
Console.WriteLine("There is no repeated numbers");
}
I've put some comments in the code (plus the changes)
And for debugging purpose, I suggest you use a fixed Random sequence. new Random(5) (or any other number) will return the same sequence every time you launch your program.
Note that if there are multiple repetitions of a number, like { 4, 4, 4 } then the y array will be { 4, 4 }
at first:
why do u use the 'break;' ?
second:
in the first for - loop u assign a random number to x[i]
but then in the nested second loop
u already ask x[j] to check for same values (but that doesn't exist yet)
there are so many ways to check if values are equal,
but i like your approach:
so what i would suggest:
make a for - loop and assign all the random numbers to int[] x
then think again how u can evaluate
x[0] = x[1] or x[2] or x[3] ...
Try to use Linq to find the duplicate in the Array
int[] x = new int[] { 2, 5, 7, 2, 8 };
int[] y;
var result = x.GroupBy(item => item)
.Select(grp => new { key = grp.Key, Count = grp.Count() });
y = result.Where(res => res.Count > 1).Select(res => res.key).ToArray();
int[] array = new int[5] {1,2,3,4,4};
List<int> duplitcateList = array.Where(x => array.Where(y => y == x).Count() > 1).Distinct().ToList();
or you can replace last line of above code with below.
List<int> duplitcateList = array.
GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
above code is using Linq.
suppose your first array (in question x) is array.
Linq will first check for all elements in to list which occur more then once, and select them distinctly and store it to duplicateList
if you need an array at the, you can simply convert this list to array by doing this,
int[] yArray = duplitcateList.ToArray();
Make use of linq in your code , as below
//first populate array x
var duplicates= xArray.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToArray();
linq query above make use of groupby and find duplicate i.e. element occuring more then one time in you array and then you select those element and return result
I think this will will be the most understandable solution without complicated extension methods:
int[] x = new int[20];
// there can be at most 10 duplicates in array of length of 20 :)
// you could use List<int> to easily add elements
int[] y = new int[10];
int counter = 0;
Random rnd = new Random();
// fill the array
for (int i = 0; i < x.Length; i++)
x[i] = rnd.Next(1, 15);
// iterate through distinct elements,
// otherwise, we would add multiple times duplicates
foreach (int i in x.Distinct())
// if the count of an elements is greater than one, then we have duplicate
if(x.Count(n => n == i) > 1)
{
y[counter] = i;
counter++;
}
Related
I'm trying to solve whats probably an easy task, but I'm extremely new to this and don't quite have my head around working with arrays in a complex fashion. I'm trying to figure out if two inputs each corresponding numbers sum to the same number (for example with 123 and 321, 1+3 2+2 and 1+3 all equal 4).
The code I have so far has broken down each input into arrays, and I can sum those arrays into a third array, but I cant figure out how to check it with itself. Should I even bother with the 3rd array, and just figure out how to check the sums of the array in a loop?
public static void Main()
{
Console.Write("\n\n"); //begin user input
Console.Write("Check whether each cooresponding digit in two intigers sum to the same number or not:\n");
Console.Write("-------------------------------------------");
Console.Write("\n\n");
Console.Write("Input 1st number then hit enter: ");
string int1 = (Console.ReadLine());//user input 1
Console.Write("Input 2nd number: ");
string int2 = (Console.ReadLine());//user input 2
int[] numbers = new int[int1.ToString().Length]; //changing user inputs to strings for array
int[] numbers2 = new int[int2.ToString().Length];
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = int.Parse(int1.Substring(i, 1));//populating arrays
numbers2[i] = int.Parse(int2.Substring(i, 1));
}
int[] numbers3 = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++)
{
numbers3[i] = (numbers[i] + numbers2[i]);
}
}
}
You can create the collections on the fly...
bool isEqual = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()))
.Zip(Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString())),
(i, j) => new
{
First = i,
Second = j,
Total = i + j
})
.GroupBy(x => x.Total)
.Count() == 1;
The output will equal true if all elements add up to the same value...
Test cases:
Should succeed
12345
54321
Should fail
12345
55432
To understand the above query, lets break it up into sections.
// Here I'm just converting a string to an IEnumerable<int>, a collection of integers basically
IEnumerable<int> ints1 = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()));
IEnumerable<int> ints2 = Console.ReadLine()
.ToCharArray()
.Select(i => Convert.ToInt32(i.ToString()));
// Zip brings together two arrays and iterates through both at the same time.
// I used an anonymous object to store the original values as well as the calculated ones
var zippedArrays = ints1.Zip(ints2, (i, j) => new
{
First = i, // original value from ints1
Second = j, // original values from ints2
Total = i + j // calculated value ints1[x] + ints2[x]
});
// if the totals are [4,4,4], the method below will get rid of the duplicates.
// if the totals are [4,3,5], every element in that array would be returned
// if the totals are [4,4,5], only [4,5] would be returned.
var distinctByTotal = zippedArrays.GroupBy(x => x.Total);
// So what does this tell us? if the returned collection has a total count of 1 item,
// it means that every item in the collection must have had the same total sum
// So we can say that every element is equal if the response of our method == 1.
bool isEqual = distinctByTotal.Count() == 1;
You're 99% of the way there already. Just lose the third array and check each individual sum in your final loop.
bool isOK = numbers.Length = numbers2.Length && numbers.Length > 0;
if(isOK)
{
int expectedSum = numbers[0] + numbers2[0];
for (int i = 1; i < numbers.Length; i++)
{
var sum = (numbers[i] + numbers2[i]);
if(sum != expectedSum)
{
isOK = false;
break;
}
}
}
Console.WriteLine(isOk ? "Good job." : "You got some learning to do.");
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();
So here's my problematic code. When I try to pass an array with N arguments, let's say {2,1,2,2,5} in result I want to get two-dimensional secArray[element,frequency of the element]. The problem is I get more than that and in this particular case I get an array like this:
23
11
22
21
52
Console.WriteLine("Enter number of elements: ");
int n = int.Parse(Console.ReadLine());
int[] array = new int[n];
for (int i = 0; i < array.Length; i++)
{
Console.Write("Array[{0}]: ", i);
array[i] = int.Parse(Console.ReadLine());
}
//problematic code begins
int[,] secArray = new int[n,2];
for(int i = 0;i<n;i++)
{
for(int j = 0; j<n;j++)
{
if(array[i] == secArray[j,0])
{
secArray[j, 1] += 1;
}
else
{
secArray[i, 0] = array[i];
secArray[i, 1] = 1;
}
}
}
//problematic code ends
//printing - works good
Console.WriteLine("How many same elements?");
for (int row = 0; row < secArray.GetLength(0); row++)
{
for (int col = 0; col < secArray.GetLength(1); col++)
{
Console.Write(secArray[row, col]);
}
Console.WriteLine();
}
If anyone has a clue how to fix this I'll be really grateful. It frustrates me that I don't know where the actual problem lies.
The first problem concerns the very first statement.
int[,] secArray = new int[n,2];
You don't know how many unique elements you have in your array until you traverse it. You can't use n, because n is the total number of arguments, which can be greater than the number of unique elements.
Next, the nested for loops are very inefficient. Your algorithm traverses the array for every element in the array- so it will run in O(n^2) time.
Think: do you have to traverse the array more than once? Why not just use a hashtable (dictionary in C#) to keep track of counts as you traverse the array? A hashtable uses a very efficient lookup mechanism to tell you if you've already seen the element, and the value can be used to keep track of count.
Consider replacing your problematic code with the following, and understanding how it works.
Dictionary<int, int> elementCounts = new Dictionary<int, int>();
for(int i = 0; i < n; i++)
{
int element = array[i];
if (elementCounts.ContainsKey(element))
elementCounts[element]++;
else
elementCounts.Add(element, 1);
}
Console.WriteLine("How many same elements?");
foreach(KeyValuePair<int,int> count in elementCounts)
{
Console.WriteLine("Element: {0} Count: {1}", count.Key, count.Value);
}
Then, if you want to copy the results in the hashtable (Dictionary) to a two-dimensional array, you can do the following.
int numberOfUniqueElements = elementCounts.Count;
int[,] secArray = new int[numberOfUniqueElements, 2];
int j = 0;
foreach (KeyValuePair<int, int> count in elementCounts)
{
secArray[j, 0] = count.Key;
secArray[j, 1] = count.Value;
j++;
}
I would use Linq's GroupBy to do this
var array = new int[] { 2, 1, 2, 2, 5 };
var result = array.GroupBy(x => x).Select(x => new[] { x.Key, x.Count() }).ToArray();
Why don't you use a hash table. Let the number in the array be the hash entry key, and let the value of the hash entry be the count. Then just iterate through the array once. While iterating through the array check if hash entry exists if so add 1 to it, if not create it.
Something like
for(int i = 0; i<n;i++) {
if(hashTable.containsKey(array[i])) {
hashTable[array[i]]++];
} else {
hashTable.add(array[i],1);
}
}
Please note that this is quedocode and will require to lookup the methods and implement it correctly.
Lets say I have an array of integers. I found out that I can randomize the order of the elements simply by doing:
Random rnd = new Random();
array = array.OrderBy(x => rnd.Next()).ToArray();
But lets say I want to keep the first and the last elements in their original place. Can I do it using the same approach (using OrderBy()) or do I need to re-think my situation?
You can't do that in a single expression, but maybe a List<int> could help:
Random rnd = new Random();
var list = new List<int>();
list.Add(array[0]);
var partialArray = array.Skip(1).Take(array.Length - 2);
list.AddRange(partialArray.OrderBy(x => rnd.Next()));
list.Add(array[array.Length -1 ]);
You can do it:
int[] ints = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
ints = ints.Select((x, index) => new { Value = x, Index = index })
.OrderBy(tuple => (tuple.Index >= start && tuple.Index <= stop) ? random.Next(start, stop) : tuple.Index)
.Select(tuple => tuple.Value)
.ToArray();
Of course you can use the same approach, but you have to take care of the first and the last value. Just an example for your input array:
var list = array.Skip(1).Take(array.Length - 2).OrderBy(x => rnd.Next()).ToList();
list.Insert(0, array.First());
list.Add(array.Last());
array = list.ToArray();
Dmitry's example is basically the same, but gives you the option to keep more elements.
You can just use a standard shuffle algorithm modified to use a range, for example (using the Fisher-Yates algorithm):
public static void Shuffle<T>(IList<T> array, Random rng, int start, int end)
{
for (int n = end+1; n > start+1;)
{
int k = rng.Next(start, n);
--n;
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
Then call it like this:
Random rng = new Random();
for (int i = 0; i < 100; ++i)
{
var array = Enumerable.Range(1, 12).ToArray();
Shuffle(array, rng, 3, 9);
Console.WriteLine(string.Join(", ", array));
}
A slightly different approach which doesn't involve using List....
Random rnd = new Random();
//array = array.OrderBy(x => rnd.Next()).ToArray();
int lastIndexToChange = array.Length - 1;
for (int i = 1; i < lastIndexToChange; i++)
{
var tempStore = array[i];
int newPosition = rnd.Next(1, lastIndexToChange);
array[i] = array[newPosition];
array[newPosition] = tempStore;
}
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]);
}
}