Ocaml - match n-ary_tree with empty tree - syntax

Let's say I have a n-ary tree type
type tree = Node of (char*tree) list ref;;
and this correspond to the empty tree
let empty_tree ()= Node(ref[]);;
I'm trying to write a function that only looks if my tree is empty or not, such as
let checkIsEmpty t = match t with empty_tree-> print_string "tree is empty";;
But when I write checkIsEmpty empty_tree;; it just return a unit, it won't print "tree is empty"
I also tried that way
let checkisEmpty t = match t with z when z = empty_tree-> print_string "tree is empty";;
Sadly it still fails.
How can I look if my tree is empty? I'd like to keep the match with and the way tree is declared (Empty is not part of the type..) if possible.
Thanks!

You most likely need to flush the output to see it. You can write this:
print_string "tree is empty"; flush stdout
However, your first match doesn't work. Any identifier in a pattern introduces a new variable. So the variable empty_tree in your first implementation will always match whatever tree you pass to your function. (Or indeed it will match any value whatsoever.)
The second implementation should work a little better once you add flush stdout, and assuming there is a global value empty_tree that is an empty tree. But you should also add a case that matches when the tree is not empty; otherwise you'll get an exception for that case.
Furthermore your empty_tree is a function that returns an empty tree. It's not an empty tree itself (as your latest code is assuming).
(I would suggest you not modify your question too much after asking it. It makes it hard to write an answer that corresponds to what you asked.)

Related

Prolog looking for the inorder location of an element in tree(without using lists)

I am trying to go through a binary tree in an inorder traveling method
my target is to find the occurance of a specific key in the tree
for example,
i have the following tree:
t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil))
when i will use my inorder_finder i will get the following:
for "c" i will get 8
for "d" i will get 1
for "w" i will get -1
I have come up to the following code:
inorder_finder(nil,_,_,0).
inorder_place(t(_,X,_),X,Count,Place) :-
Place is Count+1.
inorder_place(t(L,_,R),Wanted,Count,Place) :-
inorder_place(L,Wanted,Count+1,Place),
Place<1,
inorder_place(R,Wanted,Count+1,Place),
Place<1,
Count = Count+1.
and i call the following predicate:
inorder_finder inorder_place(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"c",1,Place)
but it doesnt work at the moment. (just always returns false)
any ideas?
update: I have updated the code according to the comments i got - it still returns false and doesnt work as i would like it to
Most obvious errors have been mentioned in comments, what still remain are:
Place<1 : I don't get why?? Place may has value greater than 1.
inorder_place: never defined...
inorder_place(t(_,X,_),X,Count,Place):-Place is Count+1.: even if you find the letter you need first recursively enumerate the left branch of tree and then Place of wanted letter (see answer below)
I think the problem could be solved in two parts, one in-order-enumerate all nodes then simply traverse until you find the right node. Though I didn't followed this version (even it is more clear) since with a simple-mixed solution it is more efficient since you may not need to enumerate all nodes. For this attempt that you're trying to do I think you need two counters - first one the counter when calling inorder_find(..) e.g when entering, second counter will return where the counting stopped in order to continue from there in the right branch of tree.
inorder_finder inorder_place(...):still not valid syntax for calling the predicate- it should return error not false...
My implementation:
inorder_finder(nil,_,Count,Count,-1).
inorder_finder(t(L,X,_),X,Count,Count2,Place):-
inorder_finder(L,X,Count,Count3,_),
Place is Count3+1,Count2 is Place.
inorder_finder(t(L,X,R),Wanted,Count,Count2,Place):-
dif(X,Wanted),
inorder_finder(L,Wanted,Count,Count3,Place1),
Count4 is Count3+1,
inorder_finder(R,Wanted,Count4,Count2,Place2),
Place is max(Place1,Place2).
Examples:
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"c",0,_,P).
P = 8 ;
false.
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"W",0,_,P).
P = -1.
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"d",0,_,P).
P = 1 ;
false.

Algorithm to let a program has a pre-defined hash value?

Let's put it via an intuitive example.
I don't want others to modify my source code, so I put a statement in my code:
if( hash_value_of(this_file) != "A_PRE-DEFINED_HASH_VALUE" )
output("Aha! You modified my file!")
So in this case, the pre-defined hash value will affect the actual hash value of the source file at the output stage. It's like a strange loop so that I have to find a way to calculate a hash value beforehand that exactly matches the output.
It is of note that actually I don't care if this method can protect my source file at all. It is just an example. What of concern is how to calculate such a hash value beforehand.
Is there any algorithm matches the need? I am not expecting to get answers like "why do you even think about it?", "what's the usage?". It's only an algorithm discussion. Thanks for any contribution!

How to have nested conditions for PMD Xpath rules

My rule requires me to apply them only to methods without 'get' as part of their name. In another words, my rules need to apply to only non-getter methods in the class. I know to get a hold of all the non-getter methods, I can use
//MethodDeclarator[not(contains(#Image,'get'))]
However, I don't know the syntax about where I insert my logic for the rules. Is it like
//MethodDeclarator[
not(contains(#Image,'get'))
'Some Rule Statements'
]
I saw the use of . in the beginning of statement inside [] in some example code. what are they used for?
In my particular case, I need to combine following pieces together but so far I am unable to accomplish it yet.
Piece 1:
//PrimaryExpression[not(PrimarySuffix/Arguments)]
Piece 2:
//MethodDeclarator[not(contains(#Image,'get'))]
Piece 3:
//PrimaryExpression[PrimaryPrefix/#Label='this']
You need to have at least some basic knowledge/understanding of XPath.
I saw the use of . in the beginning of statement inside [] in some
example code. what are they used for?
[] is called predicate. It must contain a boolean expression. It must immediately follow a node-test. This specifies an additional condition for a node that satisfies the node-test to be selected.
For example:
/*/num
selects all elements named num that are children of the top element of the XML document.
However, if we want to select only such num elements, whose value is an odd integer, we add this additional condition inside a predicate:
/*/num[. mod 2 = 1]
Now this last expression selects all elements named num that are children of the top element of the XML document and whose string value represents an odd integer.
. denotes the context node -- this is the node that has been selected so-far (or the starting node off which the complete XPath expression is evaluated).
In my particular case, I need to combine following pieces together ...
You forgot to say in what way / how the three expressions should be combined. In XPath some of the frequently used "combinators" are the operators and, or, and the function not().
For example, if you want to select elements that are selected by all three provided XPath expressions, you can use the and operator:
//PrimaryExpression
[not(PrimarySuffix/Arguments)
and
PrimaryPrefix/#Label='this'
]

Prolog: append a list to itself

suppose I have a list ListSum, and I want to append a new list to ListSum recursively, like
appList(ListSum):-
%%generate a list: ListTemp,
append(ListTemp,ListSum,ListSum),
appList(ListSum).
but append(ListTemp,ListSum,ListSum) didn't work in the way i wanted.
Can anyone help me out?
Cheers
You have to understand the concept of unification (or actually "matching" as implemented in Prolog). You can't bind two or more values to the same variable. Variables in Prolog once matched persisted its value until the final goal achieved, or fails somewhere. After that, if there're more possibilities then the variable is re-instantiated with another value and so on.
For example, if I query appList([]), then the append would be tested to match as:
append(ListTemp,[],[])
If ListTemp isn't empty list, this clause would fail because the semantic of append is "append the first argument with second, both are lists, resulting in the third". The recursive call to appList(ListSum) would be called as appList([]) since ListSum is matched with [] previously, resulting in infinite recursion (fortunately, if ListTemp isn't [], this won't be reached).
You must have two arguments in the clause, where one is the original list, and the other is the resulting list. The first two argument of append is then ListSum and ListTemp (depends on the append order you want), while the third is the resulting list. Done, no recursion required.
here's a non-recursive solution, not sure why you even need recursion:
appself(L,X) :- append(L,L,X).

Clone detection algorithm

I'm writing an algorithm that detects clones in source code. E.g. if there is a block like:
for(int i = o; i <5; i++){
doSomething(abc);
}
...and if this block is repeated somewhere else in the source code it will be detected as a clone. The method I am using at the moment is to create hashes for lines/blocks and compare them with hashes of other lines/blocks in the same source to see if there are any matches.
Now, if the same block as above was to be repeated somewhere with only the argument of doSomething different, it would not be detected as a clone even though it would appear very much like a clone to you and me. My algorithm detects exact matches but doesn't detect matching blocks where only the argument is different.
Could anyone suggest any ways of getting around this issue? Thanks!
Here's a super-simple way, which might go too far in erasing information (i.e., might produce too many false positives): replace every identifier that isn't a keyword with some fixed name. So you'd get
for (int DUMMY = DUMMY; DUMMY<5; DUMMY++) {
DUMMY(DUMMY);
}
(assuming you really meant o rather than 0 in the initialization part of the for-loop).
If you get a huge number of false positives with this, you could then post-process them by, for instance, looking to see what fraction of the DUMMYs actually correspond to the same identifier in both halves of the match, or at least to identifiers that are consistent between the two.
To do much better you'll probably need to parse the code to some extent. That would be a lot more work.
Well if you're going todo something else then you're going to have to parse to code at least a bit. For example you could detect methods and then ignore the method arguments in your hash. Anyway I think it's always true that you need your program to understand the code better than 'just text blocks', and that might get awefuly complicated.

Resources