Need an explanation on how this code works - c

I'm learning C in college and I don't understand this piece of code that my professor wrote and it has no explanation (I know it adds a random number from 0 to 99 to next array element but don't know how)
srandom(time(NULL));
for(i = 0; i < n; i++)
a[i] = i == 0 ? random() % 100 : a[i-1] + random() % 100;
Though it works as intended, I would just like to understand how it adds numbers to next array element without "+=" or something like that.

You can rewrite it like this:
for(i=0;i<n;i++) {
if (i == 0) {
a[i] = random()%100;
} else {
a[i] = a[i-1] + random()%100;
}
}
So, you see that the value at a[1] is a[0] + random()%100 and so on. The if is needed because when i is 0, you haven't a previous values to use (a[-1] would be an error). The ternary operator condition ? a : b can be read as "if condition is true, a; else b".

You can look at it on this way:
srandom(time(NULL));
for (i = 0; i < n; i++){
if (i == 0){
a[i] = random() % 100; // random number module 100 will give number between 0 and 99 inclusive
}
else{
a[i] = a[i - 1] + random() % 100; // a[i] will get value equal to sum of previous array value a[i - 1] and new random number between 0 and 99
}
}
In for loop you have i++ which is increasing index by one.

Related

Need more Efficient way to read subarrays

The problem statement asks the number of such subarrays where i < j < k, such that sum of any two numbers should be greater than or equal to the third in the subarray:
What I did:
I ran a loop from i=0 till n-2:
and the basic logic I used was if the first two elements in the sorted subarray are greater than or equal to the maximum, then all pairs will be greater than any element. and every time I get the subarray, I add the next element into it and set those three variables again. Am passing 15/20 TCs other am getting TLE:
Constraints:
1<=n<=10^5
1<=ai<=10^9
for(int i=0;i<n-2;i++)
{
int r=i+2;
vector<int> temp(inp.begin()+i,inp.begin()+r+1);
sort(temp.begin(),temp.end());
max_elem=temp[1];min_elem=temp[0];
int maximum=temp[temp.size()-1];
//cout<<max_elem<<" "<<min_elem<<"\n";
while(r<n && max_elem+min_elem >= maximum)
{
//cout<<max_elem<<" "<<min_elem<<" "<<inp[r]<<"\n";
cnt++;
r++;
if(inp[r]<min_elem) {max_elem=min_elem;min_elem=inp[r];}
else if(inp[r]<max_elem) max_elem=inp[r];
else if(inp[r]>maximum) maximum=inp[r];
}
}
cout<<cnt<<"\n";
Sample TC:
I1:
5
7 6 5 3 4
O1:
6
Explanation:
6 subarrays fulfill the conditions: (7,6,5),(7,6,5,3),(7,6,5,3,4),(6,5,3),(6,5,3,4),(5,3,4).
I2:
5
1 2 3 5 6
O2:
3
Explanation:
(1,2,3),(2,3,5),(3,5,6) --(NOTE: 1,2,3,5 isn't the ans coz 1+2 < 5 )
A naive approach to do this is this is as the following. Your logic is correct and it is what I implemented. I changed the sort (NlogN) with a single pass (N) finding only the 2 smallest and largest numbers. I haven't compiled the code and not sure it works as intended. It has the overall complexity of (N*N*N).
Execution time can be improved by doing some extra checks:
min1 + min2 >= maxcondition can be checked after each inner (k) loop, breaking if it violates for single case.
If condition is not satisfied for say subarray 4-7, there is no need to check any other substring including 4-7. By storing violating cases and checking against them before each loop, overall execution time can be improved.
int min1;
int min2;
int max;
int count = 0;
for(int i = 2; i < n; i++){
for(int j = 0; j < i - 2; j++){
max = -1;
min1 = min2 = 1000000000;
for(int k = j; k <= i; k++){
if(inp[k] > max)
max = inp[k];
if(inp[k] < min1){
min1 = inp[k];
continue;
}
if(inp[k] < min2){
min2 = inp[k];
}
}
if(min1 + min2 >= max)
count++;
}
}
There might be some bugs, but here is the general idea for a O(n log n) solution:
We keep a windows of elements from startIdx to endIdx. If its a valid subarray, it means we can expand it, we can add another element to it, so we increase endIdx. If its not valid, it wouldnt be valid no matter how much we expand it, so we need to reduce it by increasing startIdx.
pseudocode:
multiset<int> nums;
int startIdx = 0, endIdx = 0;
int sol = 0;
while(endIdx != inp.size()) {
if (endIdx - startIdx < 3) {
nums.add(inp[endIdx]);
endIdx++;
} else {
if (nums.lowestElement() + nums.secondLowestElement() < nums.highestElement()) {
nums.remove(nums.find(inp[startIdx]));
startIdx++;
} else {
sol += endIdx - startIdx - 2; // amount of valid subarrays ending in inp[endIdx - 1]
nums.add(inp[endIdx]);
endIdx++;
}
}
}

How to find if there is a common difference between integers in an array?

Lets say that the users input is 7 10 12 14 16 20 25. I want the output to be a set of numbers in ascending order whose difference is all the same. So for this case it would be: 12,25,7,20 OR 10,14,16,20. Notice how in both cases their difference is the same and theres at least 4 numbers in the output. How do i do this?
I'm trying to find if there is a common difference between the integers in the array. I first thought that it would be better to sort them in ascending order and then if sorted_array[1] - sorted_array[0] = sorted_array[2] - sorted_array[1] then theres a common difference. But then it doesnt work if the numbers are for example 4 5 12 13 16 20 27 28 where theres a common difference between [12,5], [20,13], [27,20]
int r = 0;
int l = 0;
while (r < n) {
if (arr_days4[r] - arr_days4[l] == arr_days4[r+1] - arr_days4[l+1]) {
sequence_difference++;
r++;
i++;
}
else if(arr_days4[i] - arr_days4[r] > arr_days4[r + 1] - arr_days4[l+1]){
l++;
}
else{
r++;
}
printf("\n%d", sequence_difference);
}
When I try to print sequence_difference it gives me 32767...Can anyone help?
first of all you should clear the requirement or specify the provided input and the output you want.
but seeing your code there's many mistakes i can figure out
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (array[i] > array[j]) {
a = array[i];
array[i] = array[j];
array[j] = a;
}
}
}
the inner loop must iterate n-1 times because of at last pass i will exceed n if you don't do this.
next error is in your while loop you have used i which is having value n becuase of upper for loop.
so try to look at these mistakes.
for more info you can check

A for loop in C using an array

I've created an array named a that can hold 100 double values,
double a[100];
I set the first element of the array a to NUM, which is a symbolic constant defined early in my code.
a[0] = NUM
I'm curious as to how I would write a for loop that sets each remaining value of a to the value of the preceding element plus 0.1. For example, the second element in the array is the first plus 0.1. I've tried doing
for(i=1; i<=99; i=+0.1)
But I think something is wrong with my initialization of i
Use i to index the array, not to store the value you should put on the array. Remember you can use expressions to access the array, like a[i - 1]
for (i = 1; i < 100; i++)
a[i] = a[i - 1] + 0.1;
int i;
for(i = 0; i < 100; i++)
a[i] = NUM + 0.1 * i;
dont forget to tell the type int !
int i = 0;
for(i = 0; i < 100; i++){
if (i == 0)
a[i] = NUM;
else
a[i] = a[i - 1] + .1;
}
Your array definition includes the step. So your array would run about 1000 times, at 1, 1.1, 1.2, but a[1.1] isn't a valid index of your array. Use i to index the array, and then retrieve the previous value to set the next.
From your question I can understand that this is one of your first program in C/C++, so I think that you need to start from basic things and learn how to do it properly, before doing it elegantly.
http://ideone.com/RGZgXL
for(i = 0; i < ARRAY_SIZE; i++) {
if(i == 0) { // if we are on the first element, set it to NUM
array[i] = NUM;
} else { // otherwise make the sum
array[i] = array[i-1] + STEP;
}
}
In the link you'll find the code and some comments that I hope will help you in understanding it.
Cheers

cyclic permutation in O(1) space and O(n) time

I saw an interview question which asked to
Interchange arr[i] and i for i=[0,n-1]
EXAMPLE :
input : 1 2 4 5 3 0
answer :5 0 1 4 2 3
explaination : a[1]=2 in input , so a[2]=1 in answer so on
I attempted this but not getting correct answer.
what i am able to do is : for a pair of numbers p and q , a[p]=q and a[q]=p .
any thoughts how to improve it are welcome.
FOR(j,0,n-1)
{
i=j;
do{
temp=a[i];
next=a[temp];
a[temp]=i;
i=next;
}while(i>j);
}
print_array(a,i,n);
It would be easier for me to to understand your answer if it contains a pseudocode with some explaination.
EDIT : I came to knpw it is cyclic permutation so changed the question title.
Below is what I came up with (Java code).
For each value x in a, it sets a[x] to x, and sets x to the overridden value (to be used for a[a[x]]), and repeats until it gets back to the original x.
I use negative values as a flag to indicate that the value's already been processed.
Running time:
Since it only processes each value once, the running time is O(n).
Code:
int[] a = {1,2,4,5,3,0};
for (int i = 0; i < a.length; i++)
{
if (a[i] < 0)
continue;
int j = a[i];
int last = i;
do
{
int temp = a[j];
a[j] = -last-1;
last = j;
j = temp;
}
while (i != j);
a[j] = -last-1;
}
for (int i = 0; i < a.length; i++)
a[i] = -a[i]-1;
System.out.println(Arrays.toString(a));
Here's my suggestion, O(n) time, O(1) space:
void OrderArray(int[] A)
{
int X = A.Max() + 1;
for (int i = 0; i < A.Length; i++)
A[i] *= X;
for (int i = 0; i < A.Length; i++)
A[A[i] / X] += i;
for (int i = 0; i < A.Length; i++)
A[i] = A[i] % X;
}
A short explanation:
We use X as a basic unit for values in the original array (we multiply each value in the original array by X, which is larger than any number in A- basically the length of A + 1). so at any point we can retrieve the number that was in a certain cell of the original array by array by doing A[i] / X, as long as we didn't add more than X to that cell.
This lets us have two layers of values, where A[i] % X represents the value of the cell after the ordering. these two layers don't intersect through the process.
When we finished, we clean A from the original values multiplied by X by performing A[i] = A[i] % X.
Hopes that's clean enough.
Perhaps it is possible by using the images of the input permutation as indices:
void inverse( unsigned int* input, unsigned int* output, unsigned int n )
{
for ( unsigned int i = 0; i < n; i++ )
output[ input[ i ] ] = i;
}

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.

Resources