Search code examples
listclips

How to add together the elements on the same position CLIPS


I am new to clips and I have not idea how to iterate through lists correctly and to add them together and put the sum on the same position. I have two lists defined as facts and I want to create a list that will have the sums of the lists of the elements on the same position. Ex: (deffacts lists (list 1 2 3 4) (list 1 2 3 4) ) And the result should be : (listSum 2 4 6 8)

Any help or advice is welcomed. Thank you!


Solution

  • Here's a function that will merge two lists:

             CLIPS (6.31 6/12/19)
    CLIPS> 
    (deffunction add-merge (?m1 ?m2)
       ;; Get the lengths of the multifields
       (bind ?l1 (length$ ?m1))
       (bind ?l2 (length$ ?m2))
       ;; Swap values if the first multifield is not the largest
       (if (> ?l2 ?l1)
          then
          (bind ?tmp ?l1)
          (bind ?l1 ?l2)
          (bind ?l2 ?tmp)
          (bind ?tmp ?m1)
          (bind ?m1 ?m2)
          (bind ?m2 ?tmp))
       ;; Merge the values
       (bind ?rv (create$))
       (loop-for-count (?i ?l2)
          (bind ?rv (create$ ?rv (+ (nth$ ?i ?m1) (nth$ ?i ?m2)))))
       (loop-for-count (?i (+ ?l2 1) ?l1)
          (bind ?rv (create$ ?rv (nth$ ?i ?m1))))
       ?rv)
    CLIPS> (add-merge (create$ 1 2 3 4) (create$ 5 6 7 8))
    (6 8 10 12)
    CLIPS>
    

    With the default settings in CLIPS, you can't have duplicate facts, so if you want two lists with the same values you need to create a slot that will contain a unique value for each list:

    CLIPS>    
    (deftemplate list
       (slot id (default-dynamic (gensym*)))
       (multislot values))
    CLIPS>    
    (deffacts lists
       (list (id l1) (values 1 2 3 4))
       (list (id l2) (values 1 2 3 4)))
    CLIPS>
    

    Then you can create a rule which will merge two lists:

    CLIPS>
    (defrule merge
       (sum-lists ?l1 ?l2)
       (list (id ?l1) (values $?v1))
       (list (id ?l2) (values $?v2))
       =>
       (assert (list (values (add-merge ?v1 ?v2)))))
    CLIPS> (reset)
    CLIPS> (assert (sum-lists l1 l2))
    <Fact-3>
    CLIPS> (run)
    CLIPS> (facts)
    f-0     (initial-fact)
    f-1     (list (id l1) (values 1 2 3 4))
    f-2     (list (id l2) (values 1 2 3 4))
    f-3     (sum-lists l1 l2)
    f-4     (list (id gen1) (values 2 4 6 8))
    For a total of 5 facts.
    CLIPS>