From: Ray Godfrey
Subject: Help!!
Date: 
Message-ID: <1421dc84.0304230632.5d92ff6b@posting.google.com>
Would anyone be kind enough to help, or even do this for me? :(

Create a garden design recommender system in Lisp.


--------------------------------------------------------------------------------

The purpose of this system is to recommend: a garden surface, a type
of plant, a type of tree, and a feature for a garden.  The system only
considers 4 attributes: garden size, budget, how easy to maintain the
garden must be, and how safe the garden must be (e.g. for children). 
An initial interview with the user is used to gain this information,
and based on these the system will create a list of suitable
recommendations.  The user can view these recommendations, and refine
them by deciding that a particular item (surface, plant, etc.) must
(or must not) be included in the recommendations (thus filtering down
the recommendations).  The system will also be able to show the
cheapest of the current recommendations.


--------------------------------------------------------------------------------

The following starter code is given, and should be used unaltered:

(defvar *surfaces* '((grass 1 7 9) (concrete 7 1 1) (gravel 4 2 7)
(paving-stones 8 2 1) (decking 8 4 3)
(bark-chipping 6 3 10)))

(defvar *plants* '((roses 3 2 6) (cactus 3 1 4) (bonsai 8 4 10) (ivy 4
5 9) (daffodils 2 2 10)))

(defvar *trees* '((birch 5 1 10) (chestnut 7 3 8) (willow 6 2 10)
(eucalyptus 5 5 10)))

(defvar *garden-features* '((fountain 6 3 3) (pond 7 5 1) (rockery 2 2
8) (herb-garden 5 7 9)))

(defvar *current-recs* nil)

The global variables *surfaces*, *plants*, *trees* and
*garden-features* are lists containing items stored as sublists in the
form: (<item name> <cost factor> <maintenance factor> <safety
factor>).  All factors are in the range 1-10.  For cost, 1=very cheap,
10=very expensive.  For maintenance, 1=very low maintenance, 10=very
high maintenance.  For safety, 10=very safe, 1=not safe.  The final
global *current-recs* holds the list of current recommendations, which
can be viewed or further filtered down, etc.


--------------------------------------------------------------------------------

You should implement the following functions for your system:

start-rec.  This function, which takes no arguments, is the starting
point for making new recommendations.  It asks the user about the
size, budget, maintenance and safety requirements (see above) of the
garden in question.  It then invokes the make-recommendations function
to get a list of all initial recommendations.  This list of initial
recommendations is assigned to *current-recs* and the total number of
initial recommendations is displayed.
make-recommendations.  This function takes 4 arguments: size, budget,
maintenance and safety.  It compiles (and returns) an exhaustive list
of suitable recommendations.  Each recommendation contains one
surface, one plant type, one tree type, and one garden feature.  Each
recommendation also includes a total cost of the recommendation for
the garden in question (size matters, etc.).  Example: (GRASS ROSES
BIRCH FOUNTAIN (TOTAL-COST 450)).  Note: recommendations must be in
this exact format!  A recommendation is suitable if all 4 items in it
have maintenance factors <= the one specified, and safety factors >=
the one specified, and the total cost for the garden <= budget.  A
recommendation can be costed by passing a list of items to cost e.g.
(GRASS ROSES BIRCH FOUNTAIN), to cost-item-list along with the garden
size.
cost-item-list.  This function takes a list of items (i.e. plants,
trees, surfaces, etc.) along with the size of the garden in question
and returns the total cost. It invokes cost-item to calculate the cost
of individual items and tallys these to find the total cost.
cost-item.  This function takes an item name (e.g. GRASS) and a garden
size.  It calculates the item's cost as follows:
For surfaces: cost factor * size * 3
For plants: cost factor * size
For trees: ( cost factor * size ) + 20
For garden features: cost factor * 35
show-recs.  This function takes no arguments.  It displays the total
number of current recommendations (in *current-recs*), and prompts the
user to enter a range of recommendations to view (e.g. view
recommendations 20 to 35).  The recommendations in the range are
displayed and numbered.
cheapest-recs.  This function takes no arguments.  It prints out the
cheapest of the current recommendations (which will be 1 or more
recommendations).
must-have.  This function takes a item name as its only argument.  It
removes any recommendations from *current-recs* which do not include
the given item.  It displays how many recommendations have been
removed and how many remain.
cannot-have.  This function takes a item name as its only argument. 
It removes any recommendations from *current-recs* which include the
given item. It displays how many recommendations have been removed and
how many remain.
Note that you will probably have to implement additional helper
functions in addition to the above.  The above functions, however,
must work precisely as outlined above.


--------------------------------------------------------------------------------

Sample Run of System

CL-USER 1 > (start-rec)

What is the size of your garden in sq yards?: 25

What is your total budget?: 600

How much time can you give for maintaining your garden (1=none,
10=lots)?: 7

How important is garden safety to you (1=not important, 10=very
important)?: 2

There are a total of 61 recommendations
NIL

CL-USER 2 > (show-recs)

There are 61 current recommendations.
View recommendations from (1-61): 1
to (1-61): 61

Recommendation 1: (GRASS ROSES BIRCH FOUNTAIN (TOTAL-COST 505))
Recommendation 2: (GRASS ROSES BIRCH ROCKERY (TOTAL-COST 365))
Recommendation 3: (GRASS ROSES BIRCH HERB-GARDEN (TOTAL-COST 470))
Recommendation 4: (GRASS ROSES CHESTNUT FOUNTAIN (TOTAL-COST 555))
Recommendation 5: (GRASS ROSES CHESTNUT ROCKERY (TOTAL-COST 415))
Recommendation 6: (GRASS ROSES CHESTNUT HERB-GARDEN (TOTAL-COST 520))
Recommendation 7: (GRASS ROSES WILLOW FOUNTAIN (TOTAL-COST 530))
Recommendation 8: (GRASS ROSES WILLOW ROCKERY (TOTAL-COST 390))
Recommendation 9: (GRASS ROSES WILLOW HERB-GARDEN (TOTAL-COST 495))
Recommendation 10: (GRASS ROSES EUCALYPTUS FOUNTAIN (TOTAL-COST 505))
Recommendation 11: (GRASS ROSES EUCALYPTUS ROCKERY (TOTAL-COST 365))
Recommendation 12: (GRASS ROSES EUCALYPTUS HERB-GARDEN (TOTAL-COST
470))
Recommendation 13: (GRASS CACTUS BIRCH FOUNTAIN (TOTAL-COST 505))
Recommendation 14: (GRASS CACTUS BIRCH ROCKERY (TOTAL-COST 365))
Recommendation 15: (GRASS CACTUS BIRCH HERB-GARDEN (TOTAL-COST 470))
Recommendation 16: (GRASS CACTUS CHESTNUT FOUNTAIN (TOTAL-COST 555))
Recommendation 17: (GRASS CACTUS CHESTNUT ROCKERY (TOTAL-COST 415))
Recommendation 18: (GRASS CACTUS CHESTNUT HERB-GARDEN (TOTAL-COST
520))
Recommendation 19: (GRASS CACTUS WILLOW FOUNTAIN (TOTAL-COST 530))
Recommendation 20: (GRASS CACTUS WILLOW ROCKERY (TOTAL-COST 390))
Recommendation 21: (GRASS CACTUS WILLOW HERB-GARDEN (TOTAL-COST 495))
Recommendation 22: (GRASS CACTUS EUCALYPTUS FOUNTAIN (TOTAL-COST 505))
Recommendation 23: (GRASS CACTUS EUCALYPTUS ROCKERY (TOTAL-COST 365))
Recommendation 24: (GRASS CACTUS EUCALYPTUS HERB-GARDEN (TOTAL-COST
470))
Recommendation 25: (GRASS BONSAI BIRCH ROCKERY (TOTAL-COST 490))
Recommendation 26: (GRASS BONSAI BIRCH HERB-GARDEN (TOTAL-COST 595))
Recommendation 27: (GRASS BONSAI CHESTNUT ROCKERY (TOTAL-COST 540))
Recommendation 28: (GRASS BONSAI WILLOW ROCKERY (TOTAL-COST 515))
Recommendation 29: (GRASS BONSAI EUCALYPTUS ROCKERY (TOTAL-COST 490))
Recommendation 30: (GRASS BONSAI EUCALYPTUS HERB-GARDEN (TOTAL-COST
595))
Recommendation 31: (GRASS IVY BIRCH FOUNTAIN (TOTAL-COST 530))
Recommendation 32: (GRASS IVY BIRCH ROCKERY (TOTAL-COST 390))
Recommendation 33: (GRASS IVY BIRCH HERB-GARDEN (TOTAL-COST 495))
Recommendation 34: (GRASS IVY CHESTNUT FOUNTAIN (TOTAL-COST 580))
Recommendation 35: (GRASS IVY CHESTNUT ROCKERY (TOTAL-COST 440))
Recommendation 36: (GRASS IVY CHESTNUT HERB-GARDEN (TOTAL-COST 545))
Recommendation 37: (GRASS IVY WILLOW FOUNTAIN (TOTAL-COST 555))
Recommendation 38: (GRASS IVY WILLOW ROCKERY (TOTAL-COST 415))
Recommendation 39: (GRASS IVY WILLOW HERB-GARDEN (TOTAL-COST 520))
Recommendation 40: (GRASS IVY EUCALYPTUS FOUNTAIN (TOTAL-COST 530))
Recommendation 41: (GRASS IVY EUCALYPTUS ROCKERY (TOTAL-COST 390))
Recommendation 42: (GRASS IVY EUCALYPTUS HERB-GARDEN (TOTAL-COST 495))
Recommendation 43: (GRASS DAFFODILS BIRCH FOUNTAIN (TOTAL-COST 480))
Recommendation 44: (GRASS DAFFODILS BIRCH ROCKERY (TOTAL-COST 340))
Recommendation 45: (GRASS DAFFODILS BIRCH HERB-GARDEN (TOTAL-COST
445))
Recommendation 46: (GRASS DAFFODILS CHESTNUT FOUNTAIN (TOTAL-COST
530))
Recommendation 47: (GRASS DAFFODILS CHESTNUT ROCKERY (TOTAL-COST 390))
Recommendation 48: (GRASS DAFFODILS CHESTNUT HERB-GARDEN (TOTAL-COST
495))
Recommendation 49: (GRASS DAFFODILS WILLOW FOUNTAIN (TOTAL-COST 505))
Recommendation 50: (GRASS DAFFODILS WILLOW ROCKERY (TOTAL-COST 365))
Recommendation 51: (GRASS DAFFODILS WILLOW HERB-GARDEN (TOTAL-COST
470))
Recommendation 52: (GRASS DAFFODILS EUCALYPTUS FOUNTAIN (TOTAL-COST
480))
Recommendation 53: (GRASS DAFFODILS EUCALYPTUS ROCKERY (TOTAL-COST
340))
Recommendation 54: (GRASS DAFFODILS EUCALYPTUS HERB-GARDEN (TOTAL-COST
445))
Recommendation 55: (GRAVEL ROSES BIRCH ROCKERY (TOTAL-COST 590))
Recommendation 56: (GRAVEL ROSES EUCALYPTUS ROCKERY (TOTAL-COST 590))
Recommendation 57: (GRAVEL CACTUS BIRCH ROCKERY (TOTAL-COST 590))
Recommendation 58: (GRAVEL CACTUS EUCALYPTUS ROCKERY (TOTAL-COST 590))
Recommendation 59: (GRAVEL DAFFODILS BIRCH ROCKERY (TOTAL-COST 565))
Recommendation 60: (GRAVEL DAFFODILS WILLOW ROCKERY (TOTAL-COST 590))
Recommendation 61: (GRAVEL DAFFODILS EUCALYPTUS ROCKERY (TOTAL-COST
565))
NIL

CL-USER 3 > (cannot-have 'gravel)
7 recommendations removed.
54 recommendations remaining.
NIL

CL-USER 4 > (must-have 'fountain)
38 recommendations removed.
16 recommendations remaining.
NIL

CL-USER 5 > (show-recs)

There are 16 current recommendations.
View recommendations from (1-16): 1
to (1-16): 16

Recommendation 1: (GRASS ROSES BIRCH FOUNTAIN (TOTAL-COST 505))
Recommendation 2: (GRASS ROSES CHESTNUT FOUNTAIN (TOTAL-COST 555))
Recommendation 3: (GRASS ROSES WILLOW FOUNTAIN (TOTAL-COST 530))
Recommendation 4: (GRASS ROSES EUCALYPTUS FOUNTAIN (TOTAL-COST 505))
Recommendation 5: (GRASS CACTUS BIRCH FOUNTAIN (TOTAL-COST 505))
Recommendation 6: (GRASS CACTUS CHESTNUT FOUNTAIN (TOTAL-COST 555))
Recommendation 7: (GRASS CACTUS WILLOW FOUNTAIN (TOTAL-COST 530))
Recommendation 8: (GRASS CACTUS EUCALYPTUS FOUNTAIN (TOTAL-COST 505))
Recommendation 9: (GRASS IVY BIRCH FOUNTAIN (TOTAL-COST 530))
Recommendation 10: (GRASS IVY CHESTNUT FOUNTAIN (TOTAL-COST 580))
Recommendation 11: (GRASS IVY WILLOW FOUNTAIN (TOTAL-COST 555))
Recommendation 12: (GRASS IVY EUCALYPTUS FOUNTAIN (TOTAL-COST 530))
Recommendation 13: (GRASS DAFFODILS BIRCH FOUNTAIN (TOTAL-COST 480))
Recommendation 14: (GRASS DAFFODILS CHESTNUT FOUNTAIN (TOTAL-COST
530))
Recommendation 15: (GRASS DAFFODILS WILLOW FOUNTAIN (TOTAL-COST 505))
Recommendation 16: (GRASS DAFFODILS EUCALYPTUS FOUNTAIN (TOTAL-COST
480))
NIL

CL-USER 6 > (cheapest-recs)

(GRASS DAFFODILS BIRCH FOUNTAIN (TOTAL-COST 480)) 
(GRASS DAFFODILS EUCALYPTUS FOUNTAIN (TOTAL-COST 480)) 
NIL

CL-USER 7 >

From: Matthieu Villeneuve
Subject: Re: Help!!
Date: 
Message-ID: <3ea6a65d$0$28768$626a54ce@news.free.fr>
"Ray Godfrey" <··········@yahoo.com> wrote in message
·································@posting.google.com...
> Would anyone be kind enough to help, or even do this for me? :(

It wouldn't be kind to do your homework for you. On the other hand, many
people here would be kind enough to help you, provided you show some
interest and some work on your side.

So, start thinking about the problem, try to think about solutions (even if
they don't work), then come back for more detailed questions.

--
Matthieu Villeneuve
From: Henrik Motakef
Subject: Re: Help!!
Date: 
Message-ID: <87adeh5ksg.fsf@interim.henrik-motakef.de>
··········@yahoo.com (Ray Godfrey) writes:

> Would anyone be kind enough to help, or even do this for me? :(
[Homework assignment]

Help, yes. But you cannot expect someone to do your homework for
free. (And remember that this is a public, archived forum, your
teacher could read all this.)

The best is probably if you start on your own and see how far you get,
and ask specific questions when you are stuck.

Regards
Henrik
From: Paolo Amoroso
Subject: Re: Help!!
Date: 
Message-ID: <s+mmPgsWA0pxQ6P86lCCxTOXXDjE@4ax.com>
On Wed, 23 Apr 2003 16:51:43 +0200, Henrik Motakef <··············@web.de>
wrote:

> ··········@yahoo.com (Ray Godfrey) writes:
> 
> > Would anyone be kind enough to help, or even do this for me? :(
> [Homework assignment]
> 
> Help, yes. But you cannot expect someone to do your homework for
> free. (And remember that this is a public, archived forum, your
> teacher could read all this.)

And possibly also potential employers.


Paolo
-- 
Paolo Amoroso <·······@mclink.it>
From: Ray Godfrey
Subject: Re: Help!!
Date: 
Message-ID: <1421dc84.0304280655.73cf95fc@posting.google.com>
i've done this much and now i'm struggling, could anyone help, maybe
with the must-have? plewase? :(
(defvar *surfaces* '((grass 1 7 9) (concrete 7 1 1) (gravel 4 2 7)
(paving-stones 8 2 1) (decking 8 4 3)
(bark-chipping 6 3 10)))

(defvar *plants* '((roses 3 2 6) (cactus 3 1 4) (bonsai 8 4 10) (ivy 4
5 9) (daffodils 2 2 10)))

(defvar *trees* '((birch 5 1 10) (chestnut 7 3 8) (willow 6 2 10)
(eucalyptus 5 5 10)))

(defvar *garden-features* '((fountain 6 3 3) (pond 7 5 1) (rockery 2 2
8) (herb-garden 5 7 9)))

(defvar *current-recs* nil)


(defun start-rec()
(let (size budget maintenance safety)
(format t "What is the size of your garden in square yards?:")
(setf size (read))
(format t "~%What is your total budget?:")
(setf budget(read))
(format t "~%How much time can you give for maintaining your garden
(1=none, 10=lots)?:")
(setf maintenance(read))
(format t "~%How important is garden safety to you (1=not important,
10=very important)?:")
(setf safety(read))

(setf *current-recs* (make-recommendations size budget maintenance
safety))
(format t "~%There are ~a recommendations" (length *current-recs*))
)

(defun make-recommendation(size budget maintenance safety)
	(let (result)
	(dolist (a *surfaces*)
	 (dolist (b *plants*)
	   (dolist (c *trees*)
	     (dolist (d *garden-features*)
 		(if (and (>= maintenance (caddr a)) (>= maintenance (caddr b)) (>=
maintenance (caddr c))(>= maintenance (caddr d))
			 (<= safety (cadddr a))) (<= safety (cadddr b))) (<= safety (cadddr
c))) (<= safety (cadddr d)))
			  
				(setf result (append result (list (list (car a) (car b) (car c)
(car d))))))
	     
	))))
	result
))




(defun show-recs(*current-recs*)
(format t "~%There are ~a number of recommendations"(length
*current-recs*))
(format t "~%View recommendations from (1-~a):"(length
*current-recs*))
(setf start(read))
(format t "to (1-~a):"(length *current-recs*))
(setf end(read))
(dolist (p *current-recs*)(print p))


(defun cost-item-list((one list from current-recs)
	


(defun cost-item (item size)
 (let (cost)
 (dolist (x *surfaces*) (if (equal (car x) item) (setf cost (* (cadr
x) size 3))))

 (dolist (y *plants*) (if (equal (car y) item) (setf cost (* (cadr y)
size))))

 (dolist (z *trees*) (if (equal (car z) item) (setf cost (+ 20 (*
(cadr z) size)))))

 (dolist (p *garden-features*) (if (equal (car p) item) (setf cost (*
(cadr p) 35))))
cost
))

(defun cheapest-recs()



(defun must-have(item)
  

(defun cannot-have(item)
 (if head of the list is eql to the item passed in then remove that
list from current-recs.
From: Martti Halminen
Subject: Re: Help!!
Date: 
Message-ID: <3EAD9565.A54305EF@kolumbus.fi>
Ray Godfrey wrote:
> 
> i've done this much and now i'm struggling, could anyone help, maybe
> with the must-have? plewase? :(

The first thing to do when writing Lisp code is to get your hands on an
editor which can count parentheses and indent your code for you, and use
those features: reading unindented Lisp is far too painful. Either
whatever editor came with your Lisp system, or some variant of Emacs is
usually recommended.

> (defun start-rec()
> (let (size budget maintenance safety)
> (format t "What is the size of your garden in square yards?:")
> (setf size (read))
> (format t "~%What is your total budget?:")
> (setf budget(read))
> (format t "~%How much time can you give for maintaining your garden
> (1=none, 10=lots)?:")
> (setf maintenance(read))
> (format t "~%How important is garden safety to you (1=not important,
> 10=very important)?:")
> (setf safety(read))
> 
> (setf *current-recs* (make-recommendations size budget maintenance
> safety))
> (format t "~%There are ~a recommendations" (length *current-recs*))
> )

- Here you are missing a closing paren. All defuns should be top-level
code, use FLET or LABELS if you are defining helper functions inside a
function.

- In any kind of realistic use you should have some kind of input sanity
checking: raw (read) can produce just about any kind of Lisp object,
there is no guarantee that the user actually gave a number.


> (defun make-recommendation(size budget maintenance safety)
>         (let (result)
>         (dolist (a *surfaces*)
>          (dolist (b *plants*)
>            (dolist (c *trees*)
>              (dolist (d *garden-features*)
>                 (if (and (>= maintenance (caddr a)) (>= maintenance (caddr b)) (>=
> maintenance (caddr c))(>= maintenance (caddr d))
>                          (<= safety (cadddr a))) (<= safety (cadddr b))) (<= safety (cadddr
> c))) (<= safety (cadddr d)))
> 
>                                 (setf result (append result (list (list (car a) (car b) (car c)
> (car d))))))
> 
>         ))))
>         result
> ))
> 

Here's how Emacs indented the previous (+ a few <cr>'s added), minus
whatever Netscape clobbers...

(defun make-recommendation(size budget maintenance safety)
  (let (result)
    (dolist (a *surfaces*)
      (dolist (b *plants*)
	(dolist (c *trees*)
	  (dolist (d *garden-features*)
	    (if (and (>= maintenance (caddr a))
		     (>= maintenance (caddr b))
		     (>= maintenance (caddr c))
		     (>= maintenance (caddr d))
		     (<= safety (cadddr a)))
		(<= safety (cadddr b)))
	    (<= safety (cadddr c)))
	  (<= safety (cadddr d)))
	
	(setf result (append result (list (list (car a) (car b) (car c)
						(car d))))))
      
      ))))
result
))

- Seems to me to do something very odd, a few too many parens in the
safety comparisions?
- Using append here is rather inefficient. Its easier to add the new
stuff to the start of the list:
  (push (list (car a)(car b)(car c)(car d)) result)
  Generally, as a rule of thumb, append should not be used in beginner
code,   almost every time there is some better way to do it...

> (defun show-recs(*current-recs*)
> (format t "~%There are ~a number of recommendations"(length
> *current-recs*))  ...)

This is quite likely an error: the *current-recs* here is NOT the same
as the *current-recs* created by a defvar. Try (defun show-recs () 
...).

> (defun cost-item (item size)
>  (let (cost)
>  (dolist (x *surfaces*) (if (equal (car x) item) (setf cost (* (cadr
> x) size 3))))
> 
>  (dolist (y *plants*) (if (equal (car y) item) (setf cost (* (cadr y)
> size))))
> 
>  (dolist (z *trees*) (if (equal (car z) item) (setf cost (+ 20 (*
> (cadr z) size)))))
> 
>  (dolist (p *garden-features*) (if (equal (car p) item) (setf cost (*
> (cadr p) 35))))
> cost
> ))

This seems to be rather inefficient (not that it matters with
present-day machines for a toy example): even after an item is found,
this goes through all the remaining choices, too.

> 
> (defun must-have(item)

Something like

(defun must-have (item)
   (let ((orig-length (length *current-recs*)))
     (setq *current-recs* 
           (remove-if-not #'(lambda (rec) (member item rec))
                          *current-recs*))
     <add reporting code here>
     ))  ;; untested

--
From: Raymond Wiker
Subject: Re: Help!!
Date: 
Message-ID: <868ytt21ow.fsf@raw.grenland.fast.no>
Martti Halminen <···············@kolumbus.fi> writes:

> (defun make-recommendation(size budget maintenance safety)
>   (let (result)
>     (dolist (a *surfaces*)
>       (dolist (b *plants*)
> 	(dolist (c *trees*)
> 	  (dolist (d *garden-features*)
> 	    (if (and (>= maintenance (caddr a))
> 		     (>= maintenance (caddr b))
> 		     (>= maintenance (caddr c))
> 		     (>= maintenance (caddr d))
> 		     (<= safety (cadddr a)))
> 		(<= safety (cadddr b)))
> 	    (<= safety (cadddr c)))
> 	  (<= safety (cadddr d)))
> 	
> 	(setf result (append result (list (list (car a) (car b) (car c)
> 						(car d))))))
>       
>       ))))
> result
> ))
> 
> - Seems to me to do something very odd, a few too many parens in the
> safety comparisions?

        Definitely :-)

> - Using append here is rather inefficient. Its easier to add the new
> stuff to the start of the list:
>   (push (list (car a)(car b)(car c)(car d)) result)
>   Generally, as a rule of thumb, append should not be used in beginner
> code,   almost every time there is some better way to do it...

(defun make-recommendations (size budget maintenance safety)
  (flet ((acceptable (item)
           (and (>= maintenance (third item))
                (<= safety (fourth item)))))
    (let (result)
      (dolist (a *surfaces*)
        (when (acceptable a)
          (dolist (b *plants*)
            (when (acceptable b)
              (dolist (c *trees*)
                (when (acceptable c)
                  (dolist (d *garden-features*)
                    (when (acceptable d)
                      (let* ((items 
                              (mapcar #'first (list a b c d)))
                             (tot-cost
                              (cost-item-list  items size)))
                        (when (<= tot-cost budget)
                          (push (nconc items 
                                       (list (list 'total-cost tot-cost)))
                                result)))))))))))
      (nreverse result))))

> > (defun show-recs(*current-recs*)
> > (format t "~%There are ~a number of recommendations"(length
> > *current-recs*))  ...)
> 
> This is quite likely an error: the *current-recs* here is NOT the same
> as the *current-recs* created by a defvar. Try (defun show-recs () 
> ...).
> 
> > (defun cost-item (item size)
> >  (let (cost)
> >  (dolist (x *surfaces*) (if (equal (car x) item) (setf cost (* (cadr
> > x) size 3))))
> > 
> >  (dolist (y *plants*) (if (equal (car y) item) (setf cost (* (cadr y)
> > size))))
> > 
> >  (dolist (z *trees*) (if (equal (car z) item) (setf cost (+ 20 (*
> > (cadr z) size)))))
> > 
> >  (dolist (p *garden-features*) (if (equal (car p) item) (setf cost (*
> > (cadr p) 35))))
> > cost
> > ))
> 
> This seems to be rather inefficient (not that it matters with
> present-day machines for a toy example): even after an item is found,
> this goes through all the remaining choices, too.

(defun cost-item (item size)
  (flet ((try-it (items cost-func)
           (let ((rec (find item items :key #'car)))
             (when rec
               (funcall cost-func (second rec))))))
    (or
     (try-it *surfaces* (lambda (base-cost) (* base-cost size 3)))
     (try-it *plants* (lambda (base-cost) (* base-cost size)))
     (try-it *trees* (lambda (base-cost) (+ 20 (* base-cost size))))
     (try-it *garden-features* (lambda (base-cost) (* base-cost 35)))
     (error "Couldn't compute cost for ~a~%" item))))
> 
> > 
> > (defun must-have(item)
> 
> Something like
> 
> (defun must-have (item)
>    (let ((orig-length (length *current-recs*)))
>      (setq *current-recs* 
>            (remove-if-not #'(lambda (rec) (member item rec))
>                           *current-recs*))
>      <add reporting code here>
>      ))  ;; untested

(defun must-have (item)
  (let ((l1 (length *current-recs*)))
    (setq *current-recs*
          (remove item *current-recs* :test (complement #'member)))
    (let ((l2 (length *current-recs*)))
      (format t "~&~a recommendations removed.~%" (- l1 l2))
      (format t "~a recommendations remaining.~%" l2))))

-- 
Raymond Wiker                        Mail:  ·············@fast.no
Senior Software Engineer             Web:   http://www.fast.no/
Fast Search & Transfer ASA           Phone: +47 23 01 11 60
P.O. Box 1677 Vika                   Fax:   +47 35 54 87 99
NO-0120 Oslo, NORWAY                 Mob:   +47 48 01 11 60

Try FAST Search: http://alltheweb.com/