I am taking a C# class and I need help understanding the following code.
The code has an array which represents responses to a survey, with values 1 thru 10.
The output displays these ratings and the frequency of how many times a value was selected.
The following code is from my book, but I have modified it to just a basic example.
int[] responses = { 3, 2, 5, 6, 3, 5 , 4, 5, 5, 5};
int[] frequency = new int[7];
for (int answer = 0; answer < responses.Length; answer++)
++frequency[responses[answer]];
for (int rating = 1; rating < frequency.Length; rating++)
Console.WriteLine(rating + ", " + frequency[rating]);
Console.Read();
How does the line ++frequency[responses[answer]]; work? In looking at this, if I take reponses[answer] the first time through the loop, this would represent responses[0] which would be a 3, correct? This is where I get confused, what does the ++frequency part of this line do?
frequency[responses[answer]] = frequency[responses[answer]] + 1;
EDIT: I think it's pretty unclear to write it like that. As a personal preference, I don't like using unary operations (++x, x++, etc) on elements that have lots of indexes present.
It adds one to the frequency at that location in the array.
For example, the frequency at position 3 (from your example) will be increased by one after that line executes.
EDIT: So, in more detail, when answer = 0, responses[0] = 3, so frequency[3] gets one added to it.
The ++ could very easily be at the end of the command as well. In other words,
++frequency[responses[answer]];
is the same thing (IN THIS CASE) as using
frequency[responses[answer]]++;
Let's break it down: As you point out, on the first pass responses[answer] will evaluate to "3"
So this then looks like ++frequency[3]
The ++ is incrementing the value of the array at index 3 by 1
Simple enough?
I should also point out that applying the ++ before the array rather than after it does effect how the incrementing is executed (although it doesn't effect the results of this code).
For instance:
int n = 2;
int j = ++n;
int k = n++;
What are j and k?
j will be 3, and k will also be 3. This is because if you place the ++ before, it evaluates it first. If you place it at the end, it evaluates it after the rest of the expression.
If it helps, think of ++frequency[] as "frequency = frequency + 1".
If the ++ operator comes before the variable, then the increment is applied before the statement is executed. If the ++ comes afterwards, then the statement is executed and then the variable is incremented.
In this case, it doesn't matter, since incrementing before or after doesn't impact the logic.
Since "responses[answer]" evaluates to a number, that line of code is incrementing the frequency entry at that array index. So the first time through, answer is 0, so responses[answer] is 3, so the frequency[3] box is getting incremented by 1. The next time through, the frequency[2] box is incremented... etc. etc. etc.
frequency is an array, where all elements are initialized to 0 (the default value for an int). The line ++frequency[responses[answer]] will increment the frequency element pointed out by the integer found at responses[answer]. By putting the ++ in front of frequency, the array element will be incremented before the resulting value is returned.
You can read more about the ++ operator here.
In cases like this it's often useful to rewrite the code as you walk it.
When answer = 0
++frequency[responses[0]]
++frequency[3] since responses[0] = 3
frequency now looks like { 0, 0, 0, 1, 0, 0, 0 }
When answer = 1
++frequency[responses[1]]
++frequency[2] since responses[1] = 2
frequency now looks like { 0, 0, 1, 1, 0, 0, 0 }
And so on.
It means increment the value at frequency[ 3 ]. Where 3 is the return result from responses[answer]. Similarly the next iteration would increment the value at frequency[ 2 ].
The ++ operator in C# when applied to an integer will increment it by one.
The specific line you're looking at, frequency is an array of integers with 7 elements. Which is sort of confusing, because the way you explained it in your code, it would appear that this code would break with any value in the responses array above 6.
That issue aside, basically it's incrementing whichever index of the array it's accessing. So in your example responses[0] would be 3. So this line would find the value of frequency[3] and increment it by 1. Since integer arrays are initialized with all values at zero, then after the first iteration, frequency[3] would be 1. Then if there was another 3 later in your responses array, frequency[3] would be incremented again (i.e. responses[4]).
I hope this helps you.
The goal of the code snippet seems to be to determine the number of times each response appears in the 'responses' array. So, for your example set, frequency[3] should be 5, frequency[5] should be 5, etc.
So, the line you are asking about takes the current element from the responses array, and increments the associated value in the frequency array by 1, to indicate that the particular value has been observed in responses.
Once the entire code snippet executes, the frequency array contains the number of times each element from 0 to 7 was observed in the responses array.
It is using the frequency array to count how many times each response was entered. You could have a counter for each answer:
int numberOfOnes = 0;
int numberOfTwos = 0;
// Etc...
But that would be ugly programming and not as easy or efficient. Using the frequency array allows you do not use an if/else if block or a switch and makes your code easier to read.
Another thing about that frequency array.
int[] frequency = new int[7];
This initializes all the integers in the array to 0, that's why you can just start off by incrementing it instead of seeing if it was the first time for that specific response and then initializing it with 1 or something of that nature.
Good luck with all the fun C# you have ahead of you.
Related
While using LastIndexOf to search for a short string in a longer string I came across behavior that I find somewhat counterintuitive:
If I have a haystack and a needle:
var h = "abcabcabc";
var n = "abc";
And I tell LastIndexOf to start searching at index 3, 4, I would expect it to start looking there and proceed towards the start of the string, and hence return 3:
012345678
abcabcabc
abc <- try index 4, no
abc <- found at index 3
..but it actually locates the first abc and returns 0. It behaves like there is an assumption "user wants to start searching for a string of length 3 starting at index 4; the string couldn't possibly occur at any index higher than 2 so search will begin from index 2.. found at index 0" - while that would be true if one was starting from the very end of the string i.e. a needle of length 3 couldn't possibly be found any later than haystack.Length-3, I don't find it logical to adopt the approach in the middle of a string
Another way of looking at it is "the haystack is substringed so that it has a length equal to the startIndex and then the substringed haystack is searched" - but again, I don't find it reasonable to chop a document and remove a potential match
While I can reason the search logic out thus and try to remember it, it seems illogical to me to operate in such a manner, so I'm here asking if there is some underlying reason for this behavior that will make it easier to reason about?
Note: it's also fine to say "no, your logic of "start at 4, find at 3 is unreasonable because.." - it would help adjust my mental model of how I think LastIndexOf should work
from the documentation - it says
Reports the zero-based index position of the last occurrence of a
specified string within this instance. The search starts at a
specified character position and proceeds backward toward the
beginning of the string.
So it searches from the value to the beginning of the string. Different starting point as your expectation.
Update: as Matthew Watson mentioned in his comment from the source code
For LastIndexOf specifially, overloads which take a 'startIndex' and 'count' behave differently than their IndexOf counterparts. 'startIndex' is the index of the last char element that should be considered when performing the search. For example, if startIndex = 4, then the caller is indicating "when finding the match I want you to include the char element at index 4, but not any char elements past that point.
var h = "abcabcabc";
//index 012345678
// ^ last element that will be considdered "abca"
var n = "abc";
int result = h.LastIndexOf(n,3); //0
How can I determine size of an array (length / number of items) in C#?
If it's a one-dimensional array a,
a.Length
will give the number of elements of a.
If b is a rectangular multi-dimensional array (for example, int[,] b = new int[3, 5];)
b.Rank
will give the number of dimensions (2) and
b.GetLength(dimensionIndex)
will get the length of any given dimension (0-based indexing for the dimensions - so b.GetLength(0) is 3 and b.GetLength(1) is 5).
See System.Array documentation for more info.
As #Lucero points out in the comments, there is a concept of a "jagged array", which is really nothing more than a single-dimensional array of (typically single-dimensional) arrays.
For example, one could have the following:
int[][] c = new int[3][];
c[0] = new int[] {1, 2, 3};
c[1] = new int[] {3, 14};
c[2] = new int[] {1, 1, 2, 3, 5, 8, 13};
Note that the 3 members of c all have different lengths.
In this case, as before c.Length will indicate the number of elements of c, (3) and c[0].Length, c[1].Length, and c[2].Length will be 3, 2, and 7, respectively.
You can look at the documentation for Array to find out the answer to this question.
In this particular case you probably need Length:
int sizeOfArray = array.Length;
But since this is such a basic question and you no doubt have many more like this, rather than just telling you the answer I'd rather tell you how to find the answer yourself.
Visual Studio Intellisense
When you type the name of a variable and press the . key it shows you a list of all the methods, properties, events, etc. available on that object. When you highlight a member it gives you a brief description of what it does.
Press F1
If you find a method or property that might do what you want but you're not sure, you can move the cursor over it and press F1 to get help. Here you get a much more detailed description plus links to related information.
Search
The search terms size of array in C# gives many links that tells you the answer to your question and much more. One of the most important skills a programmer must learn is how to find information. It is often faster to find the answer yourself, especially if the same question has been asked before.
Use a tutorial
If you are just beginning to learn C# you will find it easier to follow a tutorial. I can recommend the C# tutorials on MSDN. If you want a book, I'd recommend Essential C#.
Stack Overflow
If you're not able to find the answer on your own, please feel free to post the question on Stack Overflow. But we appreciate it if you show that you have taken the effort to find the answer yourself first.
for 1 dimensional array
int[] listItems = new int[] {2,4,8};
int length = listItems.Length;
for multidimensional array
int length = listItems.Rank;
To get the size of 1 dimension
int length = listItems.GetLength(0);
yourArray.Length :)
With the Length property.
int[] foo = new int[10];
int n = foo.Length; // n == 10
For a single dimension array, you use the Length property:
int size = theArray.Length;
For multiple dimension arrays the Length property returns the total number of items in the array. You can use the GetLength method to get the size of one of the dimensions:
int size0 = theArray.GetLength(0);
In most of the general cases 'Length' and 'Count' are used.
Array:
int[] myArray = new int[size];
int noOfElements = myArray.Length;
Typed List Array:
List <int> myArray = new List<int>();
int noOfElements = myArray.Count;
it goes like this:
1D:
type[] name=new type[size] //or =new type[]{.....elements...}
2D:
type[][]name=new type[size][] //second brackets are emtpy
then as you use this array :
name[i]=new type[size_of_sec.Dim]
or You can declare something like a matrix
type[ , ] name=new type [size1,size2]
What has been missed so far is what I suddenly was irritated about:
How do I know the amount of items inside the array? Is .Length equal .Count of a List?
The answer is: the amount of items of type X which have been put into an array of type X created with new X[number] you have to carry yourself!
Eg. using a counter: int countItemsInArray = 0 and countItemsInArray++ for every assignment to your array.
(The array just created with new X[number] has all space for number items (references) of type X already allocated, you can assign to any place inside as your first assignment, for example (if number = 100 and the variable name = a) a[50] = new X();.
I don't know whether C# specifies the initial value of each place inside an array upon creation, if it doesn't or the initial value you cannot compare to (because it might be a value you yourself have put into the array), you would have to track which places inside the array you already assigned to too if you don't assign sequentially starting from 0 (in which case all places smaller than countItemsInArray would be assigned to).)
In your question size of an array (length / number of items) depending on whether / is meant to stand for "alternative" or "divide by" the latter still has to be covered (the "number of items" I just gave as "amount of items" and others gave .Length which corresponds to the value of number in my code above):
C# has a sizeof operator (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/sizeof). It's safe to use for built-in types (such as int) (and only operates on types (not variables)). Thus the size of an array b of type int in bytes would be b.Length * sizeof(int).
(Due to all space of an array already being allocated on creation, like mentioned above, and sizeof only working on types, no code like sizeof(variable)/sizeof(type) would work or yield the amount of items without tracking.)
I am having trouble understanding what the for loop is doing.
To me, I see it as:
int i = 0; //Declaring i to become 0. i is the value in myArray?
i < myArray.Length; //When i is less than any value in myArray keep looping?
i++; //Every time this loop goes through increase i by 1?
//Making an array called myArray that contains 20,5,7,2,55
int[] myArray = { 20, 5, 7, 2, 55 };
//Using the built in feature, Array.Sort(); to sort out myArray
Array.Sort(myArray);
for (int i = 0; i < myArray.Length; i++)
{
Console.WriteLine(myArray[i]);
}
I'm going to make some assumptions about your knowledge of programming, so forgive me if this explanation covers topics you're already familiar with, but they are all important for understanding what a for loop does, what it's use is and what the semantics are going to be when someone comes behind you and reads your code. Your question demonstrates that you're super close to understanding it, so hopefully it'll hit you like a ton of bricks once you have a good explanation.
Consider an array of strings of length 5. You would initialize it in C# like so:
string[] arr = new string[5];
What this means is that you have an array that has allocated 5 slots for strings. The names of these slots are the indexes of the array. Unfortunately for those who are new to programming, like yourself, indexes start at 0 (this is called zero-indexing) instead of 1. What that means is that the first slot in our new string[] has the name or index of 0, the second of 1, the third of 3 and so on. That means that they length of the array will always be a number equal to the index of the final slot plus one; to put it another way, because arrays are 0 indexed and the first (1st) slot's index is 0, we know what the index of any given slot is n - 1 where n is what folks who are not programmers (or budding programmers!) would typically consider to be the position of that slot in the array as a whole.
We can use the index to pick out the value from an array in the slot that corresponds to the index. Using your example:
int[] myArray = { 20, 5, 7, 2, 55 };
bool first = myArray[0] == 20: //=> true
bool second = myArray[1] == 5; //=> true
bool third = myArray[2] == 7; //=> true
// and so on...
So you see that the number we are passing into the indexer (MSDN) (the square brackets []) corresponds to the location in the array that we are trying to access.
for loops in C syntax languages (C# being one of them along with C, C++, Java, JavaScript, and several others) generally follow the same convention for the "parameters":
for (index_initializer; condition; index_incrementer)
To understand the intended use of these fields it's important to understand what indexes are. Indexes can be thought of as the names or locations for each of the slots in the array (or list or anything that is list-like).
So, to explain each of the parts of the for loop, lets go through them one by one:
Index Initializer
Because we're going to use the index to access the slots in the array, we need to initialize it to a starting value for our for loop. Everything before the first semicolon in the for loop statement is going to run exactly once before anything else in the for loop is run. We call the variable initialized here the index as it keeps track of the current index we're on in the scope of the for loop's life. It is typical (and therefore good practice) to name this variable i for index with nested loops using the subsequent letters of the Latin alphabet. Like I said, this initializing statement happens exactly once so we assign 0 to i to represent that we want to start looping on the first element of the array.
Condition
The next thing that happens when you declare a for loop is that the condition is checked. This check will be the first thing that is run each time the loop runs and the loop will immediately stop if the check returns false. This condition can be anything as long as it results in a bool. If you have a particularly complicated for loop, you might delegate the condition to a method call:
for (int i = 0; ShouldContinueLooping(i); i++)
In the case of your example, we're checking against the length of the array. What we are saying here from an idiomatic standpoint (and what most folks will expect when they see that as the condition) is that you're going to do something with each of the elements of the array. We only want to continue the loop so long as our i is within the "bounds" of the array, which is always defined as 0 through length - 1. Remember how the last index of an array is equal to its length minus 1? That's important here because the first time this condition is going to be false (that is, i will not be less than the length) is when it is equal to the length of the array and therefore 1 greater than the final slot's index. We need to stop looping because the next part of the for statement increases i by one and would cause us to try to access an index outside the bounds of our array.
Index incrementer
The final part of the for loop is executed once as the last thing that happens each time the loop runs. Your comment for this part is spot on.
To recap the order in which things happen:
Index initializer
Conditional check ("break out" or stop lopping if the check returns false)
Body of loop
Index incrementer
Repeat from step 2
To make this clearer, here's your example with a small addition to make things a little more explicit:
// Making an array called myArray that contains 20,5,7,2,55
int[] myArray = { 20, 5, 7, 2, 55 };
// Using the built in feature, Array.Sort(); to sort out myArray
Array.Sort(myArray);
// Array is now [2, 5, 7, 20, 55]
for (int i = 0; i < myArray.Length; i++)
{
int currentNumber = myArray[i];
Console.WriteLine($"Index {i}; Current number {currentNumber}");
}
The output of running this will be:
Index 0; Current number 2
Index 1; Current number 5
Index 2; Current number 7
Index 3; Current number 20
Index 4; Current number 55
I am having trouble understanding what the for loop is doing.
Then let's take a big step back.
When you see
for (int i = 0; i < myArray.Length; i++)
{
Console.WriteLine(myArray[i]);
}
what you should mentally think is:
int i = 0;
while (i < myArray.Length)
{
Console.WriteLine(myArray[i]);
i++;
}
Now we have rewritten the for in terms of while, which is simpler.
Of course, this requires that you understand "while". We can understand while by again, breaking it down into something simpler. When you see while, think:
int i = 0;
START:
if (i < myArray.Length)
goto BODY;
else
goto END;
BODY:
Console.WriteLine(myArray[i]);
i++;
goto START;
END:
// the rest of your program here.
Now we have broken down your loop into its fundamental parts and the control flow is laid bare to your understanding. Walk through it.
We start with i equal to 0. Suppose the length of the array is 3.
Is 0 less than 3? Yes. So we go to BODY next. We write the 0th element of the array and increment i to 1. Now we go back to START.
Is 1 less than 3? Yes. So we go to BODY next. We write the 1th element of the array and increment i to 2. Now we go back to START.
Is 2 less than 3? Yes. So we go to BODY next. We write the 2th element of the array and increment i to 3. Now we go back to START.
Is 3 less than 3? No. So we go to END, and the rest of your program executes.
Now, you probably have noticed that the "goto" form is incredibly ugly and hard to read and reason about. That's why we invented while and for loops, so that you don't have to write awful code that uses gotos. But you can always reason about simple control flow by going back to the goto form mentally.
i < myArray.Length;
This is not testing against the values inside myArray but against the length (how many items the array contains). Therefore it means: When i is less than the length of the array.
So the loop will keep going, adding 1 to i (as you correctly said) each time it loops, when i is equal to the length of the array, meaning it has gone through all the values, it will exit the loop.
As Nicolás Straub pointed out, i is the index of the array, meaning the location of an item in an array, you have initialised it with the value of 0, this is correct because the first value in an array would have an index of 0.
To directly answer your question about for loops:
A for loop is executing lines of code iteratively (multiple times), the amount depends on its control statement:
for (int i = 0; i < myArray.Length; i++)
For loops are generally pre-condition (the condition to loop is before the code) and have loop counters, being i (i is actually a counter but can be seen as the index because you are going through every element, if you wanted to skip some then i would only be a counter). For is great for when you know how many times you want to loop before you start looping.
You are correct in your thinking except as what the others have stated. Think of an array as a sequence of data. You can even use the Reverse() method to apply that to your array. I would research more about arrays so you will understand different things you can do with an array and most importantly if you need to read or write them on the console, in a listbox, or a gridview from the text or csv file.
I suggest you add:
Console.ReadLine();
When you do this the application then will read like this:
2
5
7
20
55
in this particular line of code :
correct = Array.LastIndexOf(turns.ToArray(), false, 4, 0);
I get result correct = -1, well how is this even possible ?
turns[0] up to turns[3] are equal to false turns[4]=true and turns[5]=false is it possible to be caused because the last index i want to be looked up to is 4 and it has value different than the required one ?
The issue is with the last argument (count). This restricts the number of elements searched. You are restricting it to search 0 elements starting at index 4. Thus, it doesn't find anything.
Your count indicates searching 0 elements in the section.
correct = Array.LastIndexOf(turns.ToArray(), false, 4, 2);
Try this out:
correct = Array.LastIndexOf(turns.ToArray(), false, turns.Length, turns.Length);
What were you doing wrong:
never hard code array length (especially in your case, when the array is filled with values)
the first index is actually the starting search index from backwards, and the second index is actually the count, i.e. how many items to search (MSDN constructor clarification)
Update 1:
Made a mistake on the starting index and the count number. Updated the changes, thank you #Steve for pointing it out.
This question already has answers here:
Algorithm: how to find a column in matrix filled with all 1, time complexity O(n)?
(5 answers)
Closed 9 years ago.
I'm dealing with some problematic complexity question via my university:
Program input : A n x n Array[][] that is filled with either 0 or 1.
DEFINITION: Define k as a SINK if in the k row all the values are 0, and in the k column all the values are 1 (except [k][k] itself which needs to be 0)
Program output : Is there a k number that is a SINK? If so, returnk, else return -1.
Example :
On Arr A k=3 is a SINK, on Arr B there in no SINK, so -1 is returned.
The main problem with this task is that the complexity of the program must be below O(n^2) , I have managed to solve this with that complexity, going over the oblique line summing the rows&columns. I haven't find a way to solve this with O(logn) or O(n). Also the task prevents you from using another Array[] (Due to memory complexity). Can anyone drop any light on that matter? thanks in advance!
Just to make explicit the answer harold links to in the OP's comments: start yourself off with a list of all n indices, S = {0, 1, .., n-1}. These are our candidates for sinks. At each step, we're going to eliminate one of them.
Consider the first two elements of S, say i and j.
Check whether A[i, j] is 1.
If it is, remove i from S (because the i th row isn't all 0s, so i can't be our sink )
If it isn't, remove j from S (because the j th column isn't all 1s, so j can't be our sink)
If there're still two or more elements in S, go back to Step 1.
When we get to the last element, say k, check whether the k th row is all zero and the k th column (other than A[k,k]) are all ones.
If they are, k is a sink and you can return it.
If they aren't, the matrix does not have a sink and you can return -1.
There are n elements in S to begin with, each step eliminates one of them and each step takes constant time, so it's O(n) overall.
You mention you don't want to use a second array. If that really is strict, you can just use two integers instead, one representing the "survivor" from the last step and one representing how far into the sequence 0, 1, .., n-1 you are.
I've never seen this algorithm before and I'm quite impressed with it's simplicity. Cheers.