Understanding multiple conditions in a C loop - c

There is a piece of C code
int i, j = 0;
for (i = 0, j = n-1; i < n; j = i++) {
// array operations
}
that I'm trying to convert into Lua code
local j = n-1
for i = 1, n do -- arrays are 1-based in Lua
-- array operations
j = i+1
end
but for some reason Lua code doesn't work. Am I getting that C loop right?

Imagine an array as a circular buffer. i is the current item and j is always the previous one:
n = 5
local j = n
for i = 1, n do -- arrays are 1-based in Lua
-- array operations
io.write('i=', i, ' j=', j, '\n')
j = i
end
Demo:
i=1 j=5
i=2 j=1
i=3 j=2
i=4 j=3
i=5 j=4

I do not know Lua but what the C code does is:
At every iteration:
Assign i to j: j = i;
Then increment i by 1: i = i+1;
Looks like your Lua code should be j = i instead of j = i+1

No, j is always one less than i unless i equals 0, then j is n-1. So j = i+1 should probably be j = i as i will be increased in the next iteration.
I don't know Lua so I can't be sure.

Probably not best to transform it into a lua for loop; use a while loop:
local i , j = 0 , n-1
while i < n do
--array operations
j = i
i = i + 1
end
Not that the code makes alot of sense.... if you want to convert to 1 based indexing as well use i , j = 1 , n and i<=n

Related

Why does this second loop have no initialization? And why does it print five stars?

This program produces this output:
*******
*****
***
*
Here's the code:
#include <stdio.h>
int main(void)
{
int i, j;
for (i = 1; i <= 5; i++)
{
for (j = 1; j < i;j++)
printf(" ");
for (; j <= 8 - i;j++)
printf("*");
printf("\n");
}
return 0;
}
What's the meaning of for (; j <= 8 - i;j++)? There is no initialization step and also don't understand why there is only five * on the second line.
For loops don't actually need to have an initialization statement. Many loops choose to include one, but it's not strictly necessary. Consequently, you can think of that loop as saying "we don't need to do anything special here for initialization."
As for why there are five stars on the second line, let's look at this part of the code:
for (j = 1; j < i;j++)
printf(" ");
for (; j <= 8 - i;j++)
printf("*");
On the second iteration, i is equal to 2. When the first loop runs, it will print out a single space character. The loop stops running when j < i is no longer true, so when it finishes running, the value of j will be 2. Therefore, the second loop will run for j =2, 3, 4, 5, 6, stopping when j = 7. That's why you see five stars.
Hope this helps!
What's the meaning of for (; j <= 8 - i;j++)?
That for takes the last (known) value of j used in the program
for (; j <= 8 - i;j++)
printf("*");
Here there is no need for initialization of j as value of j comes from previous for loop.
First case i=1 and j=1 but condition in loop is false and j increments to 2. And this value goes in innermost loop which runs till j=7.
That loop is using the j variable from the for loop directly above it. Each iteration of it is shorter by 2; one from the beginning, and one from the end. That is how it maintains the text centrally on the screen.
So, the first iteration at i=1 will not print any " ". It will then print 7 *, from j values of 1-7.
The second iteration at i=2 will print one " ", followed by 5 *, from j values of 2-6.
Each iteration subsequently follows this pattern.
Okay, j is initialized in the outer most block with respect to the for loops so now j is accessible from all the for loop (or any other loop).
it uses the last modified(incremented) value by the outermost for loop.
i think you can figure it now .
just figure out it by using copy pen and create a matrix for the for loop variables.
it will surely improve your programming skills.
Happy Coding.
you can try this:
variations in for loop in C
#include <stdio.h>
int main(void)
{
int i, j;
for (i = 1; i <= 5; i++) **1**
{
for (j = 1; j < i;j++) **2**
printf(" ");
for (; j <= 8 - i;j++) **3**
printf("*");
printf("\n");
}
return 0;
}
You will find that the variable j does not need to be initialized in loop 3 as it has been initialized in loop 2, and it is within the scope of the local block (j exists within loop 1, and need'nt to be initialised after loop 2).
With regard to your second query,
consider the second iteration of loop1 where i=2. When loop2 completes its execution at this point, j=2. Now consider loop3, where j is 2 (as previously established) and it executes until j is less than or equal to 8-i(8-i=8-2= 6).
So it prints a star for j = 2,3,4,5,6 = 5 stars.
Replace
printf("*");
by
printf("%d", j)
and look how the value of j is changing. This could explain how it works.

Why is this not a infinite loop?

int main() {
int i,j=6;
for(;i=j;j-=2)
printf("%d",j);
return 0;
}
This piece of code gives output 642
please explain me why this loop doesn't run infinitely and stops when j is non-positive
When j becomes 0 the expression i=j evaluates to 0. Hence, the loop terminates.
Note that if j were to start as negative number ( e.g. -1 )or as an odd number (e.g. 5), then the condition will never evaluate to 0 and will result in an infinite loop.
In C 0 is evaluated as false and non-zero as true. The controlling expression i = j becomes false when j = 0 and the loop will terminate.
The loop will go infinite if you change your program to
int i, j = 6;
i = j;
for(; i == j; j -= 2, i = j)
printf("%d",j);
for(;i=j;j-=2)
This is a for loop with no initial code, which on every iteration will assign j to i as the condition check, then at the end decrement j by 2. Note that the value of an assignment expression is the value assigned, hence your i = j expression will yield the value of j.
So, what will happen cycle by cycle is as follows:
Assign i = 6, j = 6
Nothing for the initial for loop statement
i = j (6)
Print j (6)
j -= 2
i = j (4)
Print j (4)
j -= 2
i = j (2)
Print j (2)
j -= 2
i = j (0)
The above expression evaluated to 0, hence false, hence the loop terminates.

Counting sort algorithm doesn't work in C

My task is to make a counting sort algorithm in C. The compiler doesn't make any reasons to not make a program, but it doesn't work. While debugging debugger shows the second for contain as an error so I am asking where is an error because I can't see it.
const int k = 77;
const int n = 1000;
int T[n];
int Tp[n];
int TPom[k];
int i;
for(i = 0 ; i < k ; i++)
TPom[i] = 0;
for(i = 0 ; i < k ; i++)
TPom[T[i]]= TPom[T[i]]+1;
for(i = 1 ; i < k ; ++i)
TPom[i] += TPom[i-1];
for(i = n-1 ; i >= 0 ; --i)
Tp[--TPom[T[i]]] = T[i];
There are a few problems, so I'll give you some hints:
The second loop is wrong. Hint: how many elements does T contain?
The third loop is not wrong, but is unnecessary. I personally find it easier to think about the algorithm without this loop (you might disagree).
The final loop is wrong. You want to iterate over the values 0 through k-1, populating Tp. The loop shouldn't even reference T.

C loop complexity

I'm preparing for an exam and these are some of problems from last year's tests. The task is to calculate both exact and asymptotic complexity. How would you solve it? Universally, if possible.
for ( i = j = 0; i < n; j ++ ) {
doSomething ();
i += j / n;
j %= n;
}
for ( i = 0; i < 2 * n; i += 2 )
for ( j = 1; j <= n; j <<= 1 )
if ( j & i )
doSomething ();
for (i = 0; i < 2*n; i++) {
if ( i > n )
for (j = i; j < 2 * i; j ++ ) doSomething();
else
for (j = n; j < 2 * n; j ++ ) doSomething();
}
Thanks in advance
My solution for the third loop is
t(n) = [ (n-1)*n + ((n-1)*n)/2 ] *D + [ n^2 +n ] *D + [ 2n ]*I
so it is in O(n^2) given that doSomething() has a constant time
and that i and j are integers.
The second term ( [ n^2 +n ] *D ) is fairly easy.
The loop
for (j = n; j < 2 * n; j ++ ) doSomething();
gets called while i <= n so it will be called n+1 times, since it starts from 0.
The loop for (j = n; j < 2 * n; j ++ ) calls doSomething() n times, so we have (n+1)*n*D = [n^2+n] *D. I assume that doSomething() has a constant time which is equal to D
The first term is a little bit more complex.
for (j = i; j < 2 * i; j ++ ) doSomething();
gets called when i>n so it will be called n-1 times.
The loop calls doSomething() i times.
The first time it gets called n+1, the second time ´n+2´ and so on until it is 2n-1 which is equal to n + (n-1).
So we get a sequence likes this {n+1, n+2, n+3, ... , n+(n-1)}.
If we sum up the sequence we get n-1 times n and the sum 1+2+3+...+ (n-1).
The last term can be solved with the "Gaußsche Summenformel" (sorry I don't have the English name for it but you can see the formula in the German wiki link) so it is equal to ((n-1)*n)/2
So the first term is (n-1) * n + ((n-1)*n)/2 *D
And the last term is therefor the if statement which is called 2*n*I, where I is the time to execute the If statement.
Well, the question here is, for all three loop structures, how the amount of iterations changes in proportion to n, right? so let's look at the loops. I'll omit the first one, since you solved it already.
for ( i = 0; i < 2 * n; i += 2 )
for ( j = 1; j <= n; j <<= 1 )
if ( j & i )
doSomething ();
the outer for loop obviously runs exactly n times. the inner loop runs log_2(n) times, because of the bitwise shift operation. The if clause runs in constant time, so the entire loop is in O(n * log_2(n)), assuming that doSomething() is in constant time as well.
Does that make it clearer? :)
As per request, I will explain how I came to the result that the first loop is equal to a construction like this:
int i, j;
for (i=0; i < n; i++) {
for (j=0; j <= n; j++) {
doSomething();
}
}
First of all, I must admit that before I really thought about it, I just wrote a little sample program including the first of the three for-loops that prints out i and j during the iteration. After I've seen the results, I was thinking about why the results are like this.
In the comment, I forgot to add that I defined n=200.
Explanation
We can say, that although j is incremented regularly every step in the iteration, it will never exceed a value of n. Why? After n iterations, j==n. It will be set to 0 in the statement j %= n after i has been incremented. In the statement i += j / n, i will be incremented by 0 n-1 times, and at the nth time, it will be incremented by 1. This starts all over again until i >= n.

Why is this reverse string function giving a seg fault?

I want to make a reverse string function and I have done it like this:
void reverse_str(char s[]) {
int i, j;
char ch;
for(i = 0, j = strlen(s) - 1; i < j; i++, j--) {
ch = s[i];
s[i] = s[j];
s[j] = ch;
}
return ;
}
But for some reason when I change i < j to i != j I get a segmentation fault. This also happens when i and j are pointers. Why?
It's almost certainly because i and j pass each other (whether they're indexes or pointers is irrelevant here). For example, any string with an even number of characters will have this problem.
Consider the following sequence for the string drum:
0123 <- indexes
----
s = "drum", i = 0, j = 3, swap d and m.
s = "mrud", i = 1, j = 2, swap r and u.
s = "murd", i = 2, j = 1, swap u and r, oops, we've passed each other.
s = "mrud", i = 3, j = 0, swap m and d.
s = "drum", i = 4, j = -1, swap who knows what, undefined behaviour.
Note that for a string with an odd length, you won't have this problem since i eventually equals j (at the middle character).
The i < j check also fixes this problem since it detects both equality of pointers and the pointers passing each other.
If j starts as odd (when s has an even number of characters), then i and j will never be equal - so the loop will continue outside the bounds of the array s.
For example, if i = 0 and j = 1 when first evaluated, then the next loop will have i = 1 and j = 0 (note still not equal) and the third loop will have i = 2 and j = -1, hence the error.
How are you calling the function? In other words, are you sure that the character array you're passing in is writable?
If the memory is okay, it probably crashes when you use != since there's no guarantee that that happens when you expect it to.
if strlen(s) - 1 is odd then your condition i!=j will always be true.

Resources