I'm currently studying OCaml for a functional programming exam and I'm having some difficulties trying to follow the steps of this recursive function in this exercise. The task is to find the most expensive leaf in a int N-ary tree (a leaf cost is given by the sum of integers on the path to a leaf).
This is the type definition:
type 'a ntree = Ntree of 'a * 'a ntree list
this is an auxiliary function for the exercise
let rec maxpair = function
| [] -> failwith "empty list"
| [(x, y)] -> (x, y)
| (x, y) :: (a, b) :: rest ->
if y > b then maxpair ((x, y) :: rest)
else maxpair ((a, b) :: rest)
and finally here's the final function
let rec leaf_cost = function
| Ntree (x, []) -> (x, x)
| Ntree (x, tlist) ->
let (y, c) = maxpair (List.map leaf_cost tlist)
in
(y, c + x)
This is the solution of the exercise, meaning it works. But I'm having trouble trying to analyze every recursive step in the function, especially because I'm a bit confused about the let (y, c) ... in (y, c + x) declaration.
Given a tree, leaf_cost returns a pair (v, c) which is the value of the leaf node with the maximal cost v, and that cost c.
In the base case, when there is no child node, the value is x and its cost is also x.
In the general case, a node is made of an integer x and list of child node children (aka tlist).
List.map leaf_cost children
The above expression is a list of pairs, each one being the maximum leaf and its associated cost in the respective subtree rooted in each child node.
In general, there might be multiple leaves with the same cost, but your problem ignores that and selects, in an implementation-defined way, a pair with the maximal cost among all costs so far.
This is done by calling maxpair, which gives a pair (y, c) where y is the first leaf having the maximal cost c among all the pairs obtained recursively.
Knowing that among all subtrees, (y, c) is a leaf with cost c, and that your current node weights x, the cost of the current node is c + x. That's why the returned value in the general case is (y, c+x), keeping track of the leaf in the subtrees that lead to this cost.
Related
My code seems to run til the end (thus returning None) rather than stopping when the subtree is found.
def first_greater_than_k(tree, k):
if not tree:
return None
first_greater_than_k(tree.left, k)
if tree.data > k:
return tree
first_greater_than_k(tree.right, k)
That's because you are not returning any value in first_greater_than_k function. Also, if you have a BST (Binary Search Tree) you can do a lot better than a linear search.
Problem: Find first node that is greater than K while traversing the tree.
def first_greater_than_k(tree, k):
if not tree:
return None
if tree.data > k:
return tree
return first_greater_than_k(tree.right, k)
You don't need to recurse left child of tree as values stored there are always lower than tree's value. The running time is O(h) where h is height of the tree.
Also, a more useful question would be (maybe that's what you asked and we didn't get it):
Find first node that is greater than K if we do in-order traversal.
We can solve it using BST property of the values stated in the book Introduction to Algorithms (Cormen, page 287), 3rd Edition:
Let x be a node in a binary search tree. If y is a node in the left subtree
of x, then y.key ≤ x.key. If y is a node in the right subtree of x, then
y.key ≥ x.key.
def first_greater_than_k(tree, k):
if not tree:
return None
if k < tree.data:
x = first_greater_than_k(tree.left, k)
return x if x else tree
return first_greater_than_k(tree.right, k)
This code also has a running time of O(h) where h is height of the tree.
Original answer without recursion:
def first_greater_than_k(tree, k):
subtree, first_so_far = tree, None
while subtree:
if subtree.data > k:
first_so_far, subtree = subtree, subtree.left
else:
subtree = subtree.right
return first_so_far
By the code I can guess that you want to return the subtree whose
root's value is greater than K.
For that case, you can really improve search-run-time complexity by going into the correct halve. The idea, is, to split the tree in two halves and select the correct halve based on the value of K.
Note: I don't know the language you are using, ignore the syntactical error.
def first_greater_than_k(tree, k):
if not tree:
return None
if tree.data < k
return first_greater_than_k(tree.left, k)
if(tree.data > k)
return tree;
return first_greater_than_k(tree.right, k)
Overall runtime complexity would be O(log N) where N is the number of node in the Tree.
I'm trying to write a map function in a Haskell-like language. The operation I'm trying to use is a fold_right. So basically writing a map using foldr. However, I get a "parameter mismatch error".
Thank you.
map = lambda X. lambda Y.
lambda f: X -> Y.
lambda l: List X.
l [X] (
lambda hd:X.
lambda tl: List Y.
(cons[Y](f hd))(tl)
) (nil [Y]);
The first argument to l should be the type of the result of the fold (at least, that's my educated guess), the "motive". You want the end result to be a List Y, not an X, so you should say that:
map =
lambda X. lambda Y. lambda f: X -> Y. lambda l: List X.
l
[List Y]
(lambda x: X. lambda rec_xs: List Y. cons [Y] (f x) rec_xs)
(nil [Y]);
Maybe you got confused and wrote X because l is a List X? l already knows that it contains Xs; you don't need to point it out again. You just need to point out what you want get out (which could be X, but it isn't in this case).
I am learning to use Isabelle to prove certain theories, but I encountered a problem. I would like to know how can I define exchange(X) to ensure that the theorem presented in the code listing below can be stated without causing an error?
theorem exchange_wp2_1:
"
preOrder(T) =X # preOrder(q) # F(S) ∧ exchange(X) ∧ q ≠ null ⟹
preOrder(T)=X # (data q) # preOrder(ltree q) # F ([rtree q] # S)
"
Error:
Type unification failed:Cash of types "_list" and "_tree" Type error
in application:incompatible operand type Operator: exchange::??
'tree⇒bool Operator: X::?? 'b list
I don't know exactly the definitions of preOrder and exchange, but it seems that preOrder returns a list, whereas exchange expects a tree as input. So, in your expression, it is unclear what type X should have: is it a tree or a list?
preOrder(T) = X (so X is list)
exchange X (so X is a tree)
this is what the error message tells you.
I was reading the book Introduction to Mathematical Philosophy by B.Russell and trying to formalize all the theorems described in it.
One-many relations are described by the following text (contexts on book).
One-many relations may be defined as relations such that, if x has the
relation in question to y, there is no other term x' which also has
the relation to y.
Or, again, they may be defined as follows: Given
two terms x and x', the terms to which x has the given relation and
those to which x' has it have no member in common.
Or, again, they may
be defined as relations such that the relative product of one of them
and its converse implies identity, where the “relative product” of two
relations R and S is that relation which holds between x and z when
there is an intermediate term y, such that x has the relation R to y
and y has the relation S to z.
It poses three ways of definition. I've been successfully described the first two and proved their equivalence. While I was stuck on the third, I tried to get rid of the concepts of 'relative product' and directly get to its connotation but also failed.
Here below are my definitions, did I make any mistakes?
Definition one_many {X} (R : relation X) : Prop :=
forall x y, R x y -> forall x', x <> x' -> ~(R x' y).
Definition one_many' {X} (R : relation X) : Prop :=
forall x x' y, R x y -> R x' y -> x = x'.
Inductive relative_product
{X} (R: relation X) (S: relation X) : relation X :=
| rp0 : forall x y, forall z, R x y -> S y z -> relative_product R S x z.
Inductive converse {X} (R : relation X) : relation X :=
| cv0 : forall x y, R x y -> converse R y x.
Inductive id {X} : relation X :=
| id0 : forall x, id x x.
Definition one_many'' {X} (R : relation X) : Prop :=
forall x y, relative_product R (converse R) x y <-> id x y.
Below is how I interpret the definition of the third and also I failed to prove their equivalence.
Goal forall {X} (R : relation X),
one_many'' R <-> (forall x y, R x y -> forall x', converse R y x' -> x = x').
Proof.
intros. unfold one_many''. split.
intros.
assert (relative_product R (converse R) x x' <-> id x x'). apply H.
inversion H2. apply id_eqv. apply H3.
apply rp0 with y. assumption. assumption.
intros.
split. intro.
inversion H0. subst.
apply id_eqv. apply H with y0.
assumption. assumption.
(* I'm stuck here. This subgoal is obviously not provable. *)
in which proof, id_eqv is Lemma id_eqv : forall {X} (x:X) (y:X), x = y <-> id x y, easily proved in advance.
Can somebody help me to figure out or give me a hint about where I went wrong? Thanks in advance.
I think you've mistranslated the third definition. The original text says:
Or, again, they may be defined as relations such that the relative product of one of them and its converse implies identity
(emphasis mine). That would translate as:
forall x y, relative_product R (converse R) x y -> id x y
That is, it should be a straight implication, rather than the equivalence you've asserted. You can't hope to prove your third statement from either of the others, since it's not equivalent: consider the empty relation on a nonempty set. That's certainly a one-to-many relation, but the relative product with its converse is also empty, so is not the full identity relation.
Wild guess, but you might need R to be reflexive or not empty. Using your script I end up having to prove
1 subgoal
X : Type
R : relation X
H : forall x y : X, R x y -> forall x' : X, converse R y x' -> x = x'
y : X
______________________________________(1/1)
relative_product R (converse R) y y
So you have a relation R, and one inhabitant y:X. To prove your goal, you need to have a witness z such that R y z and R z y. Without any other information, I guess your only shot is to have R to be reflexive and z be y.
in lambda calculus (λ x. λ y. λ s. λ z. x s (y s z)) is used for addition of two Church numerals how can we explain this, is there any good resource the lambda calculus for functional programming ? your help is much appreciated
Actually λ f1. λ f2. λ s. λ z. (f1 s (f2 s z)) computes addition because it is in effect substituting (f2 s z), the number represented by f2, to the "zero" inside (f1 s z).
Example: Let's take two for f2, s s z in expanded form. f1 is one: s z. Replace that last z by f2 and you get s s s z, the expanded form for three.
This would be easier with a blackboard and hand-waving, sorry.
In lambda calculus, you code a datatype in terms of the operations it induces. For instance, a boolean is a just a choice function that takes in input two values a and b and either returns a or b:
true = \a,b.a false = \a,b.b
What is the use of a natural number? Its main computational purpose is to
provide a bound to iteration. So, we code a natural number as an operator
that takes in input a function f, a value x, and iterate the application
of f over x for n times:
n = \f,x.f(f(....(f x)...))
with n occurrences of f.
Now, if you want to iterate n + m times the function f starting from x
you must start iterating n times, that is (n f x), and then iterate for m
additional times, starting from the previous result, that is
m f (n f x)
Similarly, if you want to iterate n*m times you need to iterate m times
the operation of iterating n times f (like in two nested loops), that is
m (n f) x
The previous encoding of datatypes is more formally explained in terms
of constructors and corresponding eliminators (the so called
Bohm-Berarducci encoding).