Aaron writes:
> For those who have never looked at it, teach tower introduces searching
> in Pop-11 via the problem of building a tower of a given total height
> from a set of blocks of varying heights. It's a nice simple problem to
> start with because it maps onto the problem given a set of numbers, e.g.
> [ 1 3 4 7 8 2 9] find a subset that adds up to a given target, e.g. 13.
Although this does not answer Aaron's subsequent question, I thought the
following technique for solving this problem might be of interest. We first
write a couple of familiar routines:
;;; Given a procedure, return a dynamic list. The procedure is expected
;;; to suspend in order to return its results. This is just more convenient
;;; for writing power_list.
;;;
define rptr_to_list( r ); lvars r;
pdtolist( runproc(% 0, consproc( 0, r ) %) )
enddefine;
;;; Given a list, return a list of all sublists of that list. Note that
;;; this implementation preserves order of elements. (At the expense of
;;; efficiency.) It also works on dynamic lists(!).
;;;
define power_list( L ); lvars L;
lvars sofar = [];
define lconstant solution( x ); lvars x;
conspair( x, sofar ) -> sofar;
chain( x.rev, 1, suspend )
enddefine;
procedure();
solution( [] );
lvars i, s;
for i in L do
for s in sofar do
solution( i :: s )
endfor
endfor;
termin
endprocedure.rptr_to_list
enddefine;
;;; Given a list and a predicate, create a new list, elements of which
;;; are selected from the old list using the predicate. It is important
;;; that this implementation works on dynamic lists.
;;;
define select( L, pred ); lvars L, pred;
procedure();
until null( L ) do
lvars it = L.dest -> L;
if pred( it ) then
return( it )
endif;
enduntil;
return( termin )
endprocedure.pdtolist
enddefine;
;;; Given a list of numbers, compute the sum.
;;;
define sumlist( L ); lvars L;
applist( 0, L, nonop + )
enddefine;
Now we are in a position to compute the answers. We simply select the
members of the powerlist of [ 1 3 4 7 8 2 9] that sum to 13 ....
vars answers =
select( power_list( [ 1 3 4 7 8 2 9] ), sumlist <> nonop ==#(% 13 %) );
This is a nice one-liner. Of course, we would like to see the solutions ...
: answers.hd =>
** [8 4 1]
: answers.length =>
** 6
: answers =>
** [[8 4 1] [2 8 3] [2 7 3 1] [2 7 4] [9 4] [9 3 1]]
:
Well, it amused me (and found a run-time bug in Poplog) ...
Steve
|