How do I obtain a cross product with multiple tables? - racket

I am trying to obtain a cross product between two lists. I can see that the problem is that it's trying to append (CP2 T1 T2) with (CP2 T1 T3). I have thought of other ways, such as (CP2 (CP2 T1 T2) ...), but again, the ellipses just expand into an undesired output.
(define-syntax CP
(syntax-rules ()
((CP T1 T2 ...)
(append (CP2 T1 T2) ...)
)
)
)
(define (CP2 T1 T2)
(foldr append '() (map (λ(x)
(map (λ(y) (append x y)) T2))
T1))
)
Is it not possible doing it this way at all?
Thank you.

It can be done with one of the for loops also ( http://docs.racket-lang.org/reference/for.html ):
(define (myproduct l1 l2)
(for*/list ((i l1)(j l2))
(list i j)))
(myproduct '(1 2 3) '(a b c))
Ouput:
'((1 a) (1 b) (1 c) (2 a) (2 b) (2 c) (3 a) (3 b) (3 c))

Related

Why the below lisp code is not giving desired result

I have a list
'((1 2 (A B C)) (2 3 (B C D)) (4 5 (C D F)))
I want to process the elements in the inner list, (in this case, I want to change (A B C) and other lists to (M M M)).
I wrote a code (process lst), which will do this task for the inner list.
(defun process (lst)
(cond
((null lst) '())
(T (cons 'M (process (cdr last))))))
And when I call from the main function,
(defun iterate-list (lst)
(cond
((null lst) '())
((listp (car lst))
(cons (process (car lst))
(iterate-list (cdr lst))))
(T
(cons (car lst)
(iterate-list (cdr lst))))))
I am getting ((M M M) (M M M) (M M M)) instead of ((1 2 (M M M)) (2 3 (M M M)) (4 5 (M M M))).
But when I use the same function, with just (cons (car lst)) (iterate-list (cdr lst))) in the second condition (listp (car lst)), I am getting the correct answer, that is
'((1 2 (A B C)) (2 3 (B C D)) (4 5 (C D F)))
I don't know where I am making the mistake.
If you want something practical, I would suggest the subst function from the Common LISP Standard Library.
http://clhs.lisp.se/Body/f_substc.htm
(setq tree1 '(1 (1 2) (1 2 3) (1 2 3 4))) => (1 (1 2) (1 2 3) (1 2 3 4))
(subst "two" 2 tree1) => (1 (1 "two") (1 "two" 3) (1 "two" 3 4))
(subst "five" 5 tree1) => (1 (1 2) (1 2 3) (1 2 3 4))
You can also add you own equality function by using the variant subst-if with a lambda function.
NB. You need to rename last to lst in process.
I am getting ((M M M) (M M M) (M M M)) instead of ((1 2 (M M M)) (2 3 (M M M)) (4 5 (M M M))).
The code works, but not that at the depth you want:
(process '(a b c d))
=> (M M M M)
(iterate-list '(1 2 (A B C)))
=> (1 2 (M M M))
In order to process all lists in your root list, you could do this:
(mapcar #'iterate-list '((1 2 (A B C))
(2 3 (B C D))
(4 5 (C D F))))
=> ((1 2 (M M M)) (2 3 (M M M)) (4 5 (M M M)))

LISP - Write the function (REMOVE EL), that removes given atom or list from another list on all levels of the list

I have the following task:
To build the function (REMOVE EL), that removes given atom or list from another list, and this should apply on each level of the list
Example :
L=(A B A (B A C X ) X B)
(REMOVE A L ) -> (B (B C X) X B)
I wrote the following code :
(defun removeel(el tree)
(mapcan (lambda(subtree)
(cond ((null subtree) (list nil))
((consp subtree) (list (removeel el subtree)))
((eql subtree el) nil)
(t (list subtree))))
tree))
The problem is that when I remove atom, it works excellent
(removeel 'B' (A B A (B A C X ) X B))
(A A (A C X) X)
But it doesn't work If I want to remove a list
(removeel '(B A C X) ' (A B A (B A C X ) X B))
(A B A (B A C X) X B)
What should be done to make it to remove lists too ?
the simplest way would be to introduce optional equality test function, as in remove standard procedure.
it could look this way:
(defun rem-rec (item data &key (test #'eql))
(mapcar (lambda (x) (if (listp x)
(rem-rec item x :test test)
x))
(remove item data :test test)))
CL-USER> (rem-rec 1 `(1 2 (3 4 (1 2 3)) (1 (1 2 3) 3 4)))
;;=> (2 (3 4 (2 3)) ((2 3) 3 4))
for lists equality you can use equal (or equalp or anything more specific)
CL-USER> (rem-rec '(1 2 3) '(1 2 (3 4 (1 2 3)) (1 (1 2 3) 3 4)) :test #'equal)
;;=> (1 2 (3 4) (1 3 4))

Exercise 1.3 SICP Error: Cannot evaluate expression in Racket

I am doing Exercise 1.3 from SICP.
My code is the following:
#lang racket
(require sicp)
(define (square a)
(* a a)
)
(define (sum-of-squares a b)
(+ (square a) (square b) )
)
(define (max a b)
(cond ((>= a b) a)
(else b)
)
)
(define (sum-of-biggest-squares a b c )
(cond ((>= a b)
(sum-of-squares a (max b c) )
(sum-of-squares b (max a c) )
)
)
)
(sum-of-biggest-squares 5 7 10)
Surprisingly, the Racket interpreter does
not print any result for the above. The interpreter
works fine for other values. But for
this set of three values its not
working.
When I try to add an else statement
like the following:
(else (sum-of-squares b (max a c) ) )
The interpreter says:
exercise_1-3.rkt:23:10: else: not allowed as an expression
in: (else (sum-of-squares b (max a c)))
You have a couple of syntax errors in function sum-of-biggest-squares: a parenthesis should be added to close the first cond clause, and else should be added to the second one:
(define (sum-of-biggest-squares a b c)
(cond ((>= a b) (sum-of-squares a (max b c)))
(else (sum-of-squares b (max a c)))))
Note that the way in which you format the code, so different from the current common conventions, makes very difficult to read it and easy to introduce syntax errors.

Remove from list from other list

I have list witch contain other lists (2 levels only)
((S U S U R) (S U S R) (S U R))
How to remove the lists from list which contains some pairs, the same combination of 2 element on first ans second position in list or 3th and 4th position (in my example "S U") and to return ((S U S R) (S U R))
I need to transform
((S U S U R) (S U S R) (S U R)) to => ((S U S R) (S U R))
((S U R S U) (S U S R) (S U R)) to => ((S U R S U) (S U S R) (S U R)) - do not change, because here is pairs have S U, R S, U and no S U 2 or more times
REMOVE-IF
(remove-if #'oddp '(1 2 3 4 5))
=> (2 4)
LAMBDA
(funcall (lambda (x) (string x)) :example)
=> "EXAMPLE"
EQUALP
(equalp '(S U) (list 's 'u))
=> T
SUBSEQ
(subseq '(a b c d) 0 3)
=> (A B C)
Careful:
(subseq '(a b c d) 0 10)
=> ERROR
You can also use LENGTH to get the size of a list. You could also use following functions...
NTHCDR
(nthcdr '(s u s u r u) 5)
=> (U)
LDIFF
(let ((list '(a b c d)))
(ldiff list (nthcdr 10 list)))
=> (A B C D)
(let ((list '(a b c d)))
(ldiff list (nthcdr 2 list)))
=> (A B)
What you want to do
You want to remove elements from the input list that satisfy the following predicate: given a list, a subset of this list is equal to (S U) (see comments).
Your code will looks like this:
(defun remove-s-u-at-pos-3 (list)
(remove-if (lambda (...) ...) list))
You need to extract a part of each visited list and compare it to (S U).

how to map an element in a list to a value from other list in LISP

I am new to lisp programming and i am trying to think about the below operation.
(extract '(0 1 0) '(a b c)) give us '(a b a)
(extract '(1 1 1 ) '(a b c)) gives us '(b b b)
how can i think about this and how to solve it.
As Chris Jester-Young described, it just returns elements from second list at indexes in first list. Writing such a function is very easy:
(defun extract (list-1 list-2)
(mapcar (lambda (n) (nth n list-2)) list-1))
CL-USER>(extract '(0 1 0) '(a b c))
(A B A)
CL-USER>(extract '(1 1 1 ) '(a b c))
(B B B)
If there no such index, it'll give you NIL in that place.
CL-USER> (extract '(1 100 1 ) '(a b c))
(B NIL B)
But this won't work on nested structures (trees). If you want it to return elements of list-2 shaped in the structure of list-1, you can use a simple maptree helper function, then do the same thing:
(defun maptree (fn tree)
(cond
((null tree) tree)
((atom tree) (funcall fn tree))
(t (cons
(maptree fn (first tree))
(maptree fn (rest tree))))))
(defun extract* (list-1 list-2)
(maptree (lambda (n)
(nth n list-2)) list-1))
CL-USER> (extract* '(3 (2 1 (0))) '(a b c d))
(D (C B (A)))
(extract a b) returns a copy of a where each element is replaced by the element of b in that position.