How to read nested for-loops? - c

I cannot understand what this for-loop does by reading the code. I know how a for-loop works though. By reading this code I literally gain no insight into what the program could be doing.
I'm coming from python to C, if that matters.
#include <stdio.h>
int main (void)
{
int numbers[10] = {1,0,0,0,0,0,0,0,0,0};
int i, j;
for (j = 0; j < 10; ++j)
for (i = 0; i < j; ++i)
numbers[j] += numbers[i];
return 0;
}
for (j = 0; j < 10; ++j)
This just means iterate through each element of the array. It is easy to understand.
for (i = 0; i < j; ++i)
numbers[j] += numbers[i];
This is much harder! I think it is because I cannot figure out in my head what j would be equal to. I cannot follow the two loops properly.
I would specifically like to know how I can read and understand this nested for-loop in C.
(I know what this snippet does because I compiled and ran the code.)

First of all, let's translate it into Python:
numbers = [1,0,0,0,0,0,0,0,0,0]
for j in range(10):
for i in range(j):
numbers[j] += numbers[i]
The outer loop iterates through all ten elements of numbers and, for each item, adds all previous elements in numbers to the current one. It's easier to follow if you add a few print statements.

for (j = 0; j < 10; ++j) doesn't mean "iterate through each element of the array". It means "for each value of j from 0 to 9, execute the code within the loop".
The code within the loop includes another loop:
for (i = 0; i < j; ++i)
numbers[j] += numbers[i];
So, for each value of j from 0 to 9, that inner loop will be executed. In effect, it would be like executing the inner loop sequentially 10 times:
for (i = 0; i < 0; ++i)
numbers[0] += numbers[i];
for (i = 0; i < 1; ++i)
numbers[1] += numbers[i];
for (i = 0; i < 2; ++i)
numbers[2] += numbers[i];
... and so on
(As a side note, the first execution of the inner loop does nothing, since 0 is not less than 0. So the initial value of the outer loop might as well be 1.)
To return to your original phrasing, if the outer loop essentially iterates over all elements of the array, the inner loop does a second iteration over all elements of the array prior to the current element in the outer loop.

Some times it is helpful to just write out what is happening along the way. Also, adding braces might help a little bit as well:
for (j = 0; j < 10; ++j)
{
for (i = 0; i < j; ++i)
{
numbers[j] += numbers[i];
}
}
(A) The first time through the outer loop, j will be zero, thus the inner loop will read:
for (i=0; i < 0; ++i)
because 0 is not less than 0, we skip the body of the inner loop (and numbers remains unchanged).
(B) The second time through the outer loop, j will be one, thus the inner loop will read:
for (i=0; i < 1; ++i)
So we will go through the body of the inner-loop once with i being zero, thus we will execute this
command; numbers[1] = numbers[1] + numbers[0]; (I expanded += for added clarity) which will now make the numbers array look like this: 1,1,0,0,0,0,0,0,0,0
(C) The third time through the outer loop, j will be two, thus the inner loop will read:
for(i=0; i < 2; ++i)
SO we will go through the body of the inner-loop twice with i being first zero, and then one. Thus
we will execute the following commands:
numbers[2] = numbers[2] + numbers[0];
numbers[2] = numbers[2] + numbers[1];
which will transform the numbers array into 1,1,2,0,0,0,0,0,0,0
and so on.
Hope this helps.

The jth element in the numbers array is the sum of all preceding elements in the array. Technically, the preceding elements gets added to the jth element, but numbers[j] is 0 to begin with.
When j equals 1,
numbers[1] = numbers[1] + numbers[0]
which makes numbers[1] == 1. (because i can only be 0 and numbers[0] is 1)
When j equals 2,
numbers[2] = numbers[2] + numbers[1] + numbers[0]
which makes numbers[2] == 2. (because i can be 0 and 1, and numbers[0] and numbers[1] are both 1)
When j equals 3,
numbers[3] = numbers[3] + numbers[2] + numbers[1] + numbers[0]
which makes numbers[3] == 4. (because i can be 0, 1 and 2, and numbers[2] is 2)
As such, any j - 1th (j > 1) element equals the sum of all of its preceding elements. Hence, as the loop goes on, the jth element would end up becoming the double of the j - 1th element.
At the end of the program, each value in the array would be 1 1 2 4 8 16 32 64 128 256

here is the value of your array after each outer loop
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0
1 1 2 4 0 0 0 0 0 0
1 1 2 4 8 0 0 0 0 0
1 1 2 4 8 16 0 0 0 0
1 1 2 4 8 16 32 0 0 0
1 1 2 4 8 16 32 64 0 0
1 1 2 4 8 16 32 64 128 0
1 1 2 4 8 16 32 64 128 256
as generated by this
#include <stdio.h>
#define SIZE_ARRAY 10
void show_numbers(int size_array, int index, int given_array[]) {
int i = 0;
for (; i < size_array; i++) {
printf("%3d ", given_array[i]);
}
printf("\n");
}
int main (void) {
// static const int size_array = 10;
int numbers[SIZE_ARRAY] = {1,0,0,0,0,0,0,0,0,0};
int i, j;
show_numbers(SIZE_ARRAY, 0, numbers);
for (j = 0; j < SIZE_ARRAY; ++j) {
for (i = 0; i < j; ++i) {
numbers[j] += numbers[i];
}
show_numbers(SIZE_ARRAY, j, numbers);
}
return 0;
}

Related

Length of a growing substring in matrix

Given a square matrix find the length of sub string that is growing for example.
matrix | result because of
5 |
1 2 3 4 5 |
2 5 2 5 9 |
7 8 9 0 1 --> 5 --> 1 2 3 4 5
0 0 0 0 0 |
2 3 6 1 2 |
I try to compare a[i][j] with a[i][j+1] and increment the counter but I think my problem is when the program is on the final elements and it does not increment the counter.
Here I have my code:
int main(){
int n;
scanf("%d",&n);
int i,j,a[n][n];
for(i = 0;i < n;i++){
for(j = 0;j <n;j++){
scanf("%d",&a[i][j]);
}
}
int max=-9999;
int counter;
for(i = 0;i < n;i++){
counter=0;
for(j = 0;j <n;j++){
if(a[i][j]<a[i][j+1]){
counter++;
}
if(counter>max){
max = counter;
}
}
}
printf("%d",max);
return 0;
}
For starters as the range of indices can not be negative then there is no sense to declare the variable max as having a negative value
int max=-9999;
It could be initialized at least like
int max = 0;
In this if statement
if(a[i][j]<a[i][j+1]){
there can be an access to memory beyond the allocated array when i and j are equal to n - 1 due to the expression a[i][j+1].
Also this if statement
if(counter>max){
max = counter;
}
should be moved outside the inner if statement.
And the variable count should be declared inside the outer loop
You could rewrite the inner for loop the following way
int counter=1;
for(j = 1;j <n;j++){
if(a[i][j-1]<a[i][j]){
counter++;
}
}
if(counter>max){
max = counter;
}

Why isn't there a space in the middle of my pyramid?

So I am trying to solve https://cs50.harvard.edu/x/2021/psets/1/mario/more/ this problem set from cs50.
It's taken me way too long to get this far (5-6 hours WITH help from youtube).
#include <cs50.h>
#include <stdio.h>
int get_positive_int(void);
int main(void)
{
int n = get_positive_int();
// Run a below loop until i is greater than n
for(int i = 0; i < n; i++)
{
// Run if statement on the same row until j is greater than n*2 + i+1
for(int j=0; j < n*2 + i+1; j++)
{
// Create a blank space in exact center of the pyramid
if(j + i - n == 0 || j + i - n == 1)
printf(" ");
//If the value of n-1 is less than the combined value of j and i, or
//if the value of i and n minus j is less than or equal to zero print #
else if ( j + i > n - 1 || i + n - j <= 0)
printf("#");
else
//otherwise print " "
printf(" ");
}
printf("\n");
}
}
Why doesn't the below create a two " " in the center of my pyramid?
if(j + i - n == 0 || j + i - n == 1)
printf(" ");
And why when I choose a value of 1 for n does the program not print anything?
What is this specific type of thinking/math called? I am having difficulty grasping it and I am not sure how to find information online because I don't know what it is called.
My output is below.
When N = 8
#######
#########
###########
#############
###############
#################
###################
#####################
The output I want is.
When N = 8
# #
## ##
### ###
#### ####
##### #####
###### ######
####### #######
######## ########
When I input a value of 1 I get.
What I want when I input 1 is,
# #
I'd like to know what specifically I did wrong in order to fix the issue myself, rather than the direct answer if possible.
First of all observe that your two for loops both start from 0. Thus at the beginning both i and j are equal to 0. Therefore, since n is a positive integer, both your if and else if clauses are evaluated as false and only the final else gets executed, which is printf(" ");
Now look at your pyramid. Your "pyramid" fills a space with n rows and 2*n + 2 columns. The first loop for (i = 0; i < n; i++) is for the rows, and it's correct, since there are n rows. Your second for loop, however, is faulty. It should be for (int j=0; j < n*2 + 2; j++).
Now when we look at the the i-th row we see that (remembering rows start from 0 because we started counting i from 0), you want to print n-1-i spaces, followed by i+1 # characters followed by 2 spaces, followed by i+1 # characters and finally followed by n-1-i spaces. So the "spaces" are when j < n-1-i (remember j also starts from 0), when j == n and j == n+1 and when j > n+2+i
This can be written as follows using if-else:
if ( j < (n-1-i) || j == n || j == n+1 || j > n+2+i) printf(" ");
else printf("#");
So the final code will look like:
#include <cs50.h>
#include <stdio.h>
int get_positive_int(void);
int main(void)
{
int n = get_positive_int();
for(int i = 0; i < n; i++)
{
for(int j=0; j < n*2 + 2; j++)
{
if ( j < (n-1-i) || j == n || j == n+1 || j > n+2+i) printf(" ");
else printf("#");
}
printf("\n");
}
}
Think about this mathematically. You have slope of -1, so we have j = -i + k. Our formula becomes k = i + j. If we have n = 5:
i j k
0 4 4
1 3 4
2 2 4
3 1 4
5 0 4
n = 6
i j k
0 5 5
1 4 5
2 3 5
3 2 5
4 1 5
5 0 5
so k = n - 1
That is first half, second is even easier, j = i + k, so k = j - i. It is positive slope moved by k. So for n=5
i j k
0 4 4
1 5 4
2 6 4
3 7 4
5 8 4
n = 6
i j k
0 5 5
1 6 5
2 7 5
3 8 5
4 9 5
5 10 5
look at that we have a match in both cases k = n - 1. So our formulas are
j = -i + n - 1 and j = i + n - 1.
Second in both cases we have maximum j at max(i) + k or in other words n - 1 + n - 1 so 2 * n - 2
so:
We got your lines.
Look closes and you will see how far your j has to go.
Here is the code:
// int get_positive_int(void);
int main(void)
{
int n = 5; //get_positive_int();
// Run a below loop until i is greater than n
for(int i = 0; i < n; i++)
{
// Run if statement on the same row until j is greater than n*2 + i+1
for(int j = 0; j < n * 2 - 1; j++)
{
// Create a blank space in exact center of the pyramid
if (j == n - i - 1 || j == n + i - 1)
printf("#");
else
//otherwise print " "
printf(".");
}
printf("\n");
}
}
Output:
....#....
...#.#...
..#...#..
.#.....#.
#.......#
Now you can optimize this to trim down number of inner loop execution by 25%, by looking at this. I do not need to go beyond the point where I print my second #, meaning beyond max(j) = j + 1 value of my second formula + 1 is because I still want to be able to go into loop, so we get maximum max(j) = (n + i - 1) + 1.
#include <stdio.h>
// int get_positive_int(void);
int main(void)
{
int n = 5; //get_positive_int();
// Run a below loop until i is greater than n
for(int i = 0; i < n; i++)
{
// Run if statement on the same row until j is greater than n*2 + i+1
for(int j = 0; j < n + i; j++)
{
// Create a blank space in exact center of the pyramid
if (j == n - i - 1 || j == n + i - 1)
printf("#");
else
//otherwise print " "
printf(".");
}
printf("\n");
}
}
output:
....#
...#.#
..#...#
.#.....#
#.......#
And if you notice, by thinking mathematically about this you save a lot of operations. For example in second for() loop, OP and other answer have more than 1 operations, where this has 1, in if/else both have more than 2 equality statements having, this one has 2.
NOTE: I used . instead of for demonstration.

What does this for loop do in C ?

#include <stdio.h>
int main(void) {
int i= 1, j = 1;
for (; j; printf("%d %d",i, j))
j = i++ <= 5;
return 0;
}
output-
2 13 14 15 16 17 0
Can anyone explain what is happening inside the loop? This question was asked in the interview process.
The code is equivalent to:
int main(void) {
int i=1,j=1;
while (j != 0) {
j = (i<=5);
i = i+1;
printf("%d %d",i,j);
}
return 0;
}
I think that its meaning and the output is evident now. Note that printf does not print any separator after the second number. It means that the two digit "numbers" in the output are printed by two successive invocations of printf each. If you use printf("%d %d; ",i,j); instead of printf("%d %d",i,j); the output will be:
2 1; 3 1; 4 1; 5 1; 6 1; 7 0;
Your code is the same as
#include <stdio.h>
int main() {
int i = 1, j = 1;
while (j > 0) {
if (i <= 5) {
j = 1;
} else {
j = 0;
}
i = i + 1;
printf("%d %d",i, j);
}
}
It should now be easy to understand.
De-obfuscated, the code is equivalent to this:
for(int i=1; i<7; i++)
{
printf("%d\t%d\n", i+1, (i+1) < 7);
}
What such a loop would be needed for, I have no idea.
Initially, i and j are 1 so condition for loop will be true and it will enter into the loop.
At j = i++<=5; statement first it will execute conditional operation and assign result of conditional operation (true = 1, or, false = 0) to j and increment i by one. After this, it will execute print statement from the loop which will print value for i (which is now incremented by one is 2) and j (will be 1 as the condition is true). This will continue until the i<=5 condition is true. Whenever i becomes greater than 5 j will be 0, breaking the loop.
To make the code and its output more clear rewrite the program the following way
#include <stdio.h>
int main(void)
{
for ( int i = 1, j = 1; j != 0; )
{
j = i++ <= 5;
printf("%d %d\n", i, j );
}
return 0;
}
The program output is
2 1
3 1
4 1
5 1
6 1
7 0
As the variable j is calculated as a result of this condtion
i++ <= 5
then it will be always equal to 1 except when i will be equal to 6 because for this value of i the condition is evaluted to false that is to 0 and this value is assigned to j.
So the last iteration of the loop is when i is equal to 6. In this case after this statement
j = i++ <= 5;
i will be equal to 7 and j will be equal to 0. These values are outputted in the last iteration of the loop.
7 0

Median windows in C

I wrote a code to find median filtering (median window). But, I can't make scannig to every number. What can I use instead of size in the for loops. When I use size it ensures just 5 Also, what about boundries ? What can I do for boundries ? Thank you for all appreciated answers. (I've opened new topic because users said that every topic is based on one question.If I did mistake,please delete the question, I will suffix the current question)
<size of array>
<size filter>
<data>
8
3
0 0 0 0 0 0 0 0
0 5 0 0 6 0 0 0
0 0 0 0 0 7 0 0
0 0 0 0 5 0 0 0
0 0 0 5 6 0 0 0
0 0 8 5 5 0 0 0
0 0 0 7 0 0 9 0
0 0 0 0 0 0 0 0
Output:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 5 5 0 0 0
0 0 0 5 5 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
#include <stdio.h>
int median(int a[100],int n);
int main()
{
int a[100][100];
int temp[100];
int i,j,k,count=0;
int sizefilter;
int sizearray;
scanf("%d", &sizearray);
scanf("%d", &sizefilter);
for(i = 0; i < sizearray; i++)
for(j = 0; j < sizearray; j++)
scanf("%d", &a[i][j]);
for(k = 0; k < sizearray; k++)
for(i = 0; i < sizefilter; i++)
for(j = 0; j < sizefilter; j++)
{
temp[count] = a[i][j];
count++;
a[i][j] = median(temp, count);
}
printf("\n");
printf("\n");
for(i = 0; i < sizearray; i++)
for(j = 0; j < sizearray; j++)
{
printf("%d ", a[i][j]);
if(j == sizearray-1)
printf("\n");
}
return 0;
}
int median(int a[100],int n)
{
int i,j,t;
int result;
/* Sorting begins */
for (i = 1 ; i <= n-1 ; i++)
{ /* Trip-i begins */
for (j = 1 ; j <= n-i ; j++)
{
if (a[j] <= a[j+1])
{ /* Interchanging values */
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
else continue ;
}
} /* sorting ends */
/* calculation of median */
if ( n % 2 == 0)
return result = (a[n/2] + a[n/2+1])/2 ;
else
return result = a[n/2 + 1];
}
There are some logical errors in your code:
When you filter, you need four nested loops: The outer two iterate over columns and rows of the matrix, the inner two iterate over columns and rows of the filter area. (That shouldn't be news to you; you have already been told that in an answer to your previous question.)
The constraints of the filter area are simple: The left and top indices must not fall below zero and the right and bottom indicies must be smaller than sizearray. If they are not, adjust them.
You need two arrays, the original array a and a second array that contains the filtered values. You cannot filter in-place, because if you look upwards and to the left, you'll see only filtered values, whereas your filter should always look at the original values.
Your wrong filtering loops apart: You never reset count, which you should reset, of course, for every median value you calculate. You also calculate the median in the inner loop, which is too often. A solution to this is to make count local to the loop that accumulates filter values and determines the median.
Your sorting has index errors. Instead of comparing i with i + 1, compare with ´i - 1. Your indices start from 1, soi - 1` will always yield a valid index.
You buble-sort the array, which is fine for small arrays, but slow in general. The <stdlib.h> has qsort, which may be useful to you for general sorting.
Your median indices are also off by one towards the right.
There are also some stylistic issues:
Please make a habit of using braces for code blocks for for, while and if. Only very trivial code blocks in the innermost scope can be written without braces. In your case, a lot has to be done "between" the loops, and having braces there makes it easy to add stuff.
Yor variable result in median is superfluous. You assign it and then immediately lose the variable itself, because you return. Just returning is enough.
Below is a version of your code that gives the desired output:
#include <stdint.h>
#include <stdio.h>
int min(int a, int b)
{
return a < b ? a : b;
}
int max(int a, int b)
{
return a > b ? a : b;
}
int median(int a[], int n)
{
int i, j;
for (i = 1 ; i < n ; i++) {
for (j = 1 ; j < n ; j++) {
if (a[j] < a[j - 1]) {
int t = a[j];
a[j] = a[j - 1];
a[j - 1] = t;
}
}
}
if (n % 2) return a[n / 2];
return (a[n / 2 - 1] + a[n / 2]) / 2 ;
}
int main()
{
int a[100][100];
int b[100][100];
int temp[100];
int i, j, ii, jj;
int sizefilter;
int sizearray;
scanf("%d", &sizearray);
scanf("%d", &sizefilter);
for(i = 0; i < sizearray; i++) {
for(j = 0; j < sizearray; j++) {
scanf("%d", &a[i][j]);
}
}
for(i = 0; i < sizearray; i++) {
for(j = 0; j < sizearray; j++) {
int imin = max(0, i - sizefilter / 2);
int imax = min(sizearray, i + sizefilter / 2 + 1);
int jmin = max(0, j - sizefilter / 2);
int jmax = min(sizearray, j + sizefilter / 2 + 1);
int count = 0;
for (ii = imin; ii < imax; ii++) {
for (jj = jmin; jj < jmax; jj++) {
temp[count] = a[ii][jj];
count++;
}
}
b[i][j] = median(temp, count);
}
}
for(i = 0; i < sizearray; i++) {
for(j = 0; j < sizearray; j++) {
printf("%3d", b[i][j]);
}
printf("\n");
}
return 0;
}

Multidimensional Array Printing Gives Something Different

#include <stdio.h>
int main(int argc, char **argv) {
int x[5][5] = {{0,1,2,3,4},{5,6,7,8,9}};
for (int i = 0; i < 4; i++) {
for (int j = 0; i < 4; i++) {
printf("%d\n", x[i][j]); } }
return 0; }
This was supposed to give me: 0 1 2 3 4 5 6 7 8 9
And the result is: 0 5 0 0
And then, when I change them to chars:
#include <stdio.h>
int main(int argc, char **argv) {
char x[5][5] = {{'0','1','2','3','4'},{'5','6','7','8','9'}};
for (int i = 0; i < 4; i++) {
for (int j = 0; i < 4; i++) {
printf("%d\n", x[i][j]); } }
return 0; }
I get 48 53 0 0.
Why? The code is pretty clear for me, but it seems that is happening something obscure on background (Or my brain works in a very "pythonic" way...)
Like #Keith Thompson said, you didn't initialize all 25 elements. So the remaining elements are initialized to 0. As a result, the data will be stored this way:
0 | 1 | 2 | 3 | 4 // Row 0
5 | 6 | 7 | 8 | 9 // Row 1
0 | 0 | 0 | 0 | 0 // Row 2
0 | 0 | 0 | 0 | 0 // Row 3
0 | 0 | 0 | 0 | 0 // Row 4
You only initialized the first two rows of your array. This is the reason why you got 0 5 0 0 as your output.
To get the correct output, you need to loop through the first two rows of your array.
Steps to fix this :
First
You need to change your first for-loop from:
for (int i = 0; i < 4; i++)
to
for (int i = 0; i < 2; i++)
Reason: Because you only want to loop through the first two rows (row 0 and row 1).
Second
You need to change your second for-loop from:
for (int j = 0; i < 4; i++)
to:
for (int j = 0; j < 5; j++)
Reason: You need variable j for your loop condition, not i. You also need to change from 4 to 5; because in an array, the index starts with 0. So, the indexes of each columns are 0,1,2,3,4 , respectively.
To sum up, your code supposed to be...
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d\n", x[i][j]);
}
}
Additionally, when you are changing to char x[5][5], you need to use %c, to print a character, instead of %d.
Moreover, the reason you are getting weird numbers like 48 because when you print a char with %d, you are actually printing its ASCII values. Referring to the ASCII table below, number 48 represents character '0'.
Image from http://www.asciitable.com/
for(i = 0 ; i < 2 ; i++)
for(j = 0 ; j < 5 ; j++)
printf("%d\n",x[i][j]);
i dont know why you initialized only 2 1-d arrays. but changing the bounds in the for loop should suffice your needs

Resources