I have a Scheme-like tree graph structure. I want to parse it using C into some in-memory representation and walk over it.
It there any library or front-end of parser to do this?
EDIT:
I have parsed the following expression
true && (false || true) ;
true ;
false || false
into following (This is my scheme-like tree dump)
(PROG [(AndExp TVal(OrExp FValTVal)), TVal, (OrExp FValFVal)])
Which I want to traverse using C ( I have to give it to someone else who only works with C). PROG is a label; AndExp, OrExp etc are tokens for &&, || etc ..
It seems like this is a form of S-Expression. Perhaps This S-Expression Parser can be modified for your needs.
I think i have understood your requirement, but not quite sure.
You have the expressions in prefix notation, therefore this is basically loading the prefix expression you have in your dump file in binary tree.
Here is a pseudocode which described the process to load the expressions into a tree.
tree_node make_tree (string dump)
{
tok1 = get_tok (dump);
tok2 = get_tok (dump);
tok3 = get_tok (dump);
if (tok1 == operand)
{
node = make_new_node_with (tok1);
return node;
}
node = make_new_node_with (tok1);
node->left = make_tree (tok2);
node->right = make_tree (tok3);
return node;
}
Recursive call 1 with (AndExp TVal(OrExp FValTVal))
tok1 = AndExp makes a new node1
tok2 = TVal
tok3 = (OrExp FValTVal)
Recursive call 2 with TVal returns node2 to call 1 which links it with the left pointer of node1.
Recursive call 3 with (OrExp FValTVal) from call 1.
tok1 = ORExp makes a new node3
tok2 = FVal
tok3 = TVal
Recursive call 3 with FVal and call 4 with TVal respectively returns node4 and node5 with the operand values, which are linked to the left and right links of the node3 from call 3.
No more subexpression to be considered, recursion returns back to starting point. You have the root of the tree.
( node1 )
|AndExp |
+---+---+
|
+------------+------------+
| |
( node2 ) ( node3 )
| TVal | | ORExp |
+---+---+ +---+---+
|
+-----------+-----------+
| |
( node4 ) ( node5 )
| FVal | | TVal |
+---+---+ +---+---+
If there are more than two operands , processing can be done similarly by adding additional links to the tree nodes.
For each expression in your dump file, which are separated by commas will have separate trees, which after creation can be traversed.
Related
I want to build an iteration using the Stata FAQ here. The second method seems fitting for my case. I have built the following code:
levelsof ID, local(levels)
foreach l of local levels {
var var1 var2 if ID == `l', lags(1/4) vsquish
vargranger
}
Idea: iterate over all IDs in ID, then do vargranger. However, it runs once, then outputs no observations. Which is not true, as I have 200 IDs in my search variable.
Second thing I want to add into my loop, a return / print function of the current ID used in ID.
The output should look like this, for each value of ID:
ID = XYZ
Sample: 2001 - 2019 Number of obs = 16
...
vargranger
Granger causality Wald tests
+------------------------------------------------------------------+
| Equation Excluded | chi2 df Prob > chi2 |
|--------------------------------------+---------------------------|
| var1 var2 | 11.617 4 0.020 |
| var1 ALL | 11.617 4 0.020 |
|--------------------------------------+---------------------------|
| var2 var1 | 6.2796 4 0.179 |
| var2 ALL | 6.2796 4 0.179 |
+------------------------------------------------------------------+
display of the current level is easy enough, say:
levelsof ID, local(levels)
foreach l of local levels {
di "{title:`l'}" _n
count if !missing(var1, var2) & ID == `l'
var var1 var2 if ID == `l', lags(1/4) vsquish
vargranger
}
The report "no observations" is presumably coming from var and is not a reflection of how many identifiers you have. You should add checks like that above for (e.g.) how many observations you have to play with.
I have about 100 datasets in Stata. I want to loop across all of them to get one summary table for the proportion of people across all datasets who are taking a drug aceinhib. I can write code which produces a table for each dataset, but what I want is a summary of all these tables in one table.
Here is an example using just 5 datasets:
forval i=1/5 {
capture use "FILEADDRESS\FILENAME`i'", clear
table aceinhib
capture save "FILEADDRESS\NEW_FILENAME`i'", replace
}
This gives me:
----------------------
aceinhib | Freq.
----------+-----------
0 | 1578935
1 | 138,961
----------------------
----------------------
aceinhib | Freq.
----------+-----------
0 | 5671774
1 | 421,732
----------------------
----------------------
aceinhib | Freq.
----------+-----------
0 | 2350391
1 | 198,875
----------------------
----------------------
aceinhib | Freq.
----------+-----------
0 | 884,660
1 | 51,087
----------------------
----------------------
aceinhib | Freq.
----------+-----------
0 | 1470388
1 | 130,614
----------------------
What I want is:
----------------------
aceinhib | Freq.
----------+-----------
0 | 11956148
1 | 941269
----------------------
-- namely, the combined results of the 5 tables above.
Consider this pattern:
scalar a = 0
scalar b = 0
quietly forval i = 1/1000 {
sysuse auto, clear
count if foreign
scalar a = scalar(a) + r(N)
count if !foreign
scalar b = scalar(b) + r(N)
}
gen double count = cond(_n == 1, scalar(a), cond(_n == 2, scalar(b), .))
gen which = cond(_n == 1, "Foreign", cond(_n == 2, "Domestic", ""))
list which count in 1/2
Just cumulate counts from one file to another. For the real problem, don't read in the same dataset, repeatedly, but different files in a loop.
Perhaps this will point you in a useful direction.
clear
tempfile working
save `working', emptyok
forval i=1/5{
quietly use "FILEADDRESS\FILENAME`i'", clear
* replace "somevariable" with the name of a variable that is never missing
collapse (count) N=somevariable, by(aceinhib)
append using `working'
quietly save `working', replace
}
use `working', clear
collapse (sum) N, by(aceinhib)
list
If all files have the same structure, you could append them into one file before your table command. The following solutions also rely on aceinhib being coded as 0/1. If the files are not too large to append, it could be as simple as:
use "FILEADDRESS\FILENAME1", clear
forvalues i = 2/100 {
append using "FILEADDRESS\FILENAME`i'"
}
table aceinhib
If the resulting data file from append is too large, and there are no weights involved, you may continue as you have and employ the replace option for table:
forvalues i = 1/100 {
use "FILENAME`i'", clear
table aceinhib, replace
rename table1 freq
save "NEW_FILENAME`i'"
}
use "NEW_FILENAME1", clear
forvalues i = 2/100 {
append using "NEW_FILENAME`i'"
}
collapse (sum) freq, by(aceinhib)
list
Note that this approach will create data files containing the individual frequency tables. A third approach relies on storing the results of tab into a matrix for each iteration of the loop, and adding them to another matrix to store the cumulative freq of 0/1 values for aceinhib in each dataset:
mat b = (0\0)
forvalues i = 1/100 {
use "`FILENAME`i''", clear
tab aceinhib, matcell(aceinhib`i')
mat aceinhib = aceinhib + aceinhib`i'
}
mat list aceinhib
This is how I would approach the problem, although there may be cleaner solutions leveraging user written packages or other base Stata functionality that I haven't included here.
I am writing a simple text game in C where the player combats a very simple AI. Inside the main() function, there is a loop that should continue as long as the player's HP or the enemy's HP is higher than 0. See the example below.
while(grunt->hp > 0 || player->hp > 0) {
stats(player);
printf("Grunt HP: %d\n", grunt->hp);
plyMove(player, grunt);
aiMove(player, grunt);
}
if(player->hp > 0) {
printf("You won the battle!\n"); }
else {
printf("You've lost the battle!\n"); }
return 0;
Now to my understanding, this while loop should do it's thing as long as both expressions are true. If just one of them becomes false, the loop should end. However, if the enemy's HP is lower than zero, it will not break out. But if the player's HP is lower than zero, it breaks.
Every iteration of the loop is printing these values, so I can keep track of them.
Am I simply not understanding the logic of this? If you need to see any additional code, please let me know.
You're using a logical OR, which is true if at least one parameter is true. In other words, the truth table is this:
In | In | Out
T | T | T
T | F | T
F | T | T
F | F | F
It sounds like you want a logical AND, which is true if both parameters are true. This way, the fight continues as long as both the player and enemy have over 0 health. The operator for logical AND in C (and many other languages) is &&.
In case you're interested, here's the truth table for AND:
In | In | Out
T | T | T
T | F | F
F | T | F
F | F | F
While both the grunt's hp and the player's hp (true) are above 0 you want the loop to continue so you want:
while(grunt->hp > 0 && player->hp > 0)
If either the grunt's hp or the player's hp goes below 0 the condition above will be false and you will exit the loop.
If in your head you were thinking "I want to end the game when the player's HP or the enemy's HP is below or equal to zero", the right while condition would be:
while(!(grunt->hp <= 0 || player->hp <= 0))
With the logical inverse operator !
Recall: !(A || B) == !A && !B so other guys answer is strictly equivalent.
Sometimes an abstraction can make things easier to grasp.
Consider if you had:
#define Alive(who) ((who)->hp > 0)
then you could write:
while (Alive(grunt) && Alive(player)) {
…
}
The Report will display Two Columns Foo and Bar
Some Rows of Foo are Empty Some have a numerical Value:
Foo:
+----+
| |
+----+
|10.0|
+----+
then There is the Bar Column, this column will take the Values from Foo and add 10 to them, the report should yield Results like this:
Foo: Bar:
+----+----+
| | |
+----+----+
|10.0|20.0|
+----+----+
Thats the Expression i use to determine whether Foo is numeric inside Bar:
=IsNumeric(ReportItems!FooBox.Value)
And this is the Result that Expression will Yield:
Foo: Bar:
+----+-----+
| |False|
+----+-----+
|10.0|True |
+----+-----+
Okay, thats exactly the way i want it so far, thus i write My Expression that way:
=IIf(IsNumeric(ReportItems!FooBox.Value),
ReportItems!FooBox.Value +10,
"")
This will Yield the Following Results:
Foo: Bar:
+----+------+
| |#Error|
+----+------+
|10.0|20.0 |
+----+------+
And most Bizare, when i remove the little addition in the Truepart of the IIf, it will execute:
=IIf(IsNumeric(ReportItems!FooBox.Value),
ReportItems!FooBox.Value,
"")
Foo: Bar:
+----+------+
| | |
+----+------+
|10.0|10.0 |
+----+------+
It's almost as if the "wrong" part of the Ternary operator gets executed Anyway, thus generating this castError or whatever it might be.
How can i convert the Values properly in order to Show the Results as Explained before?
Indeed - using IIf will cause both statements (true and false) to be evaulated and that leads to the error you are getting.
being in your situation, I would create my own function to handle this - you can place it in Code field of your Report (click outside of Page area to access Report object)
your function might look like this:
Public Function MyAdd(val As Object) As Nullable(Of Integer)
If TypeOf(val) Is Integer Then
Return val + 10
Else
Return Nothing
End If
End Function
you might need to play with types used (Object and Nullable Of Integer are maybe not what will work for you)
then, of course, use MyAdd in your expression and pass ReportItems!FooBox.Value as parameter
A function to count the number of nodes in a tree.
int count(node *t)
{
int i;
if (t == NULL)
return(0);
i = 1 + count(t->left) + count(t->right); // recursion occurs address of left node is passed and
return(i); // continue to pass until whole left node
} // is traversed and the value of t is
// NULL and 0 is returned same for right node counting
// i = 1 + 0 + 0 = 1
How is the number of nodes counted ?
To understand recursion, you must first understand recursion.
That's a recursive implementation of counting tree nodes. It is called for the root node and returns "one plus number of nodes in left subtree plus number of nodes in the right subtree", that is done recursively until it reaches leaf nodes.
The total count includes the current/root node plus the count on the left branch plus the count on the right branch. Your sentinel is the NULL which means you've reached the leaf node of whatever branch you are currently counting. Then you unwind back up. Recursion :)
First, have you tried it yourself?
Basically, it adds 1 for every non-null node. It's roughly like this: 1 + number_of_nodes_to_the_left + number_of_nodes_to_the_right. This expands to: 1+(1+number_of_nodes_to_the_left_in_left+number_of_nodes_to_the_right_in_left) + (1+number_of_nodes_to_the_left_in_right + number_of_nodes_to_the_right_in_right). Keep on expanding and you'll see that it's basically 1 + 1 + 1 +.... for every non-null node in the tree.
EDIT: To illustrate this better, consider the following tree:
Node0
|
(left) | (right)
Node1 _|_ Node2
|
(left) | (right)
Node3 _|_ Node4
When you do int node_count = count(Node0), since Node0 is not NULL, it goes to the return statement which is:
return 1 + count(left) + count(right). You need to understand a basic thing that very operation in your recursion function happens one-after-the-other.In other words operation count(right) doesn't happen until operation count(left) is completed. Now take a look at the return statement you have there and translate it in terms of the above tree. It would be 1+count(Node1)+count(Node2). So count(Node2) doesn't get calculated before count(Node1) has finished. So for count(Node1), count function gets called (again) with Node1 as the argument. So let us, for now, forget about the semi-calculated expression 1+count(Node1)+count(Node2) (we'll come back to it later).
Now for count(Node1), Node1 is not NULL and hence proceeds to the return statement. This would (again) be 1+count(left)+count(right). But wait, Node1 doesn't have left and right nodes. So, when count(left) gets called with the argument being NULL, it returns 0 and the same happens for count(right). So the expression for count(Node1) becomes 1 + 0 + 0. There are no more count functions being called for Node1 and hence it returns to it's original caller, which was the return statement of count(Node0).
Since we have count(Node1) figured out, let's replace it in the return statement of count(Node0). This now becomes 1 + (1 + 0 + 0) + count(Node2).
Now I'm going to make this a bit faster. Since Node2 has two children, the return statement of Node2 will be 1 + count(Node3) + count(Node4). Just like it was for Node1, count(Node3) and count(Node4) will each return 1 + 0 + 0, turning the return statement of count(Node2) to be 1 + (1 + 0 + 0) + (1 + 0 + 0).
Now that count(Node2) has been fully calculated, let's return to the original caller of count(Node2), which is 1 + (1 + 0 + 0) + count(Node2). Replace what we got from count(Node2) in there and we get 1 + (1+0+0) + (1 + (1+0+0) + (1+0+0)). Add it up and we get the value of 5. This value gets returned to whichever function that called count(Node0), like the statement int node_count = count(Node0) and node_count will have the value 5.
Consider these trees:
A tree with no nodes (i.e. a NULL pointer) - returns 0
A tree with one node, the root. This will call:
i=1+count(t->left)+count(t->right);
with left and right NULL, and so will return 1 + 0 + 0
A tree with a root and a single right leaf
i=1+count(t->left)+count(t->right);
will return 1 for the root, 0 for the tree rooted at left (by the rules above) and 1 for the tree rooted at right (by the rules above), which is 1 + 0 + 1
And so on.