I am trying to understand pair construction and representation.
Let's take a look at the following results:
(length (cons '(a b) '(d e f)))
=> 4
Now let's switch the order:
(length (cons '(d e f) '(a b)))
=> 3
but
(length (car (cons '(d e f) '(a b))))
=> 3
Could you please explain the results above?
What is the difference between car and cdr?
Remember that cons simply sticks together two things, for historical reasons the first one is referred to as car and the second one as cdr.
If the second one happens to be a proper list, then the result is also a list. Hence a list is defined as the result of consing one element with the result of consing one element ... and so on, until we reach the empty list '(). For example:
(cons 1 (cons 2 (cons 3 '())))
=> '(1 2 3)
When dealing with lists, think of car as the first element of the list and cdr as the rest of the elements, and cons adds one more element at the head of the list - that element can be anything, including another list. It just gets added at the head, the lists are not "merged" (we use append for that). Take a look:
(car '(1 2 3))
=> 1
(cdr '(1 2 3))
=> '(2 3)
Now, regarding your examples - the first one adds '(a b) as the first element of a list, where the rest is '(d e f), so we now have a 4 element list, like this:
(cons '(a b) '(d e f))
=> '((a b) d e f)
Similarly for the second example: we add the first element '(d e f) to the rest of the elements '(a b), and we get a 3 element list:
(cons '(d e f) '(a b))
=> '((d e f) a b)
Finally, if we call car on the above list, we get its first element - which happens to be '(d e f), and clearly it has 3 elements:
(car (cons '(d e f) '(a b)))
=> '(d e f)
Related
Isn't it supposed to be (a b c d) ??
When I try it on Racket it gives me () .
'((a b c d)) is a list, containing only one element, that is the four-element list (a b c d). So if you get the car of it, you obtain as result (a b c d), while the cdr produces correctly the empty list ().
How would you create such a list using cons?
(cons (cons 'a (cons 'b (cons 'c (cons 'd '()))))
'())
or
(cons '(a b c d) '())
cdr returns the second element of the given pair, so it returns '().
I'm trying to create function which checks is list proper or improper. Can't find any solution in the internet. Is this possible?
For example we have code using list?:
(define (proper-list? list)
(cond
((list? list) '(it's a proper list))
(else '(it's an improper list))))
(proper-list? '(a b c))
; -> (it's a proper list) - OK
(proper-list? '(a b . c))
; -> (it's an improper list) - OK
(proper-list? '(a . b))
; -> (it's an improper list)
; - NOT OK. it should return (it's a pair)
How to distinguish improper list from pair?
The function list? checks wether a list is proper or not:
(list? '(1 2 3)) ; ==> #t
(list? '(1 2 . 3)) ; ==> #f
Use this in your function to return either of the two lists in your specification.
EDIT
Because of the strange requirement that (a . b) would not be considered a improper list I think you should add an extra term in you cond that differentiate the two improper lists of one pair in chain and more than one pair in chain by using pair? in the cdr. (pair? (cdr '(a . b)) ; ==> #f and (pair? (cdr '(a b . c)) ; ==> #t
The split-list function takes a list and returns a list of two lists consisting of alternating elements of the input. I wrote the following:
(defun split-list (L)
(cond
((endp L) (list NIL NIL))
(t (let ((X (split-list (cdr L))))
(cond
((oddp (length L))
(list (cons (first L) (first X)) (cadr X)))
(t (list (first X) (cons (first L) (cadr X)))))))))
The output is as expected for odd numbered lists, the first list consisting of the 1st, 3rd, 5th etc elements and the second part consisting of the 2nd, 4th, 6th etc. With an even list however, the 1st, 2nd ,3rd.. are on the right of the returned lists with the rest on the left.
For Example:
(SPLIT-LIST '(a b c 1 2 3))
(SPLIT-LIST RETURNED ((b 1 3) (a c 2))
the order should be swapped. Is there a major flaw in my logic that I'm missing? Can I rectify this situation without making major alterations?
Yes, you can rectify the problem without major modifications.
Add a case for (endp (cdr L))
Do the recursive call on cddr L
After that, the else case will always have two new elements, one to cons onto each list; there is no more need for the length call
First, when you have cond with only one test and a default t clause, please use if instead.
Also, you are using first, but cadr; second is more readable in your context than cadr.
Now, the order is swapped for even lists. Try to perform a step-by-step execution. It might be a little tedious by hand but this is useful to understand what happens. I personally prefer to use the trace macro: (trace split-list). Then, running your example:
0: (split-list (a b c 1 2 3))
1: (split-list (b c 1 2 3))
2: (split-list (c 1 2 3))
3: (split-list (1 2 3))
4: (split-list (2 3))
5: (split-list (3))
6: (split-list nil)
6: split-list returned (nil nil)
5: split-list returned ((3) nil)
4: split-list returned ((3) (2))
3: split-list returned ((1 3) (2))
2: split-list returned ((1 3) (c 2))
1: split-list returned ((b 1 3) (c 2))
0: split-list returned ((b 1 3) (a c 2))
Unclear? Try with an odd-sized list:
0: (split-list (a b c 1 2))
1: (split-list (b c 1 2))
2: (split-list (c 1 2))
3: (split-list (1 2))
4: (split-list (2))
5: (split-list nil)
5: split-list returned (nil nil)
4: split-list returned ((2) nil)
3: split-list returned ((2) (1))
2: split-list returned ((c 2) (1))
1: split-list returned ((c 2) (b 1))
0: split-list returned ((a c 2) (b 1))
It seems you always store the innermost result in the left list!
A possible recursive implementation goes roughly like this:
(defun split-list (list)
(if (endp list)
'(nil nil)
(destructuring-bind (left right) (split-list (cddr list))
(list (cons (first list) left)
(if (second list)
(cons (second list) right)
right)))))
But this can blow the stack for sufficiently large inputs. For your information, here is a simple non-recursive approach with loop:
(defun split-list (list)
(loop for (a b) on list by #'cddr
collect a into left
when b
collect b into right
finally (return (list left right)))
And since you probably will have to split your list into more than 2 lists in your next assignment, a more generic version, still with loop:
(defun split-list (list &optional (n 2))
(loop with a = (make-array n :initial-element nil)
for e in list
for c = 0 then (mod (1+ c) n)
do (push e (aref a c))
finally (return (map 'list #'nreverse a))))
(split-list '(a b c d e f g) 3)
=> ((a d g) (b e) (c f))
If you want to have fun with circular lists, you can also try this, which works for any sequence, not only lists:
(defun split-n (sequence &optional (n 2))
(let* ((ring (make-list n :initial-element nil))
(head ring)
(last (last ring)))
(setf (cdr last) ring)
(map nil
(lambda (u)
(push u (first ring))
(pop ring))
sequence)
(setf (cdr last) nil)
(map-into head #'nreverse head)))
If you plan to investigate how this works, evaluate (setf *print-circle* t) first.
One of the very common idioms in recursive list processing is to build up result lists in reverse order, and then to reverse them just before returning them. That idiom can be useful here. The essence of your task is to return a list of two lists, the first of which should contain even-indexed elements, the second of which should contain odd-indexed elements. Here's how I'd approach this problem (if I were doing it recursively). The idea is to maintain a list of even elements and odd elements, and a boolean indicating whether we're at an even or odd position in the overall list. On each recursion, we add an element to the "evens" list, since the current index of the current list is always zero, which is always even. The trick is that on each recursive call, we swap the evens and the odds, and we negate the boolean. At the end, we use that boolean to decide which lists are the "real" evens ands odds list.
(defun split-list (list &optional (evens '()) (odds '()) (evenp t))
"Returns a list of two lists, the even indexed elements from LIST
and the odd indexed elements LIST."
(if (endp list)
;; If we're at the end of the list, then it's time to reverse
;; the two lists that we've been building up. Then, if we ended
;; at an even position, we can simply return (EVENS ODDS), but
;; if we ended at an odd position, we return (ODDS EVENS).
(let ((odds (nreverse odds))
(evens (nreverse evens)))
(if evenp
(list evens odds)
(list odds evens)))
;; If we're not at the end of the list, then we add the first
;; element of LIST to EVENS, but in the recursive call, we swap
;; the position of EVENS and ODDS, and we flip the EVENP bit.
(split-list (rest list)
odds
(list* (first list) evens)
(not evenp))))
CL-USER> (split-list '())
(NIL NIL)
CL-USER> (split-list '(1))
((1) NIL)
CL-USER> (split-list '(1 2))
((1) (2))
CL-USER> (split-list '(1 2 3))
((1 3) (2))
CL-USER> (split-list '(1 2 3 4))
((1 3) (2 4))
CL-USER> (split-list '(1 2 3 4 5 6 7 8 9 10))
((1 3 5 7 9) (2 4 6 8 10))
Recursion is always a good idea, as a conceptual tool aiding our thinking while developing a problem's solution. Once the correct code is formulated, iff your language is limited in its handling of recursion, re-write it to use other means.
A modern implementation of a Scheme-derived language (Scheme is a kind of a Lisp, right?), Racket has unlimited recursion, implementing call stack on the heap. As such, recursive code for a recursive algorithm is perfectly fine.
Correctness / serenity simplicity first, efficiency later!
The simple solution for your requirements is (in the executable "pseudocode" of Haskell)
foldr (\x [a, b] -> [x:b, a]) [[], []]
I first saw this neat trick in an old F# (IIRC) answer by user ed'ka (IIRC); quite a few years back. (But actually it appears to have been in haskellwiki since more or less forever).
Coded in direct recursive style in Scheme, it is
(define (split xs)
(cond
((null? xs) (list '() '()))
((split (cdr xs)) => (lambda (acc)
(list (cons (car xs) (cadr acc)) ; always in the first subgroup!
(car acc))))))
The list's head element must appear in the first subgroup. No need to exert ourselves trying hard to arrange for it to happen, just say it, and it happens just because you said so, all by itself, because of the magic that is recursion !
(split '(a b c 1 2 3))
(split '(a b c 1 2))
; '((a c 2) (b 1 3))
; '((a c 2) (b 1))
A side note: I decided to never use if again, in preference of cond, because an if's clause in itself says nothing about its activation conditions - we must count, of all things, to know which is which. With cond it's plain, and it is right there at the clause's start.
It is easy enough to amend this to produce e.g. a three-way split, with
(define (split3 xs)
(cond
((null? xs) (list '() '() '()))
(else (apply
(lambda (a b c) ; Scheme-style destructuring
(list (cons (car xs) c) ; rotate right:
a ; xs's 2nd elt to appear in the 2nd group!
b)) ; head element of (cdr xs) is in `a`
(split3 (cdr xs)))))) ; the recursive result
(split3 '(a b c 1 2 3))
(split3 '(a b c 1 2))
; '((a 1) (b 2) (c 3))
; '((a 1) (b 2) (c))
I am relatively new to LISP and am trying some new things for a Lisp program I am trying to create for a presentation.
I need to be able to print every other character in a list, for example, (A B C D E F) would return (A C E) .. but I am getting easily confused...
I am normally program Java, so this comes kind of different to me.
I am trying to program this using purely recursion.. So something along the lines of....
(defun every-other (lst)
(cond ((null lst) 0)
(( **** now this is where I get confused as to what I should do..
I've tried adding a counter to only remove even numbered elements, but I think I implemented the counter wrong, I also tried remove(cadr lst) lst, but that would only return zeros...
any help would be greatly appreciated..
Thanks!
Since you say you want it to be done recursively, just think it through case by case.
The list is null -> return the empty list [the empty list is '()].
Otherwise the list is not null -> In this case you want to build a new list containing
the first element, skip the second element, then grab
every-other element of the remaining list.
Turning this case analysis into code looks something like this:
(defun every-other (lst)
(cond
;; If the list is null return the empty list.
((null lst) '())
;; If the list is not null, construct [cons] a new list with the first element of lst
;; and every-other element of the list after the first two elements [rest returns the
;; list without the first element, so we can just use it twice].
(t (cons (first lst) (every-other (rest (rest lst)))))))
Now going through the evaluation of this code should look something like this:
(every-other '(a b c d e f))
=> (cons 'a (every-other '(c d e f)))
=> (cons 'a (cons 'c (every-other '(e f))))
=> (cons 'a (cons 'c (cons 'e (every-other '())))
=> (cons 'a (cons 'c (cons 'e '())))
=> (cons 'a (cons 'c '(e)))
=> (cons 'a '(c e))
=> '(a c e)
For fun, a loop-based solution:
(defun every-other (lst)
(loop
for i in lst
for keep = t then (not keep)
if keep collect i))
Just use a loop.
(loop :for c :in '(a b c d e f) :by #'cddr
:collect c)
:By in a for-in clause sets the stepping function (default is #'cdr). In order to get every other element, step two steps each time. Cddr is a shortcut for applying cdr two times.
(defun aaa (x)
(aa (length x) x))
(defun aa (n x)
(cond ((null x) nil)
((evenp (- n (length x))) (cons (car x) (aa n (cdr x))))
(t (aa n (cdr x)))))
This is a stupid case lol~
shorter recursive solution:
(defun every-other (l)
(unless (null l)
(cons (first l) (every-other (cddr l)))))
If I have a list and I map a lambda function over it how can I get a reference to the next or previous item while processing the current one?
(map (lambda (x) x) '(1 2 3))
How would I reference the previous or next element while processing x?
John McCarthy originally made maplist and it's defined in CL still and predates map(car). It's definition in Scheme would be something like:
(define (maplist fun lst)
(if (null? lst)
'()
(cons (fun lst) (maplist fun (cdr lst)))))
(maplist values '(1 2 3 4)) ; ==> ((1 2 3 4) (2 3 4) (3 4) (4))
It's slightly more difficult to get each element like map but if you need more than the first then it's perfect.
Start with your one list, construct two other lists, one 'shifted' right, and the other 'shifted' left. Like this:
(define (process func x)
(let ((to-front (cons 'front (reverse (cdr (reverse x)))))
(to-rear (append (cdr x) (list 'rear))))
(map func to-front x to-rear)))
Note that the stuff above with reverse is because map expects all lists to have the same length. So when adding to the front, you need to remove one from the tail.
Also, the provided func needs to accept three arguments.
> (process list '(a b c))
((front a b) (a b c) (b c rear))
You can always use map on two zipped lists, i.e.
(import (srfi srfi-1)) ; or use some zip implementation
(define a '(1 2 3 4 5))
(map (lambda (x) x)
(zip a
(append (cdr a) (list (car a)))))
which results in ((1 2) (2 3) (3 4) (4 5) (5 1)).
Of course, the above assumes "periodic" boundary conditions for the lists (you should modify the boundary conditions for your case).
And also you would need to modify the lambda to handle pairs of elements.
For simplicity let's take the case of two elements at a time -- the current and next one. So if you have (list 1 2 3), and a function that takes this and next args, you want it to be called with:
1 2
2 3
3 <some value, let's say 3>
You could write that concisely as:
(map f xs (append (drop xs 1) (list (last xs))))
However the drop and append-ing means that's not the fastest way to do it. Instead you could write a map-slide-pairs function to do it more directly:
#lang racket/base
(require racket/match)
;; map a list as "sliding pairs". For example:
;; (map-slide-pairs cons '(1 2 3)) ==> '((1 . 2)
;; (2 . 3)
;; (3 . 3))
(define (map-slide-pairs f xs #:last-val [last-val #f])
;; Concise implementation:
;; (map f xs (append (drop xs 1) (list (last xs)))))
;; Faster implementation:
(let loop ([xs xs])
(match xs
[(list) (list)]
[(list this) (list (f this (or last-val this)))]
[(list this next more ...) (cons (f this next)
(loop (cons next more)))])))
(module+ test
(require rackunit)
(check-equal? (map-slide-pairs cons '(1 2 3))
'([1 . 2][2 . 3][3 . 3]))
(check-equal? (map-slide-pairs cons '(1 2 3) #:last-val 100)
'([1 . 2][2 . 3][3 . 100])))
Hopefully you can see how to extend this and make a "map-slide-triples" function that would be called with the previous, current, and next elements of the list.