Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 months ago.
Improve this question
I was studying the following piece of code and tried to write on paper the values that i and j receive at each step but I don't understand why at the 4th step, j's value decreses from 3 to 2 as there is no decrement operator (as far as I understand it):
#include<stdio.h>
int main() {
int i, j, n;
int v[] = {
-7,
29,
76,
8
};
n = sizeof(v) / sizeof(int);
for (i = 0, j = 1; n > 1 && i < n;
(v[i] > v[j]) && (v[i] = v[i] + v[j] - (v[j] = v[i])), i++, j = j < n - 1 ? --i, j + 1 : i + 1)
printf("i=%d j=%d \n", i, j);
for (i = 0; i < n; i++) printf("%d\t", v[i]);
printf("\n");
return 0;
}
Output:
i=0 j=1
i=0 j=2
i=0 j=3
i=1 j=2
i=1 j=3
i=2 j=3
i=3 j=4
i=3 j=5
i=3 j=6
-7 8 29
Tried to understand how i and j receive their value.
The code is invalid:
v[i] = v[i] + v[j] - (v[j] = v[i]) assigns to v[j] and reads from v[j] at the same time. You can't do that.
When j=4 then accessing v[j] is invalid. v has 4 elements, you can access up to index 3.
why at the 4th step, j's value decreses from 3 to 2
From step 3: i is incremented i++, so i=1. Then j is just assigned value 2 from the ternary expression false branch. i + 1 is 2, so y=2.
> i=0 j=3 n=4
..., i++, j = j < n - 1 ? --i, j + 1 : i + 1
> i++ -> i=1
..., j = j < n - 1 ? --i, j + 1 : i + 1
> j < n - 1 -> 3 < 3 -> false
j = i + 1
> i + 1 -> 1 + 1 -> 2
> j = 2
I hope this will help:
The first "part" of for statement sets the initial values of i and j (0 and 1 respectively).
The third "part" of for statement is responsible (in your code sample) for all other changes of i and j values. This part is a comma expression (with three subexpressions), that is evaluated from left to right. These subexpressions are (in order of evaluation):
(v[i] > v[j]) && (v[i] = v[i] + v[j] - (v[j] = v[i]))
That means: If (v[i] > v[j]), then give v[j] the previous value of v[i] [part: (v[j] = v[i])] and v[i] the value of v[j] (part: v[i] = v[i] + v[j] - (v[j] = v[i]), note that v[j] = v[i] evaluates to v[i]). In other words: If v[i] is greater than v[j], then swap the values of v[i] and v[j].
i++
The simplest part: Increment i value by one.
j = j < n - 1 ? --i, j + 1 : i + 1
Here is used the tertiary operator (?:). If (j < n - 1) is true, then "--i, j+1" (another comma expression) is evaluated (from left to right) and its value (the value of last/right part, ie: j+1) is assigned to j. In other words: the value of i is decremented by one and j is incremented by one, if j is less than n-1. If j is not less than n-1, then the last part of tertiary operator, i+1, is assigned to j.
By the way: I think that the last line of your output must be: "-7 8 29 76" and not "-7 8 29". So, this piece of code sorts v[] array.
Related
#include <stdio.h>
int main()
{
int i;
int j;
int k;
for(i = 1, j = 0, k = 3 ; i <= 5, j <= 6, k > 1 ;i++, j++, k--);
{
printf("%d%d%d", i, j, k);
}
}
Why is this program printing 321 instead of 212?
I get 321 when I execute the program but I think it should be 212. I cannot understand why it is printing 321.
That's because you have a semicolon at the end of the for loop, so the code runs essentially like this:
// first you increment i,j and decrement k until k is 1, so twice
for(i = 1, j = 0, k = 3 ; i <= 5, j <= 6, k > 1 ;i++, j++, k--) {}
// then you print the values
printf("%d%d%d", i, j, k);
You have 2 bugs.
The first was already mentioned and should also be reported by your compiler.
You have a stray semicolon after your for loop.
The second is that your condition is rather strange: i <= 5, j <= 6, k > 1
Relational operators have higher precedence than coma operator. That means this condition is same as (i <= 5), (j <= 6), (k > 1) which again is same as k>1.
If you want to have all the relational operands evaluate to true, you must add logical operator: i <= 5 && j <= 6 && k > 1
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.
In an array A[1...n] of positive integers, you are to count all quadruples in array satisfying:
A[i] + A[j] + A[k] = A[l] where 1 <= i < j < k < l <=n
I tried many things but could not come to a solution better than O(n^3logn)
Can we solve it in O(n^3) or O(n^2) satisfying the ordering constraint of indices?
Why not O(n^2)? If we have
A[i] + A[j] + A[k] = A[l]
where 1 ≤ i < j < k < l ≤ n
and we hashed all
A[i] + A[j] pairs
where 1 ≤ i < j < n - 1
then we can iterate:
l = n
k = n - 1
check if A[l] - A[k] is in the hash
now update on each element as we descend:
j = n - 2
remove each instance of A[j] + A[i] in the hash
where 1 ≤ i < j
for each instance of A[l] - A[j]
where j < l < n
check if a value exists in the hash
j = j - 1
...
Attempt in JavaScript:
function f(A){
if (A.length < 4)
return 0;
let n = A.length;
let hash = {};
let i = 0;
let j;
let k;
let l;
let sum;
let diff;
let count = 0;
// Hash sums up to A[n - 3]
// in O(n^2) time
for (; i<n-3; i++){
for (j=i+1; j<n-2; j++){
sum = A[i] + A[j];
hash[sum] = hash[sum] ? hash[sum] + 1 : 1;
}
}
diff = A[n-1] - A[n-2];
if (hash[diff])
count = count + hash[diff];
// Iterate on j descending,
// updating the hash each time,
// O(n) times
for (; j>1; j--){
// Remove instances of j in
// the hash in O(n) time
for (i=j-1; i>=0; i--){
sum = A[i] + A[j];
hash[sum] = hash[sum] - 1;
}
// Check for valid quadruples
// in O(n) time
// where the old j is now k
k = j;
for (l=k+1; l<n; l++){
diff = A[l] - A[k];
if (hash[diff])
count = count + hash[diff];
}
}
return count;
}
/*
1 1 1 1 3 3
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
Total 8
*/
var A = [1,1,1,1,3,3];
console.log(JSON.stringify(A))
console.log(f(A));
There is a solution in O(n^2 + S), where S is count of quadruples satisfying your condition.
Create a hash-based map M that maps integers to lists of pairs of integers (HashMap<Integer, List<Pair<Integer, Integer>>>).
For each pair (i, j) of indices (i < j) add this pair to list M[A[i] + A[j]]. (For-loop by j should be outer and for-loop by i should be nested, so pairs in all lists are sorted by j)
For each pair (k, l) of indices (k < l):
Let L be the list M[A[l] - A[k]]
For pairs (i, j) in L:
If j < k, add (i, j, k, l) to your answer
Else break nested loop, because pairs are sorted by j and following pairs will not satisfy condition j < k
Both outer loops run in O(n^2), nested loop runs only S times through the whole algorithm, so time complexity is O(n^2 + S).
i'm looking at part of an algorithm, and most of my c knowledge comes from knowing java. i understand that this is a conditional, but what exactly is the order of execution here/what's happening step by step? Thanks!
int i, j, k;
int *x = malloc(n * sizeof (int));
for (i = 0, j = m, k = 0; k < n; k++) {
x[k] = j == n ? a[i++]
: i == m ? a[j++]
: a[j] < a[i] ? a[j++]
: a[i++];
}
free(x);
It is equivalent to:
for (i = 0, j = m, k = 0; k < n; k++) {
if (j == n) x[k] = a[i++];
else if (i == m) x[k] = a[j++];
else if (a[j] < a[i]) x[k] = a[j++];
else x[k] = a[i++];
}
you can rewrite this code to:
if (j == n)
x[k] = a[i++];
else if (i == m)
x[k] = a[j++];
else if (a[j] < a[i])
x[k] = a[j++];
else
x[k] = a[i++];
it looks like part of merge sort algorithm
m and n are variables that have presumably been set beforehand and are non-negative integers, and x and a are arrays that (should have) been allocated. In the case of a[] it presumably has some meaningful contents, and those contents, along with the values of m and n, will determine what x[] gets populated or updated with.
The purpose of the loop is completely opaque to me. What it does:
Sets i to 0, j to m, and k to 0.
Looping from k == 0 to k == (n-1) inclusive
Sets x[k] to the following:
if j is n: a[i], then increments i
if j is not n:
if i is m: a[j], then increments j
if i is not m:
if the value at a[j] is less than the value at a[i]: a[j], then increments j
if the value at a[i] is not less than the value at a[i]: a[i], then increments i
When the loop is complete, x[0] up to x[n-1] will have been populated with values from within a[], based on the contents of a, and the values of m and n.
I assume you are having trouble deciphering this code:
x[k] = j == n ? a[i++]
: i == m ? a[j++]
: a[j] < a[i] ? a[j++]
: a[i++];
Assuming so, this is the conditional operator, which -- as vsync demonstrates -- is very similar to an if-else statement. Essentially, this statement should be thought of as:
condition ? valueIfTrue : valueIfFalse;
This, it turns outs, is very similar but different from:
if (condition)
statementIfTrue;
else
statementIfFalse;
The difference is that the conditional operator always results in a value, which might be assigned to a variable, otherwise used in an operation, passed as an argument, etc.... For the if-then statement to be equivalent, the two statement blocks would need to include the assignment.
Finally, there are multiple conditional operations nested, such that the valueIfFalse is resolved with another conditional operation.
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;
}