From: Klaus Ebbe Grue <grue@di...>  20070122 09:13:21

;; Hi, ;; Im a LISP beginner and I would like some help. ;; I have 2 problems that might be easy for an advanced programmer: ; I wonder whether or not clisplist@... is the right ; place to ask such questions. But I had a little spare time this morning, ; so here is a partial answer to question 2 and 3 in case you want to ; write your program in a doityourselfstyle (which I think is a good ; idea until you are no longer a LISP beginner). (inpackage "COMMONLISPUSER") ;; 2. A function that returns a list containing integers between sets of ;; lower and upper boundaries. For example: function 20 26 23 28 would ;; return: (20 21 22 23 24 25 26 27 28) ; (integerinterval m n) returns the list (m m+1 m+2 ... n) provided ; that m and n are integers and m <= n. (defun integerinterval (m n) (if (< n m) nil (cons m (integerinterval (+ m 1) n)))) ; (integerinterval1 m n) also returns the list (m m+1 m+2 ... n) ; provided that m and n are integers and m <= n. But it runs faster. (defun integerinterval1 (m n) (integerinterval2 m n nil)) ; (integerinterval2 m n result) returns the list (m m+1 m+2 ... n) ; prepended to the list 'result'. (defun integerinterval2 (m n result) (if (< n m) result (integerinterval2 m ( n 1) (cons n result)))) ; The function above is 'tail recursive' in the sense that the very ; last thing it does when (< n m) is false is that it calls *itself*. ; The integerinterval function is not tail recursive: the last thing ; it does when (< n m) is false is that it calls 'cons'. Tail recursive ; functions happen to be faster than other functions on most systems. ; (question2 s) returns a list with all integers between the smallest and ; largest element of the nonempty list s of integers. As an example, ; (question2 '(20 26 23 28)) returns (20 21 22 23 24 25 26 27 28) (defun question2 (s) (integerinterval1 (apply 'min s) (apply 'max s))) ; The function above uses (apply 'min s) to apply the minimum function to ; the list s to get the smallest element of the list. If you want to do ; that 'yourself' you can use (smallestelement s) instead: (defun smallestelement (s) (if (atom (cdr s)) (car s) (min (car s) (smallestelement (cdr s))))) ; The smallestelement function above is *not* tail recursive. One can make ; it tail recursive and thereby faster using the same trick as the one I ; used for integerinterval above. ;; 3. A random generator that chooses values form a list or a stackpile ;; without repeating any values until all have been used once. ; The following is *not* a solution to your problem. Rather, I solve ; the related problem of constructing a random permutation of the ; integers from m inclusive to n exclusive. Hopefully, you can adapt ; the code to suit your needs ; (randompermutation m n) returns a random permutation of the numbers ; m,m+1,m+2,...,n1 provided that m and n are integers and m < n. (defun randompermutation (m n) (format t "randompermutation ~s ~s~%" m n) (if (= m ( n 1)) (list m) (randompermutation1 m (floor (+ m n) 2) n))) ; (randompermutation1 m d n) returns a random permutation of the numbers ; m,m+1,m+2,...,n1 provided that m, n, and d are integers and m < d < n. (defun randompermutation1 (m d n) (format t "randompermutation ~s ~s ~s~%" m d n) (randommerge ( d m) (randompermutation m d) ( n d) (randompermutation d n))) ; (randommerge l1 s1 l2 s2) returns a random merge of the lists s1 and s2 ; provided that l1 is the length of s1 and l2 is the length of s2. When ; merging a short and a long list it picks with largest probability from ; the long list. To get all permutations with even probability it is ; important to pick with probability l1/(l1+l2) from the list of length l1. (defun randommerge (l1 s1 l2 s2) (format t "randommerge ~s ~s~%" l1 l2) (if (= l1 0) s2 (if (= l2 0) s1 (if (< (random (+ l1 l2)) l1) (cons (car s1) (randommerge ( l1 1) (cdr s1) l2 s2)) (cons (car s2) (randommerge ( l2 1) (cdr s2) l1 s1)))))) ; Cheers, ; Klaus 