implement equal function to recursion function
Asked Answered
L

2

0

I want to fix my own function that gives the same result with the default intersection function. I've been trying to write a lisp code which prints same elements in the two lists. My code works for it. But it doesn't work for nested lists. How can I fix this?

(defun printelems (L1 L2) 
(cond 
((null L1) nil) ((member (first L1) L2) (cons (first L1) (printelems (rest L1) L2)))
(t (printelems (rest L1) L2))))

Expected inputs and outputs

(printelems '(2 3 5 7) '( 2 3)) => It works
=> (2 3)
(printelems '(a b '(c f)) '(a d '(c f) e)) => It doesn't work.
=> (a (c f))

Edit

Using the default intersection function works as intended. How can I use the equal function in my recursive function?

For default intersection,

(intersection '(a b (c f)) '(a d (c f) e) :test 'equal)
((C F) A)
(intersection '(a b (c f)) '(a d c f e) :test 'equal)
(A)

My intersection,

(printelems  '(a b (c f)) '(a d c f e))
(A C F)
(printelems  '(a b (c f)) '(a d (c f) e) )
(A C F)

My edited code:

(defun flatten (l)
  (cond ((null l) nil)
    ((atom (car l)) (cons (car l) (flatten (cdr l))))
    (t (append (flatten (car l)) (flatten (cdr l))))))

(defun printelemsv1(list1 list2)
  (cond
   ((null list1) nil)
   (((member (first list1) list2) (cons (first list1) (printelemsv1 (rest list1) list2)))
   (t (printelemsv1 (rest list1) list2)))))


(defun printelems (L1 L2)
   (printelemsv1 (flatten L1) (flatten L2)))
Leeann answered 14/10, 2015 at 12:54 Comment(2)
The quote operator ' is only needed at the outmost list when writing nested lists. '(a b '(c f)) should really be '(a b (c f)). Test your version in a REPL and see the difference. Does intersect work now with help from flatten or do you still have problems?Grossman
it works but not as expected @GrossmanLeeann
S
1

Common Lisp already has an intersection function. If you want to compare sublists like (C F), you'll want to use equal or equalp as the test argument.

(intersection '(a b '(c f)) '(a d '(c f) e) :test 'equal)
;=> ('(C F) A)

While it doesn't change how intersection works, you probably don't really want quote inside your list. Quote isn't a list creation operator; it's a "return whatever the reader read" operator. The reader can read (a b (c f)) as a list of two symbols and a sublist, so (quote (a b (c f))), usually abbreviated as '(a b (c f)) is fine. E.g.:

(intersection '(a b (c f)) '(a d (c f) e) :test 'equal)
;=> ((C F) A)
Sulphanilamide answered 14/10, 2015 at 17:9 Comment(1)
I'm not sure what you're asking, exactly. You can compute the common elements using intersection. Then you can print them however you like.Sulphanilamide
G
0

It's always helpful when you provide an example of input and the expected output. I assume you mean you have two lists like '(1 (2 3) 4) and '((1) 2 5 6) that the function should produce '(1 2). In this case you can just flatten the two lists before giving them to printelems.

Since I'm not familiar with Common-Lisp itself I will leave you with one example and a link.

(defun flatten (structure)
  (cond ((null structure) nil)
        ((atom structure) (list structure))
        (t (mapcan #'flatten structure))))

Flatten a list - Rosetta Code

flatten takes an arbitrary s-expression like a nested list '(1 (2 3) 4) and returns '(1 2 3 4).

So now you just have to write a new function in which you use your printelems as a helper function and give it flattened lists.

(defun printelems.v2 (L1 L2)
   (printelems (flatten L1) (flatten L2)))

Take this with a grain of salt, since as said before I'm not familiar with Common-Lisp, so appologies in advance for any potential syntax errors.

Grossman answered 14/10, 2015 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.