I don't fully understand when these recursive calls return - recursion

I understand simple recursion code but sometimes when it gets a bit complicated. I get lost and can't really follow the code.
For example of the follow code(an anonymous wrote it):
void reversetree(struct node* head)
{
//first check for the exception whether does it even exit or not
if(head==NULL)
return ;
reversetree(head->left); //reverse call for left child
reversetree(head->right); //same reverse call for right child
//now next these steps will swap the children
struct node* temp=head->left;
head->left=head->right;
head->right=head->left;
//now exit the function and you are done :)
}
6
/ \
3 4
/ \ / \
1 2 8 9
Lets say if the binary tree looks like this,can someone do a step by step logic for me please? For my understanding, it first checks to see if the root exists, if it does then it call the function again of the left child until there is no more left child? so when the the code that swaps it ever get called? and when does it start calling the function with the right child? Sorry I am not too bright with recursions.

Usually when dealing with recursion people tend to tell you to do it with pen and paper. Its a great exercise, but I find it easier to do it these ways:
First way to look at it
There is no difference between using a recursive function and a different function that performs the same job. They both do their job and return so that your code resumes on the next line.
Imagine you have a working function, reversetree_external that reverses a whole tree so that you could write your function this way without recursion:
void reversetree(struct node* head)
{
if(head==NULL)
return ;
// switch left and right
struct node* temp=head->left;
head->left=head->right;
head->right=temp; // There was an error here
// Reverse subtrees
reversetree_external(head->left);
reversetree_external(head->right);
}
So everything you need to convince yourself of is that given an argument like:
6
/ \
3 4
/ \ / \
1 2 8 9
Turns into the following before reversetree_external reverses the two subtrees:
6
/ \
4 3
/ \ / \
8 9 1 2
If you only pass one of right and left it would turn that level before using reversetree_external to not do anything.
If you pass it a leaf node, eg. 8 the result is the same 8 (with the null pointers swapped) and reversetree_external won't do anything since it will be given NULL both times.
In fact You can see that reversetree can do the same thing as reversetree_external so instead of relying on it you can just use reversetree itself.
Second way to look at it
Now, it's good to look at this in two ways so do it in reverse, eg. start with NULL.. eg. the left node of 8, then a leaf, then a tree that uses the leaves and then a full tree using the subtrees we have calculated in advance.
input result
NULL NULL
8 8
9 9
1 1
2 2
4 4
/ \ / \
8 9 9 8
3 3
/ \ / \
1 2 2 1
6 6
/ \ / \
3 4 4 3
/ \ / \ / \ / \
1 2 8 9 9 8 2 1
So in place of doing the recursion in my mind I just use the previous result in the results which you know the same function would do. eg. I switch the 3 and 4 as the procedure would use and the two recursions is just the same transformation as the subtree done before.
The first way is just how to read recursive code, the second way is perhaps the easiest and how you can make your own recursive functions with ease. You start with the base case(es) and test them, then add a default case how to do a slightly more complex problem into a smaller similar problem that eventually ends up being a base case.

If the root does not exist, the function quits because it has no children.
Yes, the processor will then follow the chain of left children until it runs out, then the left children of the last node's right child ...
For the tree shown, here's what will happen:
Reverse node 6:
Reverse node 3:
Reverse node 1:
Reverse NULL
Reverse NULL
Swap 1's links to NULL and NULL
Reverse node 2:
Reverse NULL
Reverse NULL
Swap 2's links to NULL and NULL
Swap 3's links to 1 and 2
Reverse node 4:
Reverse node 8:
Reverse NULL
Reverse NULL
Swap 8's links to NULL and NULL
Reverse node 9:
Reverse NULL
Reverse NULL
Swap 9's links to NULL and NULL
Swap 4's links to 8 and 9
Swap 6's links to 3 and 4
It would run a bit faster with a test for NULL before each call.
The swap step could go before the recursive calls, without affecting the speed or result.

Related

unexpected output when filtering a particular column with logical expression including LIKE operator

I have the following dataset.
id
action
source
target
1
ADD
N/A
/root/dir2.trash
2
ADD
N/A
/root/dir1
3
MOVE
/home/user
/home/user.wasted
4
MOVE
/usr/bin
/usr/local/bin
5
MOVE
/usr/sbin
/usr/sbin.trash
When I run the following query, I am expecting to get row 3 and 5 in response but I get row 1 as well.
SELECT * FROM test WHERE action = 'MOVE' AND target LIKE '%.wasted' OR target LIKE '%.trash'
Demo
Your AND and OR act differently than you seem to think, at least in different precedence.
This gets the desired result, probably because it matches how you think.
It makes sure that the first part always has to apply.
SELECT * FROM test WHERE action = 'MOVE' AND ( target LIKE '%.wasted' OR target LIKE '%.trash' )
I.e. your original code acted like "(move AND wasted) OR trash".
This is similar to 2 * 3 + 5 being 11, not 16.

Robot Framework: How to sort by

I have a webpage with a combobox to sort a list by Price, Name,... The list is in many pages, so I need to get all elements first and after, I will sort by and check if the elements are correct. Right?
I am trying to do it and navigate for all pages and get all elements. But it is only taking the elements in first page. I am totally new in Robot framework.
Does anyone have a suggestion how I can do it?
${name_list_actual} Create List
${cnt_pages}= Get Element Count //div[#class='container index-new-p']/div/nav[#class='text-center']/ul/li/*
Log To Console ${cnt_pages}
:FOR ${n} IN RANGE 1 ${cnt_pages}
\ Click link //div[#class='container index-new-p']/div/nav/ul/li[${n}]/a
\ ${cnt}= Get Element Count //*[#class="title"]/*
:FOR ${i} IN RANGE 1 ${cnt}
\ ${get_names} Get Element Attribute //table[#class='result-table']/tbody/tr[${i}]/td/div/div[2]/div/a text
\ Append To List ${name_list_actual} ${get_names}
${get_names}= Select All From List //table[#class='result-table']/tbody/tr[${i}]/td/div/div[2]/div/a
\ Log To Console ${name_list_actual}
\ Continue For Loop
Thanks so much
First and foremost, by your code sample's indent it looks like you're doing nested for loops - an outer one for the changing the pages, and an inner that'll get the text in each row. The thing is - Robot Framework doesn't support nested for loops - see the documentation.
What happened on execution is the first loop (the pagination) ran with just two statements and finished:
\ Click link //div[#class='container index-new-p']/div/nav/ul/li[${n}]/a
\ ${cnt}= Get Element Count //*[#class="title"]/*
Then all the rest were executed as part of the second.
A solution would be to have a keyword "Get All Values In The Table" that'll hold the inner loop, and call it in the current outer, which will paginate.
Another issue - you're using IN RANGE, passing 1 as start and ${cnt} as end; if it had value of 4, you probably expect the tracking variable to get all values from 1 to 4.
Yet range works with the first argument inclusive, and up to - but not getting to - the second argument; thus it covers the range 1 to 3. To salvage that, you'd need to set the upper bound to cnt+1, e.g. ${cnt + 1}.
Minor stuff:
You have a statement that's within the loop block, but not prefixed with \:
${get_names}= Select All From List //table[#class='result-table']/tbody/tr[${i}]/td/div/div[2]/div/a
I'm surprised it didn't give you a syntax error - it effectively breaks the loop, and the framework should complain the next lines are prefixed as if in a loop, but one is not started.
-
When you are changing the pages by the click, you are not making sure the UI has loaded the data for the new page. If this happens through ajax calls, you may very well be working with the previous page's data, thinking it is the new one - the selenium click returns control very fast, and the operands for getting the text are running - while the UI still waits for the new data and is displaying the previous one.
-
In RF version 3.1 the loop syntax is different - the block members are not prefixed with \, and it's closed with an END statement.
I'd suggest to migrate to it - a) the current one is going to be eventually deprecated, and b) in the new one the nesting would have been marked as syntax error (you're starting a new loop without END-ing the running one), instead of silently passing with unexpected behavior.

multiple operators sharing 3 tools, how to avoid deadlock?

I would like to ask some suggestions to solve this particular deadlock:
3 operators, each is given 2 of 3 different materials at random: 1, 2, 3
3 tools, each material needs a different tool to process by an operator.
material 1 needs tool 1
material 2 needs tool 2
material 3 needs tool 3
Each operator needs to wait for the proper tools to process the materials.
i.e. If an operator has taken material 1,2, he needs tool 1,2
A deadlock may happen:
operator 1 has taken material 1,2, waiting for tool 1,2
operator 2 has taken material 2,3, waiting for tool 2,3
operator 3 has taken material 3,1, waiting for tool 3,1
None of the operator can acquire both tools, what should the operator do?
Proposal
Create a global variable to record the recent 6 materials taken by the operators. If each material appeared twice (example [1,3,1,2,2,3]), then the last operator should keep abandoning the last material until no all materials appear twice (example [1,3,1,2,2,1])?
Will this work? what if I have 10 operators with 3 tools and 3 materials. Any suggestion will help.
So how it works is that an operator would take one of the tools, and then the second one. if the second one wasn't available. then it would let the first one go too ( it will put the first tool back and make it free and available for other operators). This way, the other operator that is waiting for that tool would take it and the deadlock won't happen.
int toolx=0; // operator has no tool x
int tooly=0; // operator has no tool y
pthread_mutex_lock(&tool_mutex);
// loop if toolx and tooly are not aquired
while ((toolx + tooly)!=2){
//drop tool x
if (toolx == 1) {
toolbox[mat_x] ++;
toolx -- ;
pthread_cond_signal(&cond_tool);
}
// drop tool y
if (tooly == 1) {
toolbox[mat_y] ++;
tooly -- ;
pthread_cond_signal(&cond_tool);
}
// wait on tool x
while (toolbox[mat_x] == 0) {
pthread_cond_wait (&cond_tool,&tool_mutex); // wait
}
// wait complete and take tool x
toolbox[mat_x] --;
toolx ++ ;
//try take tool y
while (toolbox[mat_y]== 0) { // if other is taking tool y
if (toolx == 1) { //if operator is holding toolx.
toolbox[mat_x] ++;
toolx -- ; // put back tool x
pthread_cond_signal(&cond_tool);
}
pthread_cond_wait (&cond_tool,&tool_mutex); // wait on tools
}
// take tool y
toolbox[mat_y] --;
tooly ++;
}
pthread_mutex_unlock(&tool_mutex);

Prolog out of local stack space/ infinite recursion

I have read other similar questions and answers on this site, but can't seem to find the answer to my particular problem. I am trying to encode a maze in Prolog.
From region 0, you can move freely to regions 1 or region 3. From region 3, you can move freely to region 0, region 4, or region 5, etc. I want to find the all paths of length 7 from the beginning to the end (from 0 to 14). I have encoded the problem in the following manner in SWI-Prolog:
region(0).
region(1).
region(2).
region(3).
region(4).
region(5).
region(6).
region(7).
region(8).
region(9).
region(10).
region(11).
region(12).
region(13).
region(14).
region(15).
connection(0,1). %connection exists between these two regions
connection(0,3).
connection(1,2).
connection(1,8).
connection(1,7).
connection(3,4).
connection(3,5).
connection(7,9).
connection(7,5).
connection(7,8).
connection(5,6).
connection(8,10).
connection(8,11).
connection(11,12).
connection(11,13).
connection(13,15).
connection(13,14).
double_link(X,Y) :-
region(X),
region(Y),
( connection(X,Y) | connection(Y,X) ). %can go from region X to region Y, and vice versa
path(X,Y) :-
double_link(X,Y).
path(X,Y) :-
double_link(X,Z),
path(Z,Y).
When I execute path(14,0). I get true. However, when I execute path(0,14)., I run out of local stack space. I don't know how that can be. Thanks for any help!
You said:
When I execute path(14,0). I get true.
That is half of the truth! Oh, even less than that! In fact you get true not once but many times!
?- path(14,0).
true
; true
; true
; true
; true
; true
; ... .
There is a simple way to avoid typing ; or SPACE all the time. Simply use the goal false.
?- path(14,0), false
loops.
And now, you can also add such false-goals into your program. In this manner you are ruling out parts of the program ; and if the remaining part still loops, you know that there must be a problem there. This is what I got:
region(0) :- false.
% ...
region(12) :- false.
region(13).
region(14).
region(15) :- false.
connection(0,1) :- false.
% ...
connection(13,15) :- false.
connection(13,14).
double_link(X,Y) :-
region(X),
region(Y),
( connection(X,Y) ; connection(Y,X) ).
path(X,Y) :- false,
double_link(X,Y).
path(X,Y) :-
double_link(X,Z),
path(Z,Y), false.
So in this remaining part that loop has to be addressed. It should be now self-explanatory, isn't it?
The problem arises because you can go in circles in the maze. E.g. in your maze you have the connections 0 - 1 - 7 - 5 - 3 - 0. You have not taken any measures to ensure that the search does not follow those circles blindly.
A usual approach would be to add an argument to your path predicate that contains the already visited regions (initially empty). Then you have to ensure when you go to a new location X that X is not in that list (e.g. with nonmember(X,Visited)).

duplicated one node in path - cypher (query all path between two nodes)

I have got nodes connected like in the picture from the link
I do query START a=node(27), b=node(0) MATCH p=b<-[*]-a RETURN p
I expect that I will get 3 paths but got 6.
First 3 are correct but the last 3 have got duplicate 'node 0'
For example:
correct path: 0 -> 41 -> 2 -> ... -> 27
duplicate node path: 0 -> 0 -> 41 -> 2 -> 27
The lengths of incorrect paths are exactly incremented by one.
How to write a query to get (in this example) exactly 3 path without duplicate nodes?
Your query is correct and there probably is a problem in the database. I replicated your graph structure: console.neo4j. Run START n=node(*) RETURN n to get the ids of node 27 and 0 and then run your query. It returns exactly 3 results.
To check whether you have loops on node 0 execute:
START n=node(0) MATCH n-[r]-n RETURN r

Resources