'For' loop followed by an 'if' statement into 'for' loop - java

I'm trying to solve a puzzle on hackerrank (the Sherlock and Queries puzzle - https://www.hackerrank.com/challenges/sherlock-and-queries). After working on it for a while, I started digging around on the internet for some help. I found one post here https://codereview.stackexchange.com/questions/58095/sherlock-and-queries-challenge?newreg=0bf47176275d428dbdfa0c6a4bc86f07 that confused me. It looks as if he changes this
for (int j = 0; j < N; ++j) {
if (j % B[i] == 0)
...
}
into this
for (int j = B[i] - 1; j < N; j += B[i]) {
...
}
Can someone please explain how these two are equivalent?

Assuming B[i] is an integer >= 2, the two snippets would be equivalent only if the second would be :
for (int j = 0; j < N; j += B[i]) {
}
Thus j would iterate over all the values that are divisible by B[i], which are exactly the values of j for which the condition in the first loop is true.
If j is initialized to B[i]-1, j%B[i] is never 0, so the second loop is not equivalent to the first loop.

The two are not equal.
The right equivalent for the first form that comes close to the second form would be:
for (int j = 0; j < N; j += B[i]) {
...
}
The first form lets j go from 0 to N and chooses only to act when j is dividable by B[i] (without a rest value). The second form gets the same result, by letting j go to B[i] * 0, B[i] * 1, B[i] * 2.....N. If you think about it, only multiples of B[i] are dividable by B[i] (without a rest value).

Related

Why is the this block is not performed during execution?

int n = 3;
int x = n;
int y = 0;
for(int i = n; i > 0; i--)
for(int j = 0; j <=n; j++)
if(j > n)
for(int k = 1; k <=n; k++)
System.out.println("x is " +x--);
else
System.out.print("y is " +y++);
under the if statement if(j > n) why is that the for loop is not performed?
i can't really understand why, because our instructor let us analyze the running time and i can't really understand why that for loop is not performed during the execution. please help me..
for(int j = 0; j <=n; j++)
if(j > n)
What you are saying in the for loop is: Execute this code while j is less or equal to n.
Then on the if you say: If j is greater than n.
j will never be greater than n as the for loop limits j falue to be less or equal than n.
That's pretty basic and you should read more on how for works.
Also, avoid not using {}, it's very dangerous. Prefer to always do:
for(int j = 0; j <=n; j++) {
if(j > n) {
....
}
}

How does a for loop increment?

The sum is -9 but i'm having trouble figuring out why. I don't understand how the j-- in the for loop will increment. It should be incremented after the body is executed, right? But doesn't the initialization of the for loop make j-- pointless? So I assume that on the 2nd iteration j becomes 2 because of i++. Could someone help look at this the right way?
public static void whatsTheSum(){
int sum = 1;
int i = 1;
while(i < 5){
for(int j = i; j > 0; j--)
sum += (j - i);
i++;
}
System.out.println(sum);
}
I don't understand how the j-- in the for loop will increment. It should be incremented after the body is executed, right?
It's updated, then, yes. (The update is a decrement, not an increment.) But yes, it happens after each time the loop body is run.
But doesn't the initialization of the for loop make j-- pointless?
No. The initialization has j start with the value from i, and then count down while j is > 0 (without changing i).
So I assume that on the 2nd iteration j becomes 2 because of i++.
The second iteration of the while loop, yes. j will start out at 2 and then the for loop will run twice (for j = 2 and j = 1).
Just for complete clarity, here's how a for loop works:
for (initialization; test; update) {
body;
}
That's executed in this order:
Do initialization
Evaluate test, if false leave the loop
Do body
Do update
Jump to Step 2
To what I understand the requirement stated in the question above to increment j to iterate from 0 to i, you would require something like -
while(i < 5){
for(int j = 0; j < i; j++) {
sum += (j - i);
}
i++;
}
also j++ can be replaced as j=j+1 , j += 1 they would have eht esame effect and the order is very nicely explained by #T.J's answer.
So if you have nested loops its always good to write down each and every iteration:
i = 1, sum = 1
1. while (i < 5) = true so
1.1 for(int j = 1; j > 0; j--) j=1
sum += (1-1)
i=2 sum =1
2. while (i < 5) = true so
2.1 for(int j = 2; j > 0; j--)
sum += (2-2) --> sum = 1
2.2 for(int j = 1; j > 0; j--)
sum += (1-2) --> sum = 0
i=3 sum =0
3. while (i < 5) = true so
3.1 for(int j = 3; j > 0; j--)
sum += (3-3) --> sum = 0
3.2 for(int j = 2; j > 0; j--)
sum += (2-3) --> sum = -1
3.3 for(int j = 1; j > 0; j--)
sum += (1-3) --> sum = -3
And so on

I just tried this code in java and here is my output 011. Can anyone please explain me how this happend

for(int i =0; i <= 1; i++)
{
for(int j =0; j <= i; j++)
{
System.out.print(i);
}
}
Output: 011
I just want to know how this happened.
You have two loops:
for(int i =0; i <= 1; i++) //external loop
for(int j =0; j <= i; j++) //internal loop
System.out.print(i);
The external loop has 2 iteration since it starts in i = 0 and ends in i = 1 when i is incremented to i = 2 you exit the for loop.
The internal loop has i + 1 iterations.
When i = 0 the internal loop iterates once. That`s when you get the 0.
When i = 1 the internal loop iterates twice (j = 0 and j = 1). That`s when you get 11

Loop through a 2d array backwards

I need to loop through a 2d array backwards for a little map project I'm doing. I tried doing so based off of what I've read online, but my 2d array is different. How can I loop through this backwards?
for(int i = 0; i < map.length; i++){
for(int j = 0; j < map[i].length; j++) {
switch (nmap[j][i]) {
map[i][j] = new Tile();
}
}
}
To go the other way, you need to start the index at the highest value and decrease it for each iteration. Like this:
for (int i = map.length - 1; i >= 0; i--)
for (int j = map[i].length - 1; j >= 0; j--) {
switch (map[i][j]) {
map[i][j] = new Title();
}
}
Note that in both loops, we are starting from the highest index, map.length - 1 in the first and map[i].length in the second, and going down by one for each iteration until we reach the lowest index, 0 for both loops.
With for(int i = 0; i < length; i++), you're starting at the start (0), and going to the end (length).
To go the other way, just reverse everything:
for(int i = length - 1; i >= 0; i--)
Few things to note:
We have to do length - 1, or we'll start 1 past the end
We're using >= to include 0
We're decrementing i instead of incrementing it.
If you need it for a 2D array, just add a second of the above for the second dimension.
To go backwards , you need to read from the highest index to 0 . Highest index is typically length-1 since indices start from 0. Same goes for the inner j loop. Start from the highest index of map[i] i.e length -1.
eg. Array = [2 ,3,4,5,6]
Length =5 .Indices to iterate = 4 to 0 if backwards.
for(int i = map.length-1; i >= 0; i--) {
for(int j = map[i].length-1; j >= 0; j--) {
//your operation
}
}
Here you go.
for(int i = map.length-1; i >= 0; i--){
for(int j = map[i].length-1; j >= 0; j--) {
switch (nmap[j][i]) {
map[i][j] = new Tile()
}
}
}
Rather then going from 0 to map.length and 0 to map[i].length, this program starts at map.length-1 (so you don't ever get an index out of bounds error) and continues until it hits zero.

How can I remove a modulo out of my math operation?

My prof does not like the use of modulo since it's not efficient enough, but I'm not sure how else I can get the same answer using a logic operator or something. Can someone help me out with how I can do this?
j = (j + 1) % a.length;
This should do the trick.
int k = a.length;
int d = (j+1)/k;
j = (j+1) - d*k
The only way I can see of doing this without a modulo is still not great:
j = (++j < a.length)? j : (j - a.length);
Alternately, for more readability:
j++;
j = (j < a.length)? j : (j - a.length);
or
j++;
if (j >= a.length) {
j -= a.length;
}
Also, I'm not entirely sure about how Java does with loop prediction, but at least in C, the following would be slightly better for speed, if less readable, since the general assumption is that the argument to the if statement will be true, and j < a.length more often than not (Unless a.length <= 2, which seems unlikely.)
j++;
if(j < a.length) {
}
else {
j -= a.length;
}
If the initial value of j is outside the range 0 to a.length (inclusive-exclusive), then the only solutions either use a modulus or division, which, being the same operation, are the same speed, or a loop of subtraction, which will essentially accomplish the same thing as modulus on a very old processor, which is slower than the built in operation for modulus on any current processor I know about.
You could do this:
j = j + 1;
if (j >= a.length) {
j = j - a.length; // assumes j was less than length before increment
}
#ajp suggests another solution that actually would work ok.
j = j + 1;
if (j >= a.length) { // assumes j was less than length before increment
j = 0;
}
If I was writing the code, id write it this way, just in case. It has very little additional overhead and removes the "assumes"
j = j + 1;
while (j >= a.length) {
j = j - a.length;
}
Of course, the % would be a good way to do it too. Unless one is your professor.
This could be faster or slower than a divide/modulo depending on the cost of a jump (and any effect that has on the instruction pipeline/lookahead) and the efficiency of the integer division instructions.
Old processors would likely do better with the jump. More modern ones with the divide.
Think of what you are doing here. You are essentially saying:
if j + 1 is smaller than a.length, set j to j + 1
otherwise, we set j to a value smaller than a.length
This pseudocode should give you a very clear hint to the solution.

Categories