I'm trying to make a function that, given a list, will return a list of pairs of elements where the two elements are not equal. For example, given the list (1 2 3) it would return ((1 2) (1 3) (2 1) (2 3) (3 1) (3 2)). The code I have now works, but it adds nil to each spot where it would have matching numbers; (1 1) for example.
(defun make-permutations-without-identical(list)
(loop for x in list
append (loop for y in list
collect (append (if (not (equal x y)) (list x y))))))
This code, given (1 2 3) returns (NIL (1 2) (1 3) (2 1) NIL (2 3) (3 1) (3 2) NIL). How do I get rid of the NIL's?
Since the lists generated by the inner loop are fresh, you can nconc them. The loop macro has unless part so that you can conditionally collect parts. Thus you can just collect except when (equal x y):
CL-USER> (loop for x in '(1 2 3)
nconcing (loop for y in '(1 2 3)
unless (equal x y)
collect (list x y)))
((1 2) (1 3) (2 1) (2 3) (3 1) (3 2))
If you don't want to see NIL in the result list, just don't collect NILs. Collect only the items you want to be in the result list.
Related
This question already has an answer here:
Test if array is inside a list in lisp
(1 answer)
Closed 9 months ago.
I wanted to use intersection
to see the intersection of two lists.
While
(intersection (list 1 1) (list 1 1))
works perfectly fine and returns (1 1),
(intersection (list (list 1 2) (list 1 4)) (list (list 1 2) (list 1 5)))
doesnt return me (1 2) but NIL.
Where is my mistake?
intersection takes an optional :test keyword argument to specify what definition of "equality" to use. The default is eql, which compares lists for pointer equality. Since your two lists are actually distinct lists in memory, they're not eql. Use equal to compare lists element-wise.
(intersection (list (list 1 2) (list 1 4)) (list (list 1 2) (list 1 5)) :test #'equal)
I want to define a function that takes an input "n" (the number of variables) and return all possible truth values. Here, I represent the truth values for a variable i (1 <= i <= n) with +i representing true, and -i representing false.
For example:
(generate-values 2)
should return:
((2 1)(2 -1)(-2 1)(-2 -1))
(generate-values 3)
should return:
((3 2 1)(3 2 -1)(3 -2 1)(3 -2 -1)(-3 2 1)(-3 2 -1)(-3 -2 1)(-3 -2 -1))
Here is my incorrect attempt:
(defun generate-values (n)
(cond
((equal n 0) nil)
(t (list (cons n (generate-values (- n 1)))
(cons (- 0 n) (generate-values (- n 1)))))))
I know why this is incorrect, but I am not able to find a way to generate (3 2 1) and then move on to (3 2 -1). My program outputs:
((3 (2 (1) (-1)) (-2 (1) (-1))) (-3 (2 (1) (-1)) (-2 (1) (-1))))
Any help with this question qould be thoroughly appreciated! Thanks!
It might be easiest to approach this in the easiest way possible, and then to figure out how to make it a bit simpler or more efficient afterward.
If you're doing this recursively, it's important to consider what the bases cases are. A reasonable base case here is probably when n = 0. The function is always supposed to return a list of lists. In the n = 0 case, there are no "variables", so the result has to be a list of the empty list: (()).
For the case that n is anything else, consider what the function returns for n-1. It's a list of all the combinations on n-1 "variables". All you need to do is prepend n to each of those, and prepend -n to each of those, and then make sure you end up with a list of all of those.
Encoding that directly, we end up with something like this:
(defun table (n)
(if (zerop n)
'(())
(let* ((table (table (1- n)))
(plus-pos-n (mapcar (lambda (subtable)
(list* n subtable))
table))
(plus-neg-n (mapcar (lambda (subtable)
(list* (- n) subtable))
table)))
(nconc plus-pos-n plus-neg-n))))
CL-USER> (table 3)
((3 2 1) (3 2 -1) (3 -2 1) (3 -2 -1) (-3 2 1) (-3 2 -1) (-3 -2 1) (-3 -2 -1))
Now, let's look at what your current implementation is doing differently, noting that it doesn't have to be exactly the same algorithm, of course.
(defun generate-values (n)
(cond
((equal n 0)
nil)
(t
(list (cons n
(generate-values (- n 1)))
(cons (- 0 n)
(generate-values (- n 1)))))))
Stylistically, since there are only two branches, I'd prefer if to cond here, but that's not a problem. Before attacking the base case, lets look at the recursive case, when n ≠ 0. First, you're calling generate-values twice; it would be more efficient to call it once and save the result. That could end up being important later if you're calling this function with big values of n, but it doesn't make the function incorrect. But remember what generate-values returns; it returns a list of the different combinations. That means that your call to (cons n (generate-values …)) is returning a list whose first element is n, and whose remaining elements are the combinations for n-1. E.g., you're doing something like:
CL-USER> (table 1)
((1) (-1))
CL-USER> (cons 2 (table 1))
(2 (1) (-1))
But that's not what you want. You really want to add n to each of those lists:
CL-USER> (mapcar (lambda (x)
(cons 2 x))
(table 1))
((2 1) (2 -1))
That's the issue in the recursive case. There's an issue in the base case, too. In the recursive case, you want to add n and -n to each of the sublists from the n-1 case. So what happens when you have n = 1? You want to be getting (cons 1 '()) and (cons -1 '()). But since the second argument to cons is going to be each list inside of the result of (generate-values 0), you really need to have something in the list returned by (generate-values 0). What needs to be there? The empty list needs to be there. So the base case needs to return (()), not (). So, after making those changes, your code would be:
(defun generate-values (n)
(cond
((equal n 0)
'(()))
(t
(list (mapcar (lambda (x)
(cons n x))
(generate-values (- n 1)))
(mapcar (lambda (x)
(cons (- 0 n) x))
(generate-values (- n 1)))))))
CL-USER> (generate-values 3)
(((3 (2 (1)) (2 (-1))) (3 (-2 (1)) (-2 (-1))))
((-3 (2 (1)) (2 (-1))) (-3 (-2 (1)) (-2 (-1)))))
That's closer, but it's still not quite right. There's another in the recursive case. You end up generating the values that have n in the beginning (a list of them), and the values that have -n in the beginning (a list of them), but then you're using list to combine them. That returns a single list with two values. Instead, you want a single list that has the values from each of them. You want to combine them with append (or, since all the structure is newly generated, you could use nconc):
(defun generate-values (n)
(cond
((equal n 0)
'(()))
(t
(append (mapcar (lambda (x)
(cons n x))
(generate-values (- n 1)))
(mapcar (lambda (x)
(cons (- 0 n) x))
(generate-values (- n 1)))))))
CL-USER> (generate-values 3)
((3 2 1) (3 2 -1) (3 -2 1) (3 -2 -1) (-3 2 1) (-3 2 -1) (-3 -2 1) (-3 -2 -1))
This final implementation isn't exactly what I started with, but it's essentially the same in terms of the algorithm. The differences are mostly stylistic, but there are some efficiency concerns, too. Using nconc instead of append would save some memory, and it really would be good to cache the results from the recursive call, rather than recomputing it. Stylistic issues that don't affect correctness might be using if instead of cond, using list* instead of cons (to indicate that we're working with lists, not trees of cons cells), and it's nice to note that you don't have to do (- 0 n), - with a single argument returns the argument's negation. That is, (- n) = -n.
I am practicing for my programming paradigms exam and working through problem sets I come to this problem. This is the first problem after reversing and joining lists recursively, so I suppose there is an elegant recursive solution.
I am given a list of lists and a permutation. I should permute every list including a list of lists with that specified permutation.
I am given an example:
->(permute '((1 2 3) (a b c) (5 6 7)) '(1 3 2))
->((1 3 2) (5 7 6) (a c b))
I have no idea even how to start. I need to formulate the problem in recursive interpretation to be able to solve it, but I can not figure out how.
Well, let's see how we can break this problem down. We are given a list of lists, and a list of numbers, and we want to order each list according to the order specified by the list of numbers:
=>(permute '((1 2 3) (4 5 6)) '(3 2 1))
'((3 2 1) (6 5 4))
We can see that each list in the list of lists can be handled separately, their solutions are unrelated to each other. So we can have a helper permute1 that handles the case of one list, then use map to apply this function to each of the lists (with the same ordering each time):
(define (permute lists ordering)
(map (lambda (xs) (permute1 xs ordering))
lists))
(define (permute1 items ordering)
...)
Now, to calculate (permute1 '(4 5 6) '(3 2 1)), what we mean is:
The first item of the new list will be the 3rd item of items, because the first number in ordering is 3.
The rest of the items of the new list will be determined by using the rest of the numbers in the ordering.
If the ordering is the empty list, return the empty list.
This forms the base case (3), the recursive case (1), and the steps to recur deeper (2). So a sketch of our solution would look like:
(define (permute1 items ordering)
(if (empty? ordering)
'()
(let ([next-item ???])
(??? next-item
(permute1 items (rest ordering))))))
Where the ???s represent getting the item based on the first number in ordering and combining this item with the remainder of the calculation, respectively.
Here's another option, using higher-order functions. This is the idiomatic way to think about a solution in a functional language - we split the problem in sub-problems, solve each one using existing procedures and finally we compose the answer:
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
(define (perm lst order)
(foldr (lambda (idx acc)
(cons (list-ref lst (sub1 idx)) acc))
'()
order))
(define (permute lst order)
(if (atom? lst)
lst
(perm (map (lambda (x) (permute x order)) lst)
order)))
We start by defining atom?, a generic predicate and perm, a helper that will reorder any given list according to the ordering specified in one of its parameters. It uses foldr to build the output list and list-ref to access elements in a list, given its 0-based indexes (that's why we subtract one from each index).
The main permute function takes care of (recursively) mapping perm on each element of an arbitrarily nested input list, so we can obtain the desired result:
(permute '((1 2 3) (a b c) (5 6 7)) '(1 3 2))
=> '((1 3 2) (5 7 6) (a c b))
I am given an example:
(permute ('(1 2 3) '(a b c) '(5 6 7)) '(1 3 2))
((1 3 2) (5 7 6) (a c b))
The syntax you've given isn't correct, and will cause an error, but it's fairly clear what you mean. You want that
(permute '((1 2 3) (a b c) (5 6 7)) '(1 3 2))
;=> ((1 3 2) (5 7 6) (a c b))
Now, it's not clear how you're indicating the permutation. Is '(1 3 2) a permutation because it has some (1-based) indices, and indicates the way to rearrange elements, or is it because it is actually a permutation of the elements of the first list of the first list? E.g., would
(permute '((x y z) (a b c) (5 6 7)) '(1 3 2))
;=> ((x z y) (5 7 6) (a c b))
work too? I'm going to assume that it would, because it will make the problem much easier.
I have no idea even how to start. I need to formulate the problem in
recursive interpretation to be able to solve it, but I can not figure
out how.
You need to write a function that can take a list of indices, and that returns a function that will perform the permutation. E.g,.
(define (make-permutation indices)
…)
such that
((make-permutation '(3 1 2)) '(a b c))
;=> (c a b)
One you have that, it sounds like your permute function is pretty simple:
(define (permute lists indices)
(let ((p (make-permutation indices)))
(p (map p lists))))
That would handle the case you've given in your example, since (map p lists) will return ((1 3 2) (a b c) (5 7 6)), and then calling p with that will return ((1 3 2) (5 7 6) (a c b)). If you need to be able to handle more deeply nested lists, you'll need to implement a recursive mapping function.
Here's my take, which seems to be shorter than the previous examples:
(define (permute lst ord)
(define ord-1 (map sub1 ord)) ; change from 1-based to 0-based indexes
(define (perm elts) ; recursive sub-procedure
(if (list? elts)
(map perm (map (curry list-ref elts) ord-1)) ; list -> recurse
elts)) ; else return unchanged
(perm lst)) ; initial call
testing
> (permute '((1 2 3) (a b c) (5 6 7)) '(1 3 2))
'((1 3 2) (5 7 6) (a c b))
> (permute '((1 (i permute did) 3) (a b (scheme cool is)) (5 6 7)) '(1 3 2))
'((1 3 (i did permute)) (5 7 6) (a (scheme is cool) b))
I have a small exercise in Lisp:
Write a function test-delta with parameters delta and lst, which will
check if the difference between successive elements in lst is smaller than
delta. Write the function in two ways:
recursively
using a mapping function
I have no problem writing that function recursively, but I don't know which mapping function I should use. All the standard mapping functions work with only one element of the list at a time. reduce cannot be used either, because I do not have some operation to use between successive elements. What function could I use here?
All standard functions are working only with one element at time.
Reduce function cannot be use either
because i do not have some operation to use between to elements.
There's already an answer by uselpa showing that you can do this with reduce, but it feels a bit awkward to me to bend reduce to this case.
It's much more natural, in my opinion, to recognize that the standard mapping functions actually let you work with multiple lists. I'll show mapcar and loop first, and then every, which I think is the real winner here. Finally, just for completeness, I've also included maplist.
mapcar
The standard mapcar can take more than one list, which means that you can take elements from two different lists at once. Of particular note, it could take a list and (rest list). E.g.,
(let ((list '(1 2 3 4 5 6)))
(mapcar 'cons
list
(rest list)))
;=> ((1 . 2) (2 . 3) (3 . 4) (4 . 5) (5 . 6))
loop
You can use loop to do the same sort of thing:
(loop
with l = '(1 2 3 4 5 6)
for a in l
for b in (rest l)
collect (cons a b))
;=> ((1 . 2) (2 . 3) (3 . 4) (4 . 5) (5 . 6))
There are some other variations on loop that you can use, but some of them have less conventient results. E.g., you could loop for (a b) on list, but then you get a (perhaps) unexpected final binding of your variables:
(loop for (a b) on '(1 2 3 4 5 6)
collect (list a b))
;=> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 NIL))
This is similar to what maplist will give you.
every
I think the real winners here, though, are going to the be every, some, notevery, and notany functions. These, like mapcar can take more than one list as an argument. This means that your problem can simply be:
(let ((delta 4)
(lst '(1 2 4 7 9)))
(every (lambda (x y)
(< (abs (- x y)) delta))
lst
(rest lst)))
;=> T
(let ((delta 2)
(lst '(1 2 4 7 9)))
(every (lambda (x y)
(< (abs (- x y)) delta))
lst
(rest lst)))
;=> NIL
maplist
You could also do this with maplist, which works on successive tails of the list, which means you'd have access to each element and the one following. This has the same 6 NIL at the end that the second loop solution did, though. E.g.:
(maplist (lambda (tail)
(list (first tail)
(second tail)))
'(1 2 3 4 5 6))
;=> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 NIL))
reduce can be used:
(defun testdelta (delta lst)
(reduce
(lambda (r e)
(if (< (abs (- r e)) delta)
e
(return-from testdelta nil)))
lst)
t)
or, without return-from (but possibly slower):
(defun testdelta (delta lst)
(and
(reduce
(lambda (r e)
(and r (if (< (abs (- r e)) delta) e nil)))
lst)
t))
I need to write a recursive function that prints out the elements of a list twice. For example, rdouble '(1 2 3) would print (1 1 2 2 3 3) and rdouble'(1 (2 3) 4) would print (1 1 (2 2 3 3) 4 4).
So far I have:
(defun rdouble(struct)
(cond
((atom struct) struct)
(t (cons (rdouble (car struct)) (cons (car struct)
(rdouble (cdr struct))
)))))
This works fine for the first example but prints
(1 1 (2 2 3 3) (2 3) 4 4)
for the second example. How do I continue to print out each element twice but not reprint (2 3)? What am I doing wrong and how can I fix it?
The expression has THREE different cases:
an atom -> return it
a cons with an atom as the CAR -> double it
a cons with a cons as the CAR -> walk down
Your code handles only two cases, where your second case mixes 2 and 3.
the reason it is causing the problems you are experiencing is that given ((1 2) 3) your code recurses into (1 2), which correctly becomes (1 1 2 2) and then adds (1 2) (being the car in the first call) after the (1 1 2 2) giving ((1 1 2 2) (1 2) ...)
what would be best is to make rdouble always return a list, and append those lists together instead of consing them