Comparing c# array to itself - c#

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.");

Related

Need to calculate the median and mode, C#

i need to organize the numbers and get the median and mode from any quantity of numbers, so i tried different ways to implement this but i just can't get with the solution.
public static void Main()
{
int i, n;
int[] a = new int[100];
Console.Write("\n\nRead n number of values in an array and display it in reverse order:\n");
Console.Write("------------------------------------------------------------------------\n");
Console.Write("Input the number of elements to store in the array :");
n = Convert.ToInt32(Console.ReadLine());
//quantity of numbers to insert
Console.Write("Input {0} number of elements in the array :\n", n);
for (i = 0; i < n; i++)
{
Console.Write("element - {0} : ", i);
a[i] = Convert.ToInt32(Console.ReadLine());
}
//individial numbers to insert
Console.Write("\nThe values store into the array are : \n");
for (i = 0; i < n; i++)
{
Console.Write("{0} ", a[i]);
}
}
i tried to use this, but i don't know how to use it
public static class Extensions
{
public static decimal GetMedian(this int[] array)
{
int[] tempArray = array;
int count = tempArray.Length;
Array.Sort(tempArray);
decimal medianValue = 0;
if (count % 2 == 0)
{
// count is even, need to get the middle two elements, add them together, then divide by 2
int middleElement1 = tempArray[(count / 2) - 1];
int middleElement2 = tempArray[(count / 2)];
medianValue = (middleElement1 + middleElement2) / 2;
}
else
{
// count is odd, simply get the middle element.
medianValue = tempArray[(count / 2)];
}
return medianValue;
}
}
Median is a middle item (or average of two middle items) in the sorted collection:
using System.Linq;
...
int[] a = ...
...
double median = a
.OrderBy(item => item) // from sorted sequence
.Skip((a.Length - 1) / 2) // we skip leading half items
.Take(2 - a.Length % 2) // take one or two middle items
.Average(); // get average of them
Mode is the local maximum of the distribution, the most frequent element in it:
int mode = a
.GroupBy(item => item)
.OrderByDescending(group => group.Count())
.First().Key;

Duplicated elements from x array add into y array

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++;
}

C#, how to save frequency of elements from one array in another, two-dimensional array?

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.

find number with no pair in array

I am having trouble with a small bit of code, which in a random size array, with random number pairs, except one which has no pair.
I need to find that number which has no pair.
arLength is the length of the array.
but i am having trouble actually matching the pairs, and finding the one which has no pair..
for (int i = 0; i <= arLength; i++)
{ // go through the array one by one..
var number = nArray[i];
// now search through the array for a match.
for (int e = 0; e <= arLength; e++)
{
if (e != i)
{
}
}
}
I have also tried this :
var findValue = nArray.Distinct();
I have searched around, but so far, i haven't been able to find a method for this.
This code is what generates the array, but this question isn't about this part of the code, only for clarity.
Random num = new Random();
int check = CheckIfOdd(num.Next(1, 1000000));
int counter = 1;
while (check <= 0)
{
if (check % 2 == 0)
{
check = CheckIfOdd(num.Next(1, 1000000)); ;
}
counter++;
}
int[] nArray = new int[check];
int arLength = 0;
//generate arrays with pairs of numbers, and one number which does not pair.
for (int i = 0; i < check; i++)
{
arLength = nArray.Length;
if (arLength == i + 1)
{
nArray[i] = i + 1;
}
else
{
nArray[i] = i;
nArray[i + 1] = i;
}
i++;
}
You can do it using the bitwise operator ^, and the complexity is O(n).
Theory
operator ^ aka xor has the following table:
So suppose you have only one number without pair, all the pairs will get simplified because they are the same.
var element = nArray[0];
for(int i = 1; i < arLength; i++)
{
element = element ^ nArray[i];
}
at the end, the variable element will be that number without pair.
Distict will give you back the array with distinct values. it will not find the value you need.
You can GroupBy and choose the values with Count modulo 2 equals 1.
var noPairs = nArray.GroupBy(i => i)
.Where(g => g.Count() % 2 == 1)
.Select(g=> g.Key);
You can use a dictionary to store the number of occurrences of each value in the array. To find the value without pairs, look for a (single) number of occurrences smaller than 2.
using System.Linq;
int[] data = new[] {1, 2, 3, 4, 5, 3, 2, 4, 1};
// key is the number, value is its count
var numberCounts = new Dictionary<int, int>();
foreach (var number in data) {
if (numberCounts.ContainsKey(number)) {
numberCounts[number]++;
}
else {
numberCounts.Add(number, 1);
}
}
var noPair = numberCounts.Single(kvp => kvp.Value < 2);
Console.WriteLine(noPair.Key);
Time complexity is O(n) because you traverse the array only a single time and then traverse the dictionary a single time. The same dictionary can also be used to find triplets etc.
.NET Fiddle
An easy and fast way to do this is with a Frequency Table. Keep a dictionary with as key your number and as value the number of times you found it. This way you only have to run through your array once.
Your example should work too with some changes. It will be a lot slower if you have a big array.
for (int i = 0; i <= arLength; i++)
{
bool hasMatch = false;
for (int e = 0; e <= arLength; e++)
{
if (nArray[e] == nArray[i])//Compare the element, not the index.
{
hasMatch = true;
}
}
//if hasMatch == false, you found your item.
}
All you have to do is to Xor all the numbers:
int result = nArray.Aggregate((s, a) => s ^ a);
all items which has pair will cancel out: a ^ a == 0 and you'll have the distinc item: 0 ^ 0 ^ ...^ 0 ^ distinct ^ 0 ^ ... ^0 == distinct
Because you mentioned you like short and simple in a comment, how about getting rid of most of your other code as well?
var total = new Random().Next(500000) * 2 + 1;
var myArray = new int[total];
for (var i = 1; i < total; i+=2)
{
myArray[i] = i;
myArray[i -1] = i;
}
myArray[total - 1] = total;
Then indeed use Linq to get what you are looking for. Here is a slight variation, returning the key of the item in your array:
var key = myArray.GroupBy(t => t).FirstOrDefault(g=>g.Count()==1)?.Key;

Array.IndexOf vs. value of given index issue

I'm trying to loop through a given array and find how many duplicate values I have inside it. It works by going through a nested loop checking all elements of the array against each other and making sure it doesn't rise the counter if it's on the same index. But the problem is, it never counts up!
Now it's either I don't understand the concept of valueOf vs indexOf or I'm just completely lost.
int[] myArr = new int[] { 10, 5, 5 };
int counter = 0;
for (int i = 0; i < myArr.Length; i++)
{
for (int j = 0; j < myArr.Length; j++)
{
if (Array.IndexOf(myArr, myArr[i]) == Array.IndexOf(myArr, myArr[j]))
{
continue;
}
else if (myArr[i] == myArr[j])
{
counter++;
}
}
}
Console.WriteLine("There are {0} repeating values in the array.", counter);
// Output: There are 0 repeating values in the array.
Array.IndexOf searches for the first occurrence of the value in the array.
It looks like in your example you are trying to use it to make sure you're not comparing the same position in the array. In which case you could just replace that condition with if(i == j)
Going along with the other answers/comments stating the Array.IndexOf is not the correct approach to this problem, and not exactly sure if you're allowed to use LINQ, but that is by far a better approach, especially using the GroupBy method.
I have created a dotnetfiddle for you to show what I am doing.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
int[] myArr = new int[] { 10, 5, 5, 3, 3, 3 };
// int counter = 0; - now this is no longer needed
var numbersThatAreDuplicates = myArr.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => new { number = x.Key, countOfNumber = x.Count()}).ToList();
Console.WriteLine("There are {0} repeating values in the array.", numbersThatAreDuplicates.Count);
foreach (var item in numbersThatAreDuplicates)
{
Console.WriteLine(item.number + " repeats itself " + item.countOfNumber + " times.");
}
}
}
// Output
// There are 2 repeating values in the array.
// 5 repeats itself 2 times.
// 3 repeats itself 3 times.
As you can see, via the GroupBy method, you can find out how many numbers are repeating, as well as what the actual numbers are along with the number of occurrences that the actual number repeats itself in 1 line of code. Much cleaner, and efficient than using nesting for loops, but again I am not sure of what your limitations are.
I hope this helps.
You don't need to use the Array.IndexOf() function.
for example:
int[] myArr = new int[] { 10, 5, 5, 5};
int counter = 0;
List<int> dups = new List<int>();
for (int i = 0; i < myArr.Length; i++)
{
for (int j = 0; j < myArr.Length; j++)
{
if (i != j && myArr[i] == myArr[j] && !dups.Contains(i))
{
dups.Add(j);
counter++;
}
}
}
Console.WriteLine("There are {0} repeating values in the array.", counter);
// Output: There are 2 repeating values in the array.

Categories

Resources