What is Innermost loop in imperfectly nested loops? - c

Helo, I'm a bit confused about the definition of an inner loop in the case of imperfectly nested loops. Consider this code
for (i = 0; i < n; ++i)
{
for (j = 0; j <= i - 1; ++j)
/*some statement*/
p[i] = 1.0 / sqrt (x);
for (j = i + 1; j < n; ++j)
{
x = a[i][j];
for (k = 0; k <= i - 1; ++k)
/*some statement*/
a[j][i] = x * p[i];
}
}
Here, we have two loops in the same nesting level. But, in the second loop which iterates over "j" starting from j+1, there is a again another nesting level. Considering the entire loop structure, which is the inner most loop in the code ?

Both j loops are nested inside i equally, k is the inner most loop

Lol I don't know how to explain this so i'll give it my best shot I recommend using a debugger! it may help you so much you won't even know
for (i = 0; i < n; ++i)
{
//Goes in here first.. i = 0..
for (j = 0; j <= i - 1; ++j) {
//Goes here second..
//Goes inside here and gets stuck until j is greater then (i- 1) (right now i = 0)
//So (i-1) = -1 so it does this only once.
/*some statement*/
p[i] = 1.0 / sqrt (x);
}
for (j = i + 1; j < n; ++j)
{
//Goes sixth here.. etc.. ..
//when this is done.. goes to loop for (i = 0; i < n; ++i)
//Goes here third and gets stuck
//j = i which is 0 + 1.. so, j == 1
//keeps looping inside this loop until j is greater then n.. idk what is n..
//Can stay here until it hits n.. which could be a while.
x = a[i][j];
for (k = 0; k <= i - 1; ++k) {
//Goes in here fourth until k > (i-1).. i is still 0..
//So (i-1) = -1 so it does this only once
/*some statement*/
a[j][i] = x * p[i];
}
//Goes here fifth.. which goes.... to this same loop!
}
}

I'd say that k is the inner-most loop, because if you count the number of loops required to reach it from the outside, it's three loops, and that's the most out of all four of the loops in your code.

Related

C insertion sort stuck in while loop

I'm writing a simple program to sort a small array but when I run my code for insertion sort the program just runs forever.
It's probably a problem with the while loop. I ran through the program on paper and looked over some other people's code but I can't figure out why it's not working.
void mySort(int d[], unsigned int n){
int i, j, k;
for (j = 1;j < n;i++){
k = d[j];
i = j-1;
while (d[i] > k && i >=0){
d[i+1] = d[i];
d[i] = k;
i = i - 1;
}
}
}
for (j = 1;j < n;i++){
You compare value j, but you increment value i.
If you Use a Debugger, you would immediately notice that the value j does not get updated, and you'd find your problem immediately!!
Always Use a Debugger
The error is in your for loop.
for (j = 1;j < n;i++){
So your terminating conditions of the for loop are that j >= n, except you never change j or n after this statement.
Try
for (j = 1;j < n;j++){

Can't Count - Number of Comparison Operations

So I have this segment of code that was given to me.
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++)
{
if (arr[j] < arr[i])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
I am trying to calculate the number of comparison operations that would occur if the code were to run.
There's the initial comparison all the way up to i=100. so there's 101 comparisons for the outer loop. The inner loop also has 101 loops, but that comparison within will only happen 100 times due to the j=100 will not have that comparison occurring.
I've made a tries but none of been the right answer so far.
I've had 101 x (101+100) = 20301 which is not the right answer.
I've searched for this on google and came up with a question identical to this but was answering how many assignment operations that occur which I was able to answer on my own. Which btw is 25201.
I got 20201.
#include <stdio.h>
int main(void) {
int i, j;
unsigned long count;
count = 0;
for (i = 0; ++count, i < 100; ++i) {
for (j = 0; ++count, j < 100; ++j) {
++count;
}
}
(void) printf("%lu\n", count);
return 0;
}
100 comparisons on the outer loop drive 101 + 100 comparisons on the inner loop. There is one more comparison on the outer loop to detect loop termination, so:
100 * (101 + 100) + 101 = 20201.
Instrumenting the program:
outer_cmps=0;
total_inner_cmps=0;
for (int i = 0; i < 100; i++) {
++outer_cmps;
inner_cmps=0;
for (int j = 0; j < 100; j++)
{
++inner_cmps;
if (arr[j] < arr[i])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
++inner_cmps;
}
++inner_cmps;
tota_inner_cmps += inner_cmps;
}
++outer_cmps;
total_cmps = outer_cmps + total_inner_cmps;
So that would be 100*200+100+1=20101
(100 times i, which runs the j loop 100 times, which performs 1 comparisson if (arr[j] < arr[i]) per loop, and one i loop that fails when i==100and 100 times j loop that fail when j==100)

continue statement inside nested for loop

I don't understand what exactly does the continue statement inside this for loop do. How is code any different if I remove it? Which lines does it skip if it's placed at the end of for loop?
int sum = 0, i, j, stop = 0;
for( i = 1; i <= 5 && !stop; i++)
{
for( j = 1; j <= 5 ; j++)
{
if (j%4 == 0)
{
stop = 1;
continue;
}
sum += i+j;
}
}
printf("%d\n", sum);
If you run this program the sum is going to be 15, and if you comment out countinue line then it's going to be 20.
It would be more clear if you would format the code. Let's consider the inner loop
for( j = 1; j <= 5 ; j++)
{
if ( j % 4 == 0)
{
stop = 1;
continue;
}
sum += i+j;
}
Thus as you see if j % 4 == 0 then statement
sum += i+j;
is skipped.
As for the code in whole then it has no any sense.:) It is a silly code.
In fact your code is equivalent to the following
int sum = 0, j;
for( j = 1; j <= 5 ; j++ )
{
if ( j != 4 ) sum += j + 1
}
printf("%d\n", sum);
So you will get sum 2 + 3 + 4 + 6 that is equal to 15.:)
The continue statement skips the remainder of the current loop. In the case of nested loops, it skips to the next iteration of the innermost loop.
In this case, if you didn't continue, you would execute sum += i+j; in every iteration, where it appears you only want it sometimes.
That being said, this is a very awkward loop to begin with. The whole stop variable is rather ill conceived from the get-go anyway.
The continue statement is used to start the next iteration of a loop,skipping everything in the loop,after the continue. In your case,once the execution of the program reaches the continue statement,then the next iteration of your inner loop starts,skipping whatever there was after the continue. It skips sum += i+j; as it is after the continue and the sum will not be added when j is 4 as j%4 will be 0. This is why you get 20 when you comment the continue and 15 when you uncomment it.
P.S: Your outer loop will execute only once as stop will be changed inside the if in your inner loop.
continue causes the enclosing for loop to begin the next iteration. As a more basic example, take the following code:
for(int i = 0; i < 50; i++)
{
if(i % 2 == 1) // If it's odd
continue;
printf("%d\n", i);
}
In this case, the continue statement will cause the for loop to immediately begin the next iteration if i is odd, hence this code will print the even numbers between 0 and 50.
int sum = 0, i, j, stop = 0;
for( i = 1; i <= 5 && !stop; i++)
{
for( j = 1; j <= 5 ; j++)
{
if (j%4 == 0) <===== is j divisible by 4 ?
{
stop = 1; <=== set stop flag, will continue for J loop
but stop next I loop and end the routine
continue; <==== skip the rest of the J loop for this itteration
}
sum += i+j;
}
}
printf("%d\n", sum);
http://msdn.microsoft.com/en-us/library/0ceyyskb.aspx explains the continue statement

Code to store indices of occurrences doesn't work

In the program that I'm writing, I currently have a for-loop that goes through an array, num[5], and checks to see if there are any 1's in that array, which looks like:
int counter = 0;
for (int i = 1; i <= 5; i++)
if (num[i] == 1)
counter++;
This works successfully, but I'm now trying to go through the array and see what the indices of the 1's in the program are. So, if I have 01001, I want to make an array that holds the positions of the 1's. The following is what I've tried so far:
int b[counter];
for (int k = 0; k <= counter; k++) {
for (i = 0; i <= 5; i++) {
if (num[i] == 1) {
b[k] = i;
}
}
}
but this doesn't produce the desired result. When I type the string in, say 1001, I get 444. Can someone tell me what I'm doing incorrectly?
For each value of k, for each occurrence of a 1, you're setting b[k] to the index of the 1. Thus each b[k] will have the index of the last 1.
Try:
int b[counter];
int k = 0;
for (i = 0; i <= 5; i++) {
if (num[i] == 1) {
b[k++] = i;
}
}
So, whenever it gets a 1, it assigns b[k] to the index and then increases k.
Then you should also use k, not counter, when trying to print out b.
The problem lies in this part of your code.
int b[counter];
for (int k = 0; k <= counter; k++) {
**for (i = 0; i <= 5; i++) {
if (num[i] == 1) {
b[k] = i;
}**
}
}
Suppose you get a 1 at the index 1 of the array as in 01001. You assign b[k] = 1;
This is perfectly valid. But as the loop continues you get another 1 at the index 4. Thus the command b[k] = 4; is again executed.
Note that your value of k is constant in both the statements and hence you get the array b as 44.
So what you need to do is break the inner for loop as soon as you get a 1.
Here is the modified code. You also need to keep a track of the iterator i and I have done that here using the variable- new_pos // new position.
int b[counter];
int new_pos=0; //to keep track of the iterator
for (int k = 0; k <= counter; k++) {
for (i = new_pos; i <= 5; i++) {
if (num[i] == 1) {
b[k] = i;
new_pos = i+1;
break;
}
}
}
The code provided by Dukeling is also perfect, but I am just giving another way to make your own code work.

What is the best way to loop through a 2D sub-array of a 2D array?

If I have a 2D array, it is trivial to loop through the entire array, a row or a column by using for loops. However, occasionally, I need to traverse an arbitrary 2D sub-array.
A great example would be sudoku in which I might store an entire grid in a 2D array but then need to analyse each individual block of 9 squares. Currently, I would do something like the following:
for(i = 0; i < 9; i += 3) {
for(j = 0; j < 9; j += 3) {
for(k = 0; k < 3; k++) {
for(m = 0; m < 3; m++) {
block[m][k] == grid[j + m][i + k];
}
}
//At this point in each iteration of i/j we will have a 2D array in block
//which we can then iterate over using more for loops.
}
}
Is there a better way to iterate over arbitrary sub-arrays especially when they occur in a regular pattern such as above?
The performance on this loop structure will be horrendous. Consider the inner most loop:
for(m = 0; m < 3; m++) {
block[m][k] == grid[j + m][i + k];
}
C is "row-major" ordered, which means that accessing block will cause a cache miss on each iteration! That's because the memory is not accessed contiguously.
There's a similar issue for grid. Your nested loop order is to fix i before varying j, yet you are accessing grid on j as the row. This again is not contiguous and will cache miss on every iteration.
So a rule of thumb for when dealing with nested loops and multidimensional arrays is to place the loop indices and array indices in the same order. For your code, that's
for(j = 0; j < 9; j += 3) {
for(m = 0; m < 3; m++) {
for(i = 0; i < 9; i += 3) {
for(k = 0; k < 3; k++) {
block[m][k] == grid[j + m][i + k];
}
}
// make sure you access everything so that order doesn't change
// your program's semantics
}
}
Well in the case of sudoku couldn't you just store 9 3x3 arrays. Then you don't need to bother with sub arrays... If you start moving to much larger grids than sudoku you would improve cache performance this way as well.
Ignoring that, your code above works fine.
Imagine you have a 2D array a[n][m]. In order to loop a subarray q x r whose upper right corner is at position x,y use:
for(int i = x; i < n && i < x + q; ++i)
for(int j = y; j < m && j < y + r; ++j)
{
///
}
For your sudoku example, you could do this
for(int i = 0; i<3; ++i)
for(int j = 0; j < 3; ++j)
for(int locali = 0; locali < 3; ++locali)
for(int localj = 0; localkj <3; ++localj)
//the locali,localj element of the bigger i,j 3X3 square is
a[3*i + locali][3*j+localj]

Resources