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
I have a list defined as follows:
(defparameter testlist '(((a b) (c d)) ((e f) (g h ))) )
I also have a variable defined as :
(defparameter feature 'u)
I want to append a feature to (c d).
When I try:
(setf (nth 1 (nth 0 testlist)) (append (nth 1 (nth 0 testlist)) feature))
testlist becomes:
(((A B) (C D . U)) ((E F) (G H)))
However, I want a non dotted list.
I can't figure out why I have this result. Can you explain why or suggest a better method to append, that is comprehensible for a beginner level?
First off your feature is not a list. append allows the last argument to be anything but then the result would not be a proper list if the last element is itself not a proper list. Thus:
(append '(1 2) 3) ; ==> (1 2 . 3)
(append '(1 2) '(3 . 4)) ; ==> (1 2 3 . 4)
(append '(1 2) '(3 4)) ; ==> (1 2 3 4)
Thus you need to append (list feature) if you want feature to be one element in the list you are replacing and not the new dotted value.
You need to locate the list you are changing and everything before you need to recreate but everything after you can just share with the original source:
Looking at your structure you want to change the cadar while you need to recreate the caar while the result can share the cdr:
(let ((lst '(((a b) (c d)) ((e f) (g h )))) (feature 'x))
(list* (list (caar lst) (append (cadar lst) (list feature))) (cdr lst)))
; ==> (((a b) (c d x)) ((e f) (g h)))
Now how you choose to use that result is up to you. You can setf the binding and you will have the same behaviour as if you mutated except for the unwanted consequences.
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 trying to make a function in Scheme which returns how many times a character repeats in a list.
For example if i have (list 2 6 'a 'b 'a 'a 2)
the result must be ((2 . 2) (6 . 1) (a . 3) (b . 1))
it didnt need to be written in the most efficient way,just want to be easy and simple for understanding.
Thanks in advance for helping me :)
Since this appears to be homework, you posted no code whatsoever, and we know nothing about your constraints and your current knowledge of Scheme, it's hard to answer.
Basically, you can do this efficiently with a hash map, or less efficiently with 2 nested loops. I'll explain the latter for you to get started.
I'll assume you know how to loop through the list.
So basically you need to
1) loop over your list
2) for each element of the list (let's call it e)
3) loop over the list once more, counting how many of (e) you find
4) assemble (e) and the result of your counting loop
The results of step 4) need to be assembled in a result list.
If you do this, the result will be something like
'((2 . 2) (6 . 1) (a . 3) (b . 1) (a . 3) (a . 3) (2 . 2))
which is close... but not correct because you counted some elements a few times.
So in addition to the above you need a way of keeping track of every element you already encountered, and steps 3) and 4) need to be done only if you encounter a new element. Keeping track could be through another list, or simply by checking your current result list, depending on your code.
If you have any code to show, please update your question and we can help more.
EDIT
OK, since GoZoner has posted code, I have 2 alternative versions for you. I hope you study all of these and make up your own mind, instead of simply copying one.
First, the version I described; as opposed to GoZoner's version, it does not use mutable lists but is slower than the mutable version:
(define (how-many lst)
(let loop ((lst2 lst) (res '()))
(if (empty? lst2)
(reverse res)
(let ((c (car lst2)))
(loop (cdr lst2)
(if (assoc c res)
res
(cons (cons c (count (lambda (e) (eq? e c)) lst)) res)))))))
=> '((2 . 2) (6 . 1) (a . 3) (b . 1))
If you want to use a mutable structure (and I would, too), I recommend mutable hash tables. The following example is in Racket but is trivial to adapt to R6RS Scheme hash tables if required:
(define (how-many lst)
(let ((res (make-hash)))
(for-each (lambda (e) (hash-update! res e add1 0)) lst)
(hash->list res)))
=> '((6 . 1) (a . 3) (b . 1) (2 . 2))
Just note that hash tables do not respect order, so you'll get the same result but the pairs will probably in a different order (and even vary from one call to the next).
Something like this:
(define (character-count list)
(assert (list? list))
(let looking ((list list) (rslt '()))
(cond ((null? list) rslt)
((assoc (car list) rslt) =>
(lambda (pair)
(set-cdr! pair (+ 1 (cdr pair)))
(looking (cdr list) rslt)))
(else (looking (cdr list)
(cons (cons (car list) 1) rslt))))))
> (character-count '(2 a 2 a b c 2))
((c . 1) (b . 1) (a . 2) (2 . 3))
I get an 'A'?!
I'm looking for a function in Scheme to replace a element in an equation by a value.
Exemple : '(+ a b c a) with (1 2 3) should give me '(+ 1 2 3 1). (I don't want to resolve the equation, it was just an exemple)
Basically, I want to say that a=1, b=2, c=3
To proceed, I extract the variables of my first list in another list.
Then, I received the expected values in another list.
Now, I want to assign values to variables.
Any hints on how I proceed?
Thanks a lot.
You can use an "association list" of mappings that looks like ((a 1) (b 2) (c 3)).
assq can retrieve the matching pair. So, for everything in your original list, you can look it up using assq and then replace it.
So:
(lambda (ls a-list)
(map (lambda (x)
(let ((lookup (assq x a-list)))
(if lookup
(cadr lookup)
x)))
ls)))
Would take a list and an association list and replace everything in the original list with its replacement (if there is one).
Ain't this what let do?
> (let ((a 1) (b 2) (c 3))
(+ a b c b))
=> 8
If you don't want to evaluate the expression:
> (let ((a 1) (b 2) (c 3))
`(+ ,a ,b ,c ,a))
=> (+ 1 2 3 1)