[mercury-users] challenge
David Matthew Overton
dmo at cs.mu.OZ.AU
Mon Sep 28 13:48:53 AEST 1998
On Fri, Sep 25, 1998 at 10:58:08PM EST, Peter Schachte wrote:
> Here's a programming challenge that should be a bit more interesting
> than writing rot13 in Mercury. Given a type
>
> :-type tree(T) ---> empty ; tree(tree(T), T, tree(T)).
>
> write a predicate
>
> :- pred collect_pairs(tree(T), tree(T), list(pair(T))).
> :- mode collect_pairs(in, in, out).
>
> collect_pairs(T, U, L) should hold exactly when L is a list of
> corresponding elements of T and U in an inorder traversal of the
> trees. The catch is that T and U may not be the same shape. You can
> assume the trees will contain the same numbers of nodes if you like,
> or just collect as many pairs as there are nodes in the smaller tree.
> Take your pick.
>
> Oh, and no fair turning T and U into lists and then operating on the
> lists. What I'm looking for is code to traverse two different-shaped
> trees at once. I speculate that there is no reasonably elegant way to
> do it, but I'd be delighted to be proved wrong.
>
Here's a solution using higher order predicates to traverse the trees
lazily. Does this count as a ``reasonably elegant'' solution, Peter?
%%%%%
:- module challenge.
:- interface.
:- import_module list, std_util.
:- type tree(T)
---> empty
; tree(tree(T), T, tree(T)).
:- pred collect_pairs(tree(T), tree(T), list(pair(T))).
:- mode collect_pairs(in, in, out) is det.
:- implementation.
collect_pairs(Tree1, Tree2, List) :-
collect_pairs_2(get_elements([Tree1]), get_elements([Tree2]), List).
:- type next(T)
---> next(T, pred(next(T))).
:- inst next
---> next(ground, pred(out(next)) is semidet).
:- pred collect_pairs_2(pred(next(T)), pred(next(T)), list(pair(T))).
:- mode collect_pairs_2(pred(out(next)) is semidet,
pred(out(next)) is semidet, out) is det.
collect_pairs_2(P1, P2, L) :-
(
P1(next(E1, P1Prime)),
P2(next(E2, P2Prime))
->
L = [E1 - E2 | L0],
collect_pairs_2(P1Prime, P2Prime, L0)
;
L = []
).
:- pred get_elements(list(tree(T)), next(T)).
:- mode get_elements(in, out(next)) is semidet.
get_elements([empty | Trees], R) :-
get_elements(Trees, R).
get_elements([tree(L, E, R) | Trees], next(E, get_elements([L, R | Trees]))).
%%%%%
David
--
David Overton
MEngSc Student Email: dmo at cs.mu.oz.au
Department of Computer Science Web: http://www.cs.mu.oz.au/~dmo
The University of Melbourne Phone: +61 3 9344 9159
More information about the users
mailing list