List< string > to string[,] - c#

I have a List<string> tmpNames that contains names e.g. ("A","B","C","D","E",F").
The size of tmpNames can be different (it is a result obtained from client input).
Now I need to create a matrix with a number of rows and columns.
string[,] tmpMatrix = new string[tmpRows.Count,tmpCols.Count];
But to iterate and build the matrix I have the following code in which I can not access all items in tmpNames.
for(int i= 0; i<tmpRows.Count; i++){
for(int j= 0; j<tmpRows.Count; j++){
tmpMatrix[i,j] = tmpNames[i];
}
}
The result that I need is:
A B C
D E F

You have to calculate which index you need from tmpNames - you need both i and j for that. You might want to put it on paper to see the pattern:
j=0 j=1 j=2
i=0 0 1 2
i=1 3 4 5
Your code should be something like:
for(int i= 0; i<tmpRows.Count; i++){
for(int j= 0; j<tmpCols.Count; j++){
tmpMatrix[i,j] = tmpNames[i * tmpCols.Count + j];
}
}
Note that I have also corrected the condition in the 2nd loop: you have to compare j with tmpCols.Count, not tmpRows.Count.

You could use separate indexes for Row, Column & source:
for(int i = 0, source = 0; i < tmpRows.Count; i++){
for(int j = 0; j < tmpCols.Count; j++){
tmpMatrix[i, j] = tmpNames[source++];
}
}

You can calculate the indexes in the tmpMatrix from the index in the tmpNames list and populate it using a single loop:
int index = 0;
for (int index = 0; index < tmpNames.Count; index++) {
tmpMatrix[index / tmpCols.Count, index % tmpCols.Count] = tmpNames[index];
}
By using divison and modulo (%) you get the result as row and reminder as column:
index index / 3 index % 3
----- --------- ---------
0 0 0
1 0 1
2 0 2
3 1 0
4 1 1
5 1 2

Related

For-loops, array and ++ operator

Beginner asking a question.
I am testing the increment ++ operator within for-loop and the outcome is different than I expect it to be and I have no clue why. The code is not for a specific program.
int[] numbers = new int[10];
for (int i = 0; i < 10; i++)
{
numbers[i] = i++;
}
for (int a = 0; a < 10; a++)
{
Console.WriteLine("value is {0} at position {1}", numbers[a], a);
}
Output is:
value is 0 at position 0
value is 0 at position 1
value is 2 at position 2
value is 0 at position 3
value is 4 at position 4
value is 0 at position 5
value is 6 at position 6
value is 0 at position 7
value is 8 at position 8
value is 0 at position 9
If i run the first for-loop without the ++ increment (numbers[i] = i;), the values are consecutive and in order (0, 1, 2, 3 etc.). Why the ++ increment causes every other value to be zero? I thought it would be something like 0, 2, 4, 6, 8, 10 etc.
If I run numbers[i] = i+1;
outcome is something I would expect:
value is 1 at position 0
value is 2 at position 1
value is 3 at position 2
value is 4 at position 3
value is 5 at position 4
value is 6 at position 5
value is 7 at position 6
value is 8 at position 7
value is 9 at position 8
value is 10 at position 9
The code you write is
for (int i = 0; i < 10; i++)
{
numbers[i] = i++;
}
that is equal to
for (int i = 0; i < 10; i++)
{
numbers1[i] = i;
i = i + 1;
}
First time i is start from 0
// I change the i to real value for easy understanding
for (int i = 0; i < 10; i++)
{
numbers1[0] = 0;
i = 0 + 1;
//so here i is 1
}
Second time i is 2, because after first time loop the i is 1 then the for (int i = 0; i < 10; i++) will increase i from 1 to 2,
so the second time loop will be
for (int i = 0; i < 10; i++)
{
numbers1[2] = 2;
i = 2 + 1;
//so here i is 3
}
So now you know the numbers[0] is 0 and numbers[2] is 2 but about the numbers[1] you don't set the value for it so it will be the default value which the default value of int is 0.
Thank you Michael! I verified that out also by myself when messing around with the code. First I tried adding one more i++;
for (int i = 0; i < 50; i++)
{
numbers[i] = i++;
i++;
}
It gave me value on every third row.
And then third i++:
for (int i = 0; i < 50; i++)
{
numbers[i] = i++;
i++;
i++;
}
Now value every fourth line.
Solved.

How could the bug in the below C# code be fixed by only changing 1 or 2 lines of code?

I'm trying to solve the below problem in C# which I was unable to answer within the time limit during a technical interview.
The provided code contains a bug and it can only be fixed by amending 2 lines of code at most.
The function takes 2 integer arrays as parameters.
All integers within both parameters will always be positive integers.
There may be multiple occurrences of the same integer in each array parameter.
The function should return the lowest positive integer that exists in both arrays.
The function should return -1 if no such integer exists
public int test(int[] A, int[] B)
{
int m = A.Length;
int n = B.Length;
Array.Sort(A);
Array.Sort(B);
int i = 0;
for (int k = 0; k < m; k++)
{
if (i < n - 1 && B[i] < A[k])
i += 1;
if (A[k] == B[i])
return A[k];
}
return -1;
}
I'm struggling to come up with a solution that only amends 1-2 lines of code. I thought I could replace i += 1; with i += 1; k = 0; but this is obviously adding a new line.
The original code will work for some inputs but not something like the below example because we don't want to increase k when B[i] < A[k]:
int[] A = { 3, 4, 5, 6 };
int[] B = { 2, 2, 2, 3 ,5 };
Considering you can only amend the code and not add new lines to it, I believe the following should be working:
public int test(int[] A, int[] B)
{
int m = A.Length;
int n = B.Length;
Array.Sort(A);
Array.Sort(B);
int i = 0;
for (int k = 0; k < m; k++)
{
while (i < n - 1 && B[i] < A[k])
{
i += 1;
}
if (A[k] == B[i])
return A[k];
}
return -1;
}
What changed is that the if that was checking for i is now a while
It's not exactly the prettiest code, but since those are the requirements...

Print a matrix in following format for given number

For a given number n I have to print the following matrix (n = 3 example):
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
the count of rows and columns should be (2 * n) - 1. I tried to find the pattern but couldn't figured it out. Any help would be helpful. Thanks
Something like this:
private static int[][] Matrix(int n) {
// Create arrays
int[][] result = Enumerable.Range(0, 2 * n - 1)
.Select(_ => new int[2 * n - 1])
.ToArray();
// Feed arrays
for (int i = 1; i <= n; ++i) {
int from = i - 1;
int to = 2 * n - i - 1;
int v = n - i + 1;
for (int j = from; j <= to; ++j) {
result[from][j] = v;
result[to][j] = v;
result[j][from] = v;
result[j][to] = v;
}
}
return result;
}
....
int n = 3;
String report = String.Join(Environment.NewLine, Matrix(n)
.Select(line => String.Join(" ", line)));
Console.Write(report);
Output for n = 3 is
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
And for n = 4:
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
Here's a version that doesn't use any intermediate storage:
static void printMatrix(int n)
{
int x = 2*n - 1;
for (int i = 0, p = n; i < x; ++i, p += (i > x/2) ? 1 : -1)
{
for (int j = 0, q = n; j < x; ++j, q += (j > x/2) ? 1 : -1)
Console.Write(Math.Max(p, q) + " ");
Console.WriteLine();
}
}
This works as follows:
The outer loop (i) and inner loop (j) both go from 0 .. 2*n-1.
However, the values that we want to print (p and q) start at n and decrease until halfway across/down the matrix, at which point they start increasing again.
We can determine whether to increment or decrement these values by checking the loop variable to see if it is halfway across/down the matrix yet. If it is, we decrement, otherwise we increment.
That's what this is doing: p += (i > x/2) ? 1 : -1.
If i > x/2 then the value 1 will be used for the increment, otherwise -1 will be used for the increment (i.e. it will be decremented).
(Similarly for q.)
The final piece of the puzzle is that the value we want to use is actually the maximum of p and q. If you inspect the matrix, you will see that if you consider each row value and each column value, the maximum of each is used for the corresponding cell.
Hence the use of Math.Max(p, q) in the output.
Here a simpler solution less complicated and fastest here so far:
private static void printMatrix(int n)
{
// length of the matrix in one dimension
int length = (2 * n) - 1;
// iterate through y axis of the matrix
for (int i = 0; i < length; i++)
{
int value = n;
// iterate through x axis of the matrix
for (int j = 0; j < length; j++)
{
Console.Write(value);
if (i > j && i + j < length - 1)
{
value--;
}
else if (i <= j && i + j >= length - 1)
{
value++;
}
}
Console.WriteLine();
}
}
Explanation for the if statements
First take a look on the matrix like it would be an array and look at the indexes and values and what changes when iterating through the array in the two for statements whereas the value of i is for the y axis, from up to down and the value of j is for the x axis, from left to right.
// +1 and -1 means the changes of the values
0,0 0,1 0,2 0,3 0,4 // values of i,j (first is i, second is j)
[3] [3] [3] [3] [3] // printed value
1,0 1,1 1,2 1,3 1,4
[3] -1 [2] [2] [2] +1 [3]
2,0 2,1 2,2 2,3 2,4
[3] -1 [2] -1 [1] +1 [2] +1 [3]
3,0 3,1 3,2 3,3 3,4
[3] -1 [2] [2] [2] +1 [3]
4,0 4,1 4,2 4,3 4,4
[3] [3] [3] [3] [3]
As you can see, the value changes only in specific circumstances.
And this happens -1 if i > j and if i + j < length - 1, otherwise after index 3,1 you will have wrong values, after that it shouldn't subtract the value any more.
This two if statements lead us to the first statement in the code:
if (i > j && i + j < length - 1)
{
value--;
}
Now it also happens +1 if i + j >= length - 1 but that not other values like 3,1 also add +1 to the value it only increments it, if i <= j, which leads us to the second if-statement in the code:
else if (i <= j && i + j >= length - 1)
{
value++;
}
If none of these statements are true, the value simply stays the same as it should.

C# Printing a border around a 2D Array

I have a multidimensional array that I'm using as a box, and I have code that generates a border around it, like this:
#######
# #
# #
# #
# #
#######
However what I don't understand is that I can have either a 0 or a 1 in the "j == ProcArea.GetUpperBound(...)" part and it works successfully without any errors or unexpected output.
int[,] ProcArea = new int[rows, columns];
//Generate border
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
if (i == 0 || j == 0 || i == ProcArea.GetUpperBound(0) || j == ProcArea.GetUpperBound(1))
{
ProcArea[i, j] = 2;
}
}
}
Why does this work, and what is the correct value I should be using?
Thanks
If the number of rows and columns are the same, then GetUpperBound(0) and GetUpperBound(1) are going to return the same value.
Arrays you create in C# (unless you call Array.CreateInstance directly) are always 0-based. So GetUpperBound(0) will always return rows - 1, and GetUpperBound(1) will always return columns - 1.
So the code will "work" regardless of which upper bound you check, although I think you'll find that if rows != columns, then using GetUpperBound(0) will create a different sized box than GetUpperBound(1).
By the way, an alternate way of making your border would be:
var maxRow = ProcArea.GetUpperBound(0);
var maxCol = ProcArea.GetUpperBound(1);
// do top and bottom
for (int col = 0; col <= maxCol; ++col)
{
ProcArea[0, col] = 2;
ProcArea[maxRow, col] = 2;
}
// do left and right
for (int row = 0; row <= maxRow; ++row)
{
ProcArea[row, 0] = 2;
ProcArea[row, maxCol] = 2;
}
It's slightly more code, true, but you don't waste time checking indexes unnecessarily. Won't make a difference with small arrays, of course.
Check the documentation http://msdn.microsoft.com/en-us/library/system.array.getupperbound.aspx. Your array has 2 dimensions (rows and columns).
ProcArea.GetUpperBound(0) is equivalent to rows - 1
ProcArea.GetUpperBound(1) is equivalent to columns - 1

C# looping through an array

I am looping through an array of strings, such as (1/12/1992 apple truck 12/10/10 orange bicycle). The array's length will always be divisible by 3. I need to loop through the array and grab the first 3 items (I'm going to insert them into a DB) and then grab the next 3 and so on and so forth until all of them have been gone through.
//iterate the array
for (int i = 0; i < theData.Length; i++)
{
//grab 3 items at a time and do db insert, continue until all items are gone. 'theData' will always be divisible by 3.
}
Just increment i by 3 in each step:
Debug.Assert((theData.Length % 3) == 0); // 'theData' will always be divisible by 3
for (int i = 0; i < theData.Length; i += 3)
{
//grab 3 items at a time and do db insert,
// continue until all items are gone..
string item1 = theData[i+0];
string item2 = theData[i+1];
string item3 = theData[i+2];
// use the items
}
To answer some comments, it is a given that theData.Length is a multiple of 3 so there is no need to check for theData.Length-2 as an upperbound. That would only mask errors in the preconditions.
i++ is the standard use of a loop, but not the only way. Try incrementing by 3 each time:
for (int i = 0; i < theData.Length - 2; i+=3)
{
// use theData[i], theData[i+1], theData[i+2]
}
Not too difficult. Just increment the counter of the for loop by 3 each iteration and then offset the indexer to get the batch of 3 at a time:
for(int i=0; i < theData.Length; i+=3)
{
var item1 = theData[i];
var item2 = theData[i+1];
var item3 = theData[i+2];
}
If the length of the array wasn't garuanteed to be a multiple of three, you would need to check the upper bound with theData.Length - 2 instead.
Your for loop doesn't need to just add one. You can loop by three.
for(int i = 0; i < theData.Length; i+=3)
{
string value1 = theData[i];
string value2 = theData[i+1];
string value3 = theData[i+2];
}
Basically, you are just using indexes to grab the values in your array. One point to note here, I am not checking to see if you go past the end of your array. Make sure you are doing bounds checking!
This should work:
//iterate the array
for (int i = 0; i < theData.Length; i+=3)
{
//grab 3 items at a time and do db insert, continue until all items are gone. 'theData' will always be divisible by 3.
var a = theData[i];
var b = theData[i + 1];
var c = theData[i + 2];
}
I've been downvoted for this answer once. I'm pretty sure it is related to the use of theData.Length for the upperbound. The code as is works fine because array is guaranteed to be a multiple of three as the question states. If this guarantee wasn't in place, you would need to check the upper bound with theData.Length - 2 instead.
Here is a more general solution:
int increment = 3;
for(int i = 0; i < theData.Length; i += increment)
{
for(int j = 0; j < increment; j++)
{
if(i+j < theData.Length) {
//theData[i + j] for the current index
}
}
}
string[] friends = new string[4];
friends[0]= "ali";
friends[1]= "Mike";
friends[2]= "jan";
friends[3]= "hamid";
for (int i = 0; i < friends.Length; i++)
{
Console.WriteLine(friends[i]);
}Console.ReadLine();

Categories

Resources