So for example I have this List : L
((a 1) (b 2) (c 3)) ((d 4) (e 5) (f 6))
how can I turn that into
((a 1) (b 2) (c 3) (d 4) (e 5) (f 6))
A list containing two lists that I need to make one list containing lists.
I know if I car L I get the front half ((a 1) (b 2) (c 3)) and if I cdr L I get the back half
(((d 4) (e 5) (f 6))) but I cant figure out how to turn it into the form
((a 1) (b 2) (c 3) (d 4) (e 5) (f 6))
For "combining" two lists (no matter their contents), use append. And for accessing the first and second elements of a list use (car x) and (cadr x) - which is shorthand for (car (cdr x)). For example:
(define lst '(((a 1) (b 2) (c 3)) ((d 4) (e 5) (f 6))))
(append (car lst) (cadr lst))
=> '((a 1) (b 2) (c 3) (d 4) (e 5) (f 6))
For a more general solution that works with an arbitrary number of sublists, refer to #uselpa's fine answer using apply. Or if you're using Racket, append* will also work for multiple sublists:
(define lst '(((a 1) (b 2) (c 3)) ((d 4) (e 5) (f 6)) ((g 7) (h 8) (i 9))))
(append* lst)
=> '((a 1) (b 2) (c 3) (d 4) (e 5) (f 6) (g 7) (h 8) (i 9))
To complement Oscar's answer, (apply append ...) works for any number of sublists:
(define L '(((a 1) (b 2) (c 3))
((d 4) (e 5) (f 6))))
(apply append L)
=> '((a 1) (b 2) (c 3) (d 4) (e 5) (f 6))
and
(define G '(((a 1) (b 2) (c 3))
((d 4) (e 5) (f 6))
((g 7) (h 8) (i 9))))
(apply append G)
=> '((a 1) (b 2) (c 3) (d 4) (e 5) (f 6) (g 7) (h 8) (i 9))
Related
I'm trying to understand how it works member function with list and list of lists.
Here an example.
(member '(A 6) '((A 7) (B 6) (E 6) (D 5)) :test #'string-equal :key #'second)
I want to check with the member function if the second argument of the list '(A 6) is member of the second list in input.
The answer should be
true
but I'm doing something wrong, because Common Lisp reply:
Error: Cannot coerce (A 6) to type STRING.
So how can I take the second argument from the first list?
Thank you for the help.
What you are missing is that the :key argument is not applied to the first argument of member.
Another thing is that second will return the number, not the symbol.
Thus:
(member 'A '((A 7) (B 6) (E 6) (D 5)) :test #'string-equal :key #'first)
==> ((A 7) (B 6) (E 6) (D 5))
(member 'C '((A 7) (B 6) (E 6) (D 5)) :test #'string-equal :key #'first)
==> NIL
(member 'E '((A 7) (B 6) (E 6) (D 5)) :test #'string-equal :key #'first)
==> ((E 6) (D 5))
Note that the return value is the tail, not the matched list element.
This is to allow the use of member as a predicate, i.e., to distinguish between finding nil and finding nothing:
(member nil '(1 2 nil 3))
==> (NIL 3)
(find nil '(1 2 nil 3))
==> NIL
(find t '(1 2 nil 3))
==> NIL
I'm trying to sort the elements of the following list by using the third element of each sublist:
((v 1 a) (v 3 d) (v 6 b) (v 2 c))
So the result should be:
((v 1 a) (v 6 b) (v 2 c) (v 3 d))
I've tried something like this:
(sort (copy-seq my-list) #'> :key (lambda (x) (third (car x))) )
but it doesn't really work and I'm not sure how should I do this.
CL-USER 15 > (sort (copy-seq '((v 1 a) (v 3 d) (v 6 b) (v 2 c)))
#'string<
:key #'third)
((V 1 A) (V 6 B) (V 2 C) (V 3 D))
I'm trying to sort a list of polynomials written in this format:
(M [coefficient] [total degree] [Variable List]).
example:
((M 1 1 ((V 1 A))) (M 1 2 ((V 1 A) (V 1 C))) (M 1 2 ((V 2 A))) (M 1 2 ((V 1 A) (V 1 B))))
This is: a + a * c + a ^ 2 + a * b, I need to get a + a * b + c + a * a ^ 2, because a * b < a ^ 2 and a < a ^ 2.
I tried to use the function sort, but my output is:
((M 1 1 ((V 1 A))) (M 1 2 ((V 2 A))) (M 1 2 ((V 1 A) (V 1 B))) (M 1 2 ((V 1 A) (V 1 C))))
that is a + a ^ 2 + a * b + a * c.
I use:
(defun sort-poly (a b)
(cond
(t (sort-poly-helper (varpowers a) (varpowers b)))))
(defun sort-poly-helper (a b)
(cond
((null a) (not (null b)))
((null b) nil)
((equal (third(first a)) (third(first b))) (sort-poly-helper (rest a) (rest b)))
(t (sort (list (third(first a)) (third(first b))) #'string-lessp))))
with:
(sort '((M 1 1 ((V 1 A))) (M 1 2 ((V 1 A) (V 1 C))) (M 1 2 ((V 2 A))) (M 1 2 ((V 1 A) (V 1 B)))) #'sort-poly)
Some help?
Thanks
Your definition of what you want to do is sufficiently opaque that an answer is hard to provide. But the way to start is to stop programming like it is 1956 and use some abstraction.
First of all, let's define how to make a variable and get at its bits:
(defun make-variable (name &optional (degree 1))
`(v ,name ,degree))
(defun variable-name (v)
(second v))
(defun variable-degree (v)
(third v))
Now let's define how to make polynomials from lists of variables. Note that the total degree of the polynomial is computable from the degrees of all the variables, so we do that.
(defun make-polynomial (variables &optional (coefficient 1))
;; The total degree of the polynomial can just be computed from the
;; degrees of its variables
`(m ,coefficient ,(reduce #'* variables :key #'variable-degree)
,variables))
(defun polynomial-coefficient (p)
(second p))
(defun polynomical-total-degree (p)
(third p))
(defun polynomial-variables (p)
(fourth p))
Now, given lists of polynomials, we can sort them using the abstractions we've built: we don't need to grovel around with list accessors (and indeed we could change the representation of polynomials or variables and nothing would ever know).
I am guessing that what you want to sort on is the highest degree of a variable in a polynomial although it is not really clear, and not the total degree of the polynomial (which would be easier). So let's write a function to pull out the highest variable degree:
(defun highest-variable-degree (p)
(reduce #'max (mapcar #'variable-degree (polynomial-variables p))))
And now we can sort lists of polynomials.
CL-USER 23 > (sort (list (make-polynomial (list (make-variable 'a)
(make-variable 'b 2)))
(make-polynomial (list (make-variable 'c)
(make-variable 'd))))
#'<
:key #'highest-variable-degree)
((m 1 1 ((v c 1) (v d 1))) (m 1 2 ((v a 1) (v b 2))))
Remember: it is not 1956 any more.
How can I transform this list:
'((A B) (A C) (C D) (B D) (D E) (D F))
Into something like
'(A (B (nil)) (C (D ((F (nil)) (E (nil))))))
Or whatever list best represent the tree:
A
/ \
B C
|
D
/ \
E F
Note that as C was the first to claim D as its child, the (B D) didn't add the D as the child of B.
first of all i would clean up the data, removing all the unnecessary pairs (in your case '(B D)), and build the adjacency map:
user> (def data '((A B) (A C) (C D) (B D) (D E) (D F)))
#'user/data
user> (def nodes-map (group-by first
(apply sorted-set-by
#(compare (second %1) (second %2))
data)))
#'user/nodes-map
user> nodes-map
{A [(A B) (A C)], C [(C D)], D [(D E) (D F)]}
i removed the garbage using sorted-set, using the fact that it treats items to be equal using comparator, and keep only the first of them (in this case it considers (C D) and(B D) to be equal)
then i would construct the tree, using recursive function:
user> (defn to-tree [start nodes]
(list start
(if-let [connections (seq (nodes start))]
(map #(to-tree (second %) nodes) connections)
'(nil))))
#'user/to-tree
user> (to-tree 'A nodes-map)
(A ((B (nil)) (C ((D ((E (nil)) (F (nil))))))))
Hello i have to programm this fucntion in lisp:
(defun combine-list-of-lsts (lst)...)
So when executing the function i should get
(combine-list-of-lsts '((a b c) (+-) (1 2 3 4)))
((A + 1) (A + 2) (A + 3) (A + 4) (A-1) (A-2) (A-3) (A-4) (B + 1) (B + 2) (B + 3) (B + 4) (B-1) (B-2) (B-3) (B-4)(C + 1) (C + 2) (C + 3) (C + 4) (C-1) (C-2) (C-3) (C-4))
What i have now is:
(defun combine-list-of-lsts (lst)
(if (null (cdr lst))
(car lst)
(if (null (cddr lst))
(combine-lst-lst (car lst) (cadr lst))
(combine-lst-lst (car lst) (combine-list-of-lsts (cdr lst))))))
Using this auxiliar functions:
(defun combine-lst-lst (lst1 lst2)
(mapcan #'(lambda (x) (combine-elt-lst x lst2)) lst1))
(defun combine-elt-lst (elt lst)
(mapcar #'(lambda (x) (list elt x)) lst))
But what i get with this:
((A (+ 1)) (A (+ 2)) (A (+ 3)) (A (+ 4)) (A(-1)) (A(-2)) (A(-3)) (A(-4))...)
I dont know how to make this but without the parenthesis
The first thing is to look at this case:
(combine-list-of-lsts '((a b c)))
What should that be? Maybe not what your function returns...
Then I would look at the function combine-list-of-lsts. Do you need two IF statements?
Then look at combine-elt-lst. Do you really want to use LIST? It creates a new list. Wouldn't it make more sense to just add the element to the front?
Usually, when you want to reduce mutliple arguments into single result, you need function #'reduce. Your combination of lists has name cartesian n-ary product.
Following function:
(defun cartesian (lst1 lst2)
(let (acc)
(dolist (v1 lst1 acc)
(dolist (v2 lst2)
(push (cons v1 v2) acc)))))
creates cartesian product of two supplied lists as list of conses, where #'car is an element of lst1, and #'cdr is an element of lst2.
(cartesian '(1 2 3) '(- +))
==> ((3 . -) (3 . +) (2 . -) (2 . +) (1 . -) (1 . +))
Note, however, that calling #'cartesian on such product will return malformed result - cons of cons and element:
(cartesian (cartesian '(1 2) '(+ -)) '(a))
==> (((1 . +) . A) ((1 . -) . A) ((2 . +) . A) ((2 . -) . A))
This happens, because members of the first set are conses, not atoms. On the other hand, lists are composed of conses, and if we reverse order of creating products, we could get closer to flat list, what is our goal:
(cartesian '(1 2)
(cartesian '(+ -) '(a)))
==> ((2 + . A) (2 - . A) (1 + . A) (1 - . A))
To create proper list, we only need to cons each product with nil - in other words to create another product.
(cartesian '(1 2)
(cartesian '(+ -)
(cartesian '(a) '(nil))))
==> ((2 + A) (2 - A) (1 + A) (1 - A))
Wrapping everything up: you need to create cartesian product of successive lists in reversed order, having last being '(nil), what can be achieved with reduce expression. Final code will look something like this:
(defun cartesian (lst1 lst2)
(let (acc)
(dolist (v1 lst1 acc)
(dolist (v2 lst2)
(push (cons v1 v2) acc)))))
(defun combine-lsts (lsts)
(reduce
#'cartesian
lsts
:from-end t
:initial-value '(nil)))
There is one more way you can try,
(defun mingle (x y)
(let ((temp nil))
(loop for item in x do
(loop for it in y do
(cond ((listp it) (setf temp (cons (append (cons item 'nil) it) temp)))
(t (setf temp (cons (append (cons item 'nil) (cons it 'nil)) temp))))))
temp))
Usage:(mingle '(c d f) (mingle '(1 2 3) '(+ -))) =>
((F 1 +) (F 1 -) (F 2 +) (F 2 -) (F 3 +) (F 3 -) (D 1 +) (D 1 -) (D 2 +)
(D 2 -) (D 3 +) (D 3 -) (C 1 +) (C 1 -) (C 2 +) (C 2 -) (C 3 +) (C 3 -))