Compare 2 tables and check if number exist - c#

I have 2 tables with random numbers and i want to check which number from first table doesn't exist in second one and output it.
Example:
First table: 2, 6, 7, 9
Second table: 0, 6, 11, 3
Output: 2, 7, 9
My current code:
#region CompareTables
int[,] TABLE1 = new int[5, 10];
int[,] TABLE2 = new int[5, 10];
Random rnd = new Random();
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
{
TABLE1[i, j] = rnd.Next(1, 100);
TABLE2[i, j] = rnd.Next(1, 100);
}
}
Console.Write("TABLE1" + "\n\n");
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
Console.Write(TABLE1[i, j] + " " + "\t");
Console.WriteLine();
}
Console.Write("\n");
Console.Write("TABLE2" + "\n\n");
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
Console.Write(TABLE2[i, j] + " " + "\t");
Console.WriteLine();
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
if (TABLE1[i, j] == TABLE2[i, j])
Console.WriteLine();
}
Console.ReadKey();
#endregion
I would like to ask how to output numbers that are in first table but not in second?

The problem you are having is that your tables are 2 dimensional arrays and you are trying to index into them as if they were one dimensional arrays.
Look at how your are filling them up:
TABLE1[i, j] = rnd.Next(1, 100);
TABLE2[i, j] = rnd.Next(1, 100);
You are correctly using two indexes i and j (think of rows and columns).
However, later on you are doing:
if (TABLE1[1] == TABLE2[i]) //where is the second index?
This is obviously wrong, but instead of making this work, lets take a step back and think this through again. All this mucking around with two indexes seems a little... yeah, mucky, shouldn't there be a better way to do this?
In your current problem, the fact that the tables are multidimensional is simply a pain that doesn't really add any value. If you only need to return elements of the first table that are not present in the second table without any position information, then why all this hassle with indexes to begin with? Lets create a helper method that flattens the arrays and enables us to get rid of at least one index:
static IEnumerable<T> Flatten<T>(this T[,] array)
{
for (var i = 0; i < array.GetLength(0); i++)
for (var j = 0; j < array.GetLength(1); j++)
yield return array[i, j];
}
And now that we have one dimensional arrays (IEnumerable<T>s) we can leverage C#'s magic stick...LINQ! Solving your problem is as simple as:
var notPresent = TABLE1.Flatten().Except(TABLE2.Flatten());
But this can have horrible performance if the arrays are big enough. Remember how you would solve this problem by hand (and how Except does it too): take first element from table 1, check all elements from table 2 until you either find a match or there are no more elements. Take second element from table 1, check all elements from table 2 until... etc. That seems a lot of work, and it grows really fast if the tables are big. Also if your are not smart about it you might be doing unnecessary extra work because Table 1 and 2 might contain duplicate elements...
Can this be improved? Yes, there are specially built collections that allow really fast searches; Sets. In your case, a HashSet<int> seems like a pretty good choice.
Your code now would look like:
var set = new HashSet<int>(TABLE1.Flatten());
var notPresent = set.Except(TABLE2.Flatten());
And this will perform much better.

You could covert your 2D arrays into lists and find the numbers from TABLE1 that don't exist in TABLE2 with LINQ Except:
List<int> LIST1 = TABLE1.Cast<int>().ToList();
List<int> LIST2 = TABLE2.Cast<int>().ToList();
var result = LIST1.Except(LIST2);

Related

how to print the row of a matrix(multi-dimensional array) in a new line

I have a multi-dimensional array in C#, I have assigned the indices of the matrices by capturing input from a user, I am trying to implement a conditional structure that will let me print the rows of my matrix each on a separate line, for example if my array is A and A has a dimension of 3 by 3 then the code prints the first three elements on the first line, the next three elements on the next line and so on and so forth. I am trying to achieve this because it will be easier to understand the structure as a normal matrix and also build an entire matrix class with miscallenous operations.
Code
class Matrix{
static int[,] matrixA;
static void Main(string[] args){
Console.WriteLine("Enter the order of the matrix");
int n = Int32.Parse(Console.ReadLine());
matrixA = new int[n, n];
//assigning the matrix with values from the user
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
matrixA[i, j] = Int32.Parse(Console.ReadLine());
}
}
//the code below tries to implement a line break after each row for the matrix
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if( (n-1-i) == 0)
{
Console.Write("\n");
}
else
{
Console.Write(matrixA[i, j].ToString() + " ");
}
}
}
}
}
How do I modify my code so that if the array has 9 elements and its a square matrix then each row with three elements are printed on a single line.
I would use something like this for the output:
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(matrixA[i, j].ToString() + " ");
}
Console.Write("\n");
}
When the inner loop is done, that means one row has been completely printed. So that's the only time the newline is needed. (n passes of the outer loop ==> n newlines printed).

How to set a maximum value of string that can be shown in a matrix?

I'm trying to make a matrix that will show the string s only if it it displays a number less than 10. It would probably be easier doing this with an integer instead of the string but it doesn't show the same 8x8(or any other combination) the same because the "string.Empty" seems to be being the key(if someone could explain that part too, it would help me).
I also want to know how to display lets say letter "a" in the whole matrix, so that if the matrix is 3x3 I see 3 "a" in 3 rows.
Code here shows me matrix which lets s go over 10 which makes it not looking like a square.
string s = "";
int[,] matrix = new int[8, 8];
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
s += matrix[i, j] = i + j;
}
Console.WriteLine(s);
s = string.Empty;
}

cannot apply indexing with [] to an express of type 'method group, (how to print array)

i have array that call nums, it contain int var.
the array is 2d -
int[,] nums = new int[lines, row];
i need to print each line in the array in other line.
when i try to print to array like this:
for (int i = 0; i < lines; i++)
for (int j = 0; j < 46; j++)
Console.Write(nums[i,j]);
** when i using the above syntax i dont get an error in visual studio, but when i run the program, i got error in this line - Console.Write(nums[i,j]);.
error - system.IndeOutOfRangeException.
i got the error , i try to change the syntax to this:
for (int i = 0; i < lines; i++)
for (int j = 0; j < 46; j++)
Console.Write(nums[i][j]);
the error: "wrong number of indices inside []; expected 2"
and:
for (int i = 0; i < lines; i++)
for (int j = 0; j < 46; j++)
Console.Write(nums[i][j].tostring());
update
i am so stupid... i write 46(number in my program) instead of 6(numbers in each row) thats whey is was out of range.
ty for all, and i am sry to open a question with such bad problem...
TY!
If lines and row are positive integer values, say, int lines = 5; int row = 7; you can print out your table like this:
int[,] nums = new int[lines, row]; // <- Multidimensional (2 in this case) array, not an array of array which is nums[][]
//TODO: fill nums with values, otherwise nums will be all zeros
for (int i = 0; i < lines; i++) {
Console.WriteLine(); // <- let's start each array's line with a new line
for (int j = 0; j < row; j++) { // <- What the magic number "46" is? "row" should be here...
Console.Write(nums[i, j]); // <- nums[i, j].ToString() doesn't spoil the output
if (j > 0) // <- let's separate values by spaces "1 2 3 4" instead of "1234"
Console.Write(" ");
}
}
You are dealing with 2 different types of arrays
int[,] nums = new int[lines, row];
is a Multi-Dimensional Array. Elements of the array can be accessed using nums[x,y].
When you use nums[x][y] you are dealing with an array of arrays.
You cannot use array of arrays syntax with a multi-dimensional array.
You might try What are the differences between Multidimensional array and Array of Arrays in C#? for details.

filling multidimensional array with unique numbers in C#

I'm trying to write a code that will fill array with unique numbers.
I could write the code separately for 1, 2 and 3 dimensional arrays but number of for cycles grow to "infinity".
this is the code for 2D array:
static void fillArray(int[,] array)
{
Random rand = new Random();
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
array[i, j] = rand.Next(1, 100);
for (int k = 0; k < j; k++)
if (array[i, k] == array[i, j])
j--;
}
}
print_info(array);
}
Is it possible to do something like this for n-dimensional arrays?
My approach is to start with a 1-d array of unique numbers, which you can shuffle, and then slot into appropriate places in your real array.
Here is the main function:
private static void Initialize(Array array)
{
var rank = array.Rank;
var dimensionLengths = new List<int>();
var totalSize = 1;
int[] arrayIndices = new int[rank];
for (var dimension = 0; dimension < rank; dimension++)
{
var upperBound = array.GetLength(dimension);
dimensionLengths.Add(upperBound);
totalSize *= upperBound;
}
var singleArray = new int[totalSize];
for (int i = 0; i < totalSize; i++) singleArray[i] = i;
singleArray = Shuffle(singleArray);
for (var i = 0; i < singleArray.Length; i++)
{
var remainingIndex = i;
for (var dimension = array.Rank - 1; dimension >= 0; dimension--)
{
arrayIndices[dimension] = remainingIndex%dimensionLengths[dimension];
remainingIndex /= dimensionLengths[dimension];
}
// Now, set the appropriate cell in your real array:
array.SetValue(singleArray[i], arrayIndices);
}
}
The key in this example is the array.SetValue(value, params int[] indices) function. By building up the correct list of indices, you can use this function to set an arbitrary cell in your array.
Here is the Shuffle function:
private static int[] Shuffle(int[] singleArray)
{
var random = new Random();
for (int i = singleArray.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
int tmp = singleArray[j];
singleArray[j] = singleArray[i - 1];
singleArray[i - 1] = tmp;
}
return singleArray;
}
And finally a demonstration of it in use:
var array1 = new int[2,3,5];
Initialize(array1);
var array2 = new int[2,2,3,4];
Initialize(array2);
My strategy assigns sequential numbers to the original 1-d array to ensure uniqueness, but you can adopt a different strategy for this as you see fit.
You can use Rank property to get the total number of dimentions in your array
To insert use SetValue method
In the first two for loops you are analysing the array properly (i and j go from the start to the end of the corresponding dimension). The problem comes in the most internal part where you introduce a "correction" which actually provokes an endless loop for j.
First iteration:
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
Second iteration
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
. etc., etc.
(I start my analysis in the moment when the internal loop is used for the first time. Also bear in mind that the exact behaviour cannot be predicted as far as random numbers are involved. But the idea is that you are making the j counter back over and over by following an arbitrary rule).
What you want to accomplish exactly? What is this last correction (the one provoking the endless loop) meant to do?
If the only thing you intend to do is checking the previously stored values, you have to rely on a different variable (j2, for example) which will not affect any of the loops above:
int j2 = j;
for (int k = 0; k < j2; k++)
if (array[i, k] == array[i, j2])
j2--;

What's Wrong with my Merge sort Code?

I am learning to code and I though I'd try writing a merge sort algorithm (something we heard about in our analytic course but NOT homework). I was working from the pseudo code the trainer showed us but I cannot identify the problem. Any chance someone could point me in the right direction?
edit: The algorithm only returns the first value in the List.
static List<int> mergeSort(List<int> mj)
{
List<int>m = mj;
if(m.Count <= 1)
return m;
List<int> merge = new List<int>();
List<int> left = new List<int>();
List<int> right = new List<int>();
int middle = m.Count/2;
for (int i = 0; i < middle; i++)
left.Add(m[i]);
for (int j = middle; j >= m.Count; j++)
right.Add(m[j]);
left = mergeSort(left);
right = mergeSort(right);
merge.AddRange(left);
merge.AddRange(right);
for (int k = 0; k < merge.Count; k++)
{
Console.Write(merge[k] + ",");
}
return merge;
}
The problem with your code (apart from the bug Mike Cowan mentioned) is that you’re not performing any actual sorting. You’re first recursively splitting your lists in half (which is correct), but then you’re simply concatenating them back together in their original order, thereby achieving no result:
merge.AddRange(left);
merge.AddRange(right);
What you need to do instead is iterate through your two sublists (which, by induction, should have been respectively sorted in the recursive calls), and add elements to the merged list in order.
We start off by comparing the 0th elements: left[0] against right[0]. Whichever of the two is smaller, is added to the merge list, and its sublist’s counter is incremented. Suppose that left[0] < right[0]: we add left[0] to merge, and in the next iteration, we would then need to consider left[1] against right[0]. If left[1] is again smaller, we add it to merge and, in the next iteration, consider left[2] against right[0]. If right[0] is now the smaller of the two, we add it to merge and, in the next iteration, compare left[2] against right[1]. And so on.
This keeps going on until one of the sublists is exhausted. When that happens, we simply add all the elements from the remaining sublist into merge.
int leftIndex = 0;
int rightIndex = 0;
while (leftIndex < left.Count && rightIndex < right.Count)
if (left[leftIndex] < right[rightIndex])
merge.Add(left[leftIndex++]);
else
merge.Add(right[rightIndex++]);
while (leftIndex < left.Count)
merge.Add(left[leftIndex++]);
while (rightIndex < right.Count)
merge.Add(right[rightIndex++]);
Additionally, you should not be writing to console within your recursive method. Move your Console.Write calls to your Main method:
static void Main(string[] args)
{
List<int> original = new List<int>(new int[] { 4, 75, 12, 65, 2, 71, 56, 33, 78,1, 4, 56, 85, 12, 5,77, 32, 5 });
List<int> sorted = mergeSort(original);
for (int k = 0; k < sorted.Count; k++)
Console.Write(sorted[k] + ",");
}
This line:
for (int j = middle; j >= m.Count; j++)
right.Add(m[j]);
should read:
for (int j = middle; j < m.Count; j++)
right.Add(m[j]);
First off, the line
for (int j = middle; j >= m.Count; j++)
should be
for (int j = middle; j < m.Count; j++)
Also, you never actually merge the left and right, you're just placing them on top of eachother. The line
merge.AddRange(left);
merge.AddRange(right);
Should be something like
mergeLeftRight(left, right)
Where mergeLeftRight is a second function you define that does the actual sorting. Read the wikipedia article on Merge Sorts: http://en.wikipedia.org/wiki/Merge_sort
Simple merge sort steps
if( mj.length == 1 ) return mj;
Split into left and right lists and recurse
when left and right lists return, merge them <-- you do not do this
return merged left and right lists

Categories