Thanks for the help.

In the interest of understanding (and optimization), I've included my
solution.

I'd appreciate any feedback anyone can to provide (for instance, finding 50
coins that add up to $2.00 throws an OutOfMemory exception with standard JVM
settings).

-Mitch

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Find a set of 50 coins that add up to $1.00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; prepare working memory
(clear)
(reset)

;; define the parameters (play with these for different results)
(bind ?coinCount 50)
(bind ?totalAmt 100)

;; define the coin fact template
(deftemplate coin (slot denomination) (slot count) (slot amount))

;; assert all possible coin facts
(foreach ?denom (create$ half-dollar quarter dime nickel penny)
        (bind ?count 0)
        (bind ?total 0)

        ;; assign the appropriate amounts
        (if (eq ?denom half-dollar) then (bind ?amount 50) else
                (if (eq ?denom quarter) then (bind ?amount 25)) else
                (if (eq ?denom dime) then (bind ?amount 10)) else
                (if (eq ?denom nickel) then (bind ?amount 5)) else
                (if (eq ?denom penny) then (bind ?amount 1)))

        ;; assert the necessary coin facts
        (while (and (<= ?total ?totalAmt) (<= ?count ?coinCount)) do
                ;; add the fact
                (assert (coin (denomination ?denom) (count ?count) (amount ?total)))

                ;; tally the total amount
                (bind ?total (+ ?total ?amount))
                (bind ?count (+ ?count 1))
                )
        )

;; define the rules to find the combination of facts such that
;; the coin count equals ?coinCount and the amount equals ?totalAmt.
;;
;; ?cX - # of coins, ?aX amount of currency
(defrule find-solution
        (coin (denomination penny) (count ?cp) (amount ?ap))
        (coin (denomination nickel) (count ?cn) (amount ?an))
        (coin (denomination dime) (count ?cd) (amount ?ad))
        (coin (denomination quarter) (count ?cq) (amount ?aq))
        (coin (denomination half-dollar) (count ?ch) (amount ?ah))
        =>
        (if (and (eq (+ ?cp ?cn ?cd ?cq ?ch) ?coinCount)
                        (eq (+ ?ap ?an ?ad ?aq ?ah) ?totalAmt)) then
        (printout t "Solution : " ?cp " pennies, " ?cn " nickels, " ?cd " dimes, "
?cq " quarters, " ?ch " half-dollars" crlf)))

;; solve...
(run)


-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
Behalf Of [EMAIL PROTECTED]
Sent: Monday, August 11, 2003 8:27 AM
To: [EMAIL PROTECTED]
Subject: Re: JESS: Newbie question (Coin puzzle)


I think Mitch Christensen wrote:
[Charset iso-8859-1 unsupported, filtering to ASCII...]
>
> PROBLEM: Define a set of coins amounting to exactly $1.00 using exactly 50
> coins.
>
> APPROACH: I thought I'd assert he following facts,
>
>   2 Half dollar facts
>   4 Quarter facts
>  10 Dime facts
>  20 Nickel facts
> 100 Penny facts
>
> Then define a rule to print the facts such that the number of facts
(coins)
> is 50 and the value of the 50 facts equals 100 ($1.00).

Since the problem isn't to determine -which- of the 100 pennies to
use, for example, it's really unnecessary to represent each one
individually. If it -were- necessary, then you'd want to be able to
distinguish them, somehow, so you'd give them an identifier:

(deftemplate coin (slot type) (slot id (default-value (gensym*))))
(deftemplate coin-type (slot type) (slot value))

(bind ?count 50)
(while (> ?count 0)
  (assert (coin (type penny))))

Each penny would then be unique.

But I don't think I would do it this way. What if you had facts like

(penny-count 0)
(penny-count 1)
(penny-count 2)
...
(penny-count 50)

(nickel-count 0)
(nickel-count 1)
(nickel-count 2)
...


And then wrote a rule that matched one penny-count fact, one
nickel-count fact, etc, such that the counts summed to 50, and the
amounts summed to $1.00?

---------------------------------------------------------
Ernest Friedman-Hill
Distributed Systems Research        Phone: (925) 294-2154
Sandia National Labs                FAX:   (925) 294-2234
PO Box 969, MS 9012                 [EMAIL PROTECTED]
Livermore, CA 94550         http://herzberg.ca.sandia.gov

--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify [EMAIL PROTECTED]
--------------------------------------------------------------------

--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify [EMAIL PROTECTED]
--------------------------------------------------------------------

Reply via email to