Can someone explain the flow of control of this program? - java

This is an example program in my AP Computer Science course, and I can't understand the flow of control of it.
public static void mystery( int n )
{
System.out.println( "mystery called with n = " + n );
if ( n == 0 )
{
System.out.println( "n is zero so no more recursive calls!" );
return;
}
mystery( n - 1 );
System.out.println( "We did it again with n = " + n );
}
public static void main( String[] args )
{
mystery( 5 );
}
It outputs this:
mystery called with n = 5
mystery called with n = 4
mystery called with n = 3
mystery called with n = 2
mystery called with n = 1
mystery called with n = 0
n is zero so no more recursive calls!
We did it again with n = 1
We did it again with n = 2
We did it again with n = 3
We did it again with n = 4
We did it again with n = 5
So far, I understand the recursive method and how it recalls itself via:
mystery( n - 1 );
However, I don't see how it can output those five statements after:
n is zero so no more recursive calls!
Logically, it seems like it would only state:
We did it again with n = 0
Can anyone help a student out and explain to me how it output what it did?

When a function finishes, the function that called it has the opportunity to complete and execute more code.
Here is an illustration of how this recursion happens.
Each level of recursion is indicated by an increase in indentation.
mystery(5):
"mystery called with n = 5"
mystery(4):
"mystery called with n = 4"
mystery(3):
"mystery called with n = 3"
mystery(2):
"mystery called with n = 2"
mystery(1):
"mystery called with n = 1"
mystery(0):
"mystery called with n = 0"
"n is zero so no more recursive calls!"
mystery(0) returns
"We did it again with n = 1"
end of mystery(1)
"We did it again with n = 2"
end of mystery(2)
"We did it again with n = 3"
end of mystery(3)
"We did it again with n = 4"
end of mystery(4)
"We did it again with n = 5"
end of mystery(5)

After 'n is zero so no more recursive calls!' the method continues (the state is put on the stack and then loaded after the call to method(n-1) finishes.

Here is a good way of thinking about recursive programs: when you read program's code, pretend that you know what the program does, even though you don't know it yet. In your situation, this would look like this:
If n == 0, print fixed message - that's the no more recursive calls! string
If n != 0, print n followed by printing whatever the program prints for n-1, followed by printing n again - in other words, there's a "frame" of two messages around whatever the program prints for n-1
Here is how this would look:
mystery called with n = <something>
... whatever the program prints in between...
We did it again with n = <something>
The first printout happens before entering the recursive part of the call; the last printout happens after returning from the recursive part. Note that <something> is the same at the top and at the bottom, because the value of n is stored on each stack frame, and gets set to the previous value as the recursion unwinds.
With this picture in place, it is easy to see that you keep adding nested "frames" until you hit n==0, at which point you print the message in the middle.

The first five times through the mystery method, the method does not stop at the recursive call. It continues on, to output "we did it again." But I suppose since mystery is blocking, the method is only allowed to finish up once the last recursive call is returned. So upon hitting n = 0 the first five calls continue on to their original conclusion, printing "We did it again with n = ..."

Here's a run through of what this recursive method does:
mystery(5): {
| println( "mystery called with n = 5" );
|
| n != 0:
| skip return
|
| mystery(n - 1) is mystery(4)
|
| call mystery(4): {
| | println( "mystery called with n = 4" );
| |
| | n != 0:
| | skip return
| |
| | mystery(n - 1) is mystery(3)
| |
| | call mystery(3): {
| | | println( "mystery called with n = 3" );
| | |
| | | n != 0:
| | | skip return
| | |
| | | mystery(n - 1) is mystery(2);
| | |
| | | call mystery(2): {
| | | | println( "mystery called with n = 2" );
| | | |
| | | | n != 0:
| | | | skip return
| | | |
| | | | mystery(n - 1) is mystery(1);
| | | |
| | | | call mystery(1): {
| | | | | println( "mystery called with n = 1" );
| | | | |
| | | | | n != 0:
| | | | | skip return
| | | | |
| | | | | mystery(n - 1) is mystery(0);
| | | | |
| | | | | call mystery(0): {
| | | | | | println( "mystery called with n = 0" );
| | | | | |
| | | | | | n == 0:
| | | | | | return from mystery(0)
| | | | | }
| | | | |
| | | | | back inside mystery(1), continue executing where we left off
| | | | | println("We did it again with n = 1")
| | | | | method ends; return to caller
| | | | }
| | | |
| | | | back inside mystery(2), continue executing where we left off
| | | | println("We did it again with n = 2")
| | | | method ends; return to caller
| | | }
| | |
| | | back inside mystery(3), continue executing where we left off
| | | println("We did it again with n = 3")
| | | method ends; return to caller
| | }
| |
| | back inside mystery(4), continue executing where we left off
| | println("We did it again with n = 4")
| | method ends; return to caller
| }
|
| back inside mystery(5), continue executing where we left off
| println("We did it again with n = 5")
| method ends; program ends
}

Related

How to update the serial numbers of a set of records at once

Suppose the original records have 5 records, in the following order
| name | seq |
| A | 1 |
| B | 2 |
| C | 3 |
| D | 4 |
| E | 5 |
I need to re-update the seq of these 5 records to the following status at once
| name | seq |
| A | 2 |
| B | 3 |
| C | 1 |
| D | 5 |
| E | 4 |
An update means a batch of update operations that commit updates to only one record each time, rather than updating other records in turn
If the above data needs to be modified, 7 update operations are submitted at a time:
A (seq: 1 -> 0)
C (seq: 3 -> 1)
B (seq: 2 -> 3)
A (seq: 0 -> 2)
D (seq: 4 -> 0)
E (seq: 5 -> 4)
D (seq: 0 -> 5)
How do I use Java or sql processing to finally achieve the desired effect?
sql CASE..WHEN
for example:
UPDATE tablename SET seq = (
CASE name
WHEN 'A' THEN 2
WHEN 'B' THEN 3
WHEN 'C' THEN 1
WHEN 'D' THEN 5
WHEN 'E' THEN 4
END)
WHERE name in('A','B', 'C','D','E');

Java find “stain” in multidimensional - recursive

I am trying to solve this Recursive Exercise:
In a multidimensional board (M x N), which everyone of his elements can be empty or full.
"stain" size is the number of elements who are next to each other and has the value 'x'.
for example this is a multidimensional array (the numbers are the row/column number)
| 0 | 1 | 2 | 3 | 4 |
0 | | x | | | x |
1 | x | | | x | x |
2 | | | x | x | |
3 | x | | | | |
4 | x | x | x | | |
There are 3 stains:
Rows (0,1), (1,0) - Size of 2
Rows (0 ,4) ,(1 ,3) ,(1 ,4) ,(2 ,2) ,(2 ,3) - Size 5
Rows (3 ,0) ,(4 ,0) ,(4 ,1) ,(4 ,2) - Size 4
We need to write a recursive method who has a signature of:
public static int stain (char [][] mat, int row, int col)
the method will get a row and a column and calculate the stain size from that place, if there is no stain it will return 0.
I tried to write the method to solve it but looks like I was doing it kinda messy... can you direct me to the right direction? I'm not looking for a straight answer.
Thanks.
I can't do loops!

Resolving a stack with 2 recursive calls

I'm trying to refresh my skills in recursion and so far everything has gone well. However, I have never seen a problem where a string is the value of two recursive calls. Does the first recursive call ignore the rest of the statement? Is the 2nd recursive call still taken into account when it is resolved? I tried tracing it under the assumption that like a return statement, the first recursive call would break the loop. Therefore, I was under the impression that the rest of the code in the if statement would not be taken into account.
public class Example {
public static String encrypt(String word) {
int pos = word.length() / 2;
if (pos >= 1)
word = encrypt(word.substring(pos)) + encrypt(word.substring(0,pos));
return word;
}
public static void main(String []args){
System.out.println(encrypt("SECRET"));
}
}
While my expected output was "TETRET", the actual output was supposed to be "TERCES." Anyone mind explaining where my tracing or logic went wrong?
I tried tracing it under the assumption that like a return statement, the first recursive call would break the loop.
This is incorrect. Both will be evaluated.
word = encrypt(word.substring(pos)) + encrypt(word.substring(0,pos));
The first recursive call will get pushed onto the stack, and the second will be saved on the stack to be evaluated once the first call has been returned to the call stack. Here's a visual representation:
1
/ \
2 5
/ \
3 4
This is assuming 3, 4, and 5 reach the base case and thus do not continue the recursion
The word is returned in reverse order. I am unsure what you were trying to do instead. Here is a partial trace of your code, using "ABCDEF" instead of "SECRET", showing how it works :
+=================================+====================+===========================================+==============+==========================================+==============+
| word (initial call) | pos (initial call) | word (call 2) | pos (call 2) | word (call 3) | pos (call 3) |
+=================================+====================+===========================================+==============+==========================================+==============+
| "ABCDEF" | 3 | | | | |
+---------------------------------+--------------------+-------------------------------------------+--------------+------------------------------------------+--------------+
| encrypt("DEF") + encrypt("ABC") | | "DEF" | 1 | | |
+---------------------------------+--------------------+-------------------------------------------+--------------+------------------------------------------+--------------+
| | | encrypt("EF") + encrypt ("D") | | "EF" | 1 |
+---------------------------------+--------------------+-------------------------------------------+--------------+------------------------------------------+--------------+
| | | | | encrypt("F") + encrypt("E") | |
+---------------------------------+--------------------+-------------------------------------------+--------------+------------------------------------------+--------------+
| | | | | (call 4 returns "F", call 5 returns "E") | |
+---------------------------------+--------------------+-------------------------------------------+--------------+------------------------------------------+--------------+
| | | | | "FE" | |
+---------------------------------+--------------------+-------------------------------------------+--------------+------------------------------------------+--------------+
| | | (call 3 returns "FE", call 6 returns "D") | | | |
+---------------------------------+--------------------+-------------------------------------------+--------------+------------------------------------------+--------------+
| | | "FED" | | | |
+---------------------------------+--------------------+-------------------------------------------+--------------+------------------------------------------+--------------+
Here is the order in which the calls are made and "resolved" (by resolved, I mean that the return statement of the function is executed) :
encrypt("ABCDEF")
encrypt("DEF")
encrypt("EF")
encrypt("F")
resolution of encrypt("F") // returns "F"
encrypt("E")
resolution of encrypt("E") // returns "E"
resolution of encrypt("EF") // returns "FE"
encrypt("D")
resolution of encrypt("D") // returns "D"
resolution of encrypt("DEF") // returns "FED"
encrypt("ABC")
(...)
Of course the same logic applies to encrypt "ABC" as it did to encrypt "DEF", so if you understand this part you should understand the rest.
If you place the print statement as I have shown, you can see how the returned word and pos are altered. Then just backtracking off the stack, the word is reconstructed in reverse order.
public class Example {
public static String encrypt(String word) {
int pos = word.length() / 2;
System.out.println(word + " " + pos);
if (pos >= 1) {
word = encrypt(word.substring(pos)) + encrypt(word.substring(0, pos));
}
return word;
}
public static void main(String[] args) {
System.out.println(encrypt("SECRET"));
}
}
Produces the following output:
SECRET 3
RET 1
ET 1
T 0
E 0
R 0
SEC 1
EC 1
C 0
E 0
S 0
TERCES

SQL query to automatically select and sum 'grade columns' based on student performance

Please I need real help….
I have a table with student grades and their related positions for that grade - like this:
+---------+--------+--------+--------+--------+--------+--------+--------+--------+----------+
| Name | Grade1 | G1_Pos | Grade2 | G2_Pos | Grade3 | G3_Pos | Grade4 | Grade5 | Agregate |
+---------+--------+--------+--------+--------+--------+--------+--------+--------+----------+
| james | 4 | 3rd | 6 | 4th | 1 | 1st | 3 | 2 | |
| Mavis | 1 | 1st | 1 | 1st | 3 | 3rd | 2 | 3 | |
| john | 5 | 4th | 3 | 2nd | 4 | 4th | 4 | 4 | |
| bendo | 2 | 2nd | 5 | 3rd | 2 | 2nd | 1 | 2 | |
+---------+--------+--------+--------+--------+--------+--------+--------+--------+----------+
NB: Pos meaning Position..
I want to sum up the Grade Columns for each student and store their result in the aggregate column. But instead of summing all grade columns, I want to sum up only four grade columns out of the five grade columns. Grade4 and Grade5 Columns must be part of the four columns to be added.
And for that I only have this code
String sql = "update jhs1 set Agregate=(SELECT SUM(Grade4+Grade5) AS ST) WHERE ID = jhs1.ID";
pst = conn.prepareStatement(sql);
pst.execute();
and for the remaining three Grade columns, I want a code that will check and pick out the best two Grade Columns of the three Grade Columns the student performed well in. Eg. If james's result is Grade1=4 ,Grade2= 6,Grade3=1..the code must select only the best two Grades of the three grades which in this
example its Grade1 = 4 and Grade3 = 1 and add the result to Grade4 and Grade5.
So in james case it will be 4+1+3+2 = 10.
Please how do I write such a SQL query and get a result like the table below:
+---------+--------+--------+--------+--------+--------+--------+--------+--------+----------+
| Name | Grade1 | G1_Pos | Grade2 | G2_Pos | Grade3 | G3_Pos | Grade4 | Grade5 | Agregate |
+---------+--------+--------+--------+--------+--------+--------+--------+--------+----------+
| james | 4 | 3rd | 6 | 4th | 1 | 1st | 3 | 2 | 10 |
| Mavis | 1 | 1st | 1 | 1st | 3 | 3rd | 2 | 3 | 7 |
| john | 5 | 4th | 3 | 2nd | 4 | 4th | 4 | 4 | 15 |
| bendo | 2 | 2nd | 5 | 3rd | 2 | 2nd | 1 | 2 | 7 |
+---------+--------+--------+--------+--------+--------+--------+--------+--------+----------+
Please I will appreciate all help and suggestions.. thank you very much
Eg. If james's result is Grade1=4 ,Grade2= 6,Grade3=1..the code must
select only the best two Grades of the three grades which in this
example its Grade1 = 4 and Grade3 = 1 and add the result to Grade4 and
Grade5.
Instead of focusing your efforts on finding a way to pick the two best grades and then sum them, it is easier to find the worst grade and subtract it from the sum of all 3.
Something like:
SELECT grade1+grade2+grade3 - least( grade1, grade2, grade3 )
FROM .....
Note: LEAST( x,y,z,....) function pick the least of the list of expressions.
If "the least value" is determined by G2_Pos column (the greatest Gx_Pos determines the least Grade), it could be something like this:
SELECT grade1+grade2+grade3 -
CASE greatest( G1_Pos , G2_Pos , G3_Pos )
WHEN G1_Pos THEN Grade1
WHEN G2_Pos THEN grade2
WHEN G3_Pos THEN grade3
END
FROM .....
The problem might be with the same grades, for example when there will be:
+--------+---------+--------+--------+--------+--------+
| G1_Pos | grade1 | G2_Pos | grade2 | G2_Pos | grade3 |
+--------+---------+--------+--------+--------+--------+
| 3rd | 10 | 3rd | 5 | 3rd | 2 |
+--------+---------+--------+--------+--------+--------+
then this expression will always pick grade1, that is 10 in this example.

What's wrong with this recursion for checkers move generation?

I'm writing a simple checkers game in Java. The hard part so far is to generate a list of possible jumps for a piece, especially when there are several paths to jump. I have this recursion to find all possible paths to do a series of jumps. Here's some code:
/*
* possibleJumps(Square pos, Board b, Move jump, ArrayList<Move> moves)
* Add all possible jumps from the position b on board b to movelist moves.
*/
void possibleJumps(Square pos, Board b, Move jump, ArrayList<Move> moves) {
ArrayList<Move> simpleJ = this.simpleJumps(pos, b);
//jump.addJumpSquare(pos);
//System.out.println("check jump " + pos + " so far:" + jump);
if (simpleJ.isEmpty()) {
// no more jumps -> end this jump and add it to the list
jump.endJump(pos);
moves.add(jump);
System.out.println("found jump" + jump);
return;
}
for(Move j:simpleJ) {
jump.addJumpSquare(j.jumped.get(0)); // add the jumped square to the jump path
possibleJumps(j.to, b.doMove(j), new Move(jump), moves);
}
}
Just to explain: simpleJumps generates a list of possible jumps over one square (so basically all attack moves). That works fine.
Here's the test board:
A B C D E F G H
---------------------------------
1 | | o | | | | | | | 1 (0)
---------------------------------
2 | | | | | | | | | 2 (1)
---------------------------------
3 | | o | | o | | o | | o | 3 (2)
---------------------------------
4 | | | | | | | | | 4 (3)
---------------------------------
5 | | o | | o | | o | | o | 5 (4)
---------------------------------
6 | | | | | | | | | 6 (5)
---------------------------------
7 | | o | | O | | o | | | 7 (6)
---------------------------------
8 | x | | | | | | | | 8 (7)
---------------------------------
Here's the output I get:
found jumpa8c2 via b7-b5-b3-
found jumpa8c2 via b7-b5-d5-d3-
found jumpa8g2 via b7-b5-d5-d3-f3-
What it should be is:
found jumpa8c2 via b7-b5-b3-
found jumpa8c2 via b7-d5-d3-
found jumpa8g2 via b7-d5-f3-
This is, in principle, very similar to:
Print all paths from root to leaf in a Binary tree
which I read and used to get as far as I have gotten, but I'm missing something probably very simple...
Any ideas?
In this loop
for(Move j:simpleJ) {
jump.addJumpSquare(j.jumped.get(0)); // add the jumped square to the jump path
possibleJumps(j.to, b.doMove(j), new Move(jump), moves);
}
you are reusing the same jump for all possible moves - if you got 3 possible moves x,y,z you will end up with x, y and z added to the jump path.
So you either have to
create a new jump-object (with appropriate state) at each iteration or
remove the added square at the end of the iteration

Categories