So im extremely new to Scheme, and i've been trying to do a multiplying table, if you put
(multiplying-table 10 3) should give a list (3 6 9 12 15 18 21 24 27 30)
Here is my code
(define (multiplying-table n value)
(cond ((= n 0) '())
(else (* n value)(Multiplying-table(- n 1)))))
You need to use cons to combine the first number 3 with the list of the rest.
Eg. (3 6 ...) is (cons 3 (cons 6 ...)). You are instead having two expressions where the (* n value) is only for effect since the result is never used. Because of that every call should return the empty list.
Usually there are 2 ways to do it. With recursion inside cons or with an accumulator. Since lists are created from end to beginning you could count n downwards and build the list from end to beginning. The base case would just return the accumulator which by default is the empty list. Here is an example:
(define (sequence from to)
(let loop ((n to) (acc '()))
(if (< n from)
acc
(loop (- n 1) (cons n acc)))))
(sequence 5 10) ; ==> (5 6 7 8 9 10)
Related
I am trying to create a list of n elements. It must produce this output:
(my-list 5)
>> 0 1 2 3 4
I have the function below:
(define (my-list n)
(cond
((<= n 0) '())
(else (reverse-list (cons (- n 1)
(my-list(- n 1)))))
)
)
and this is producing
(my-list 10)
>>(8 6 4 2 0 1 3 5 7 9)
I understand this is due to reversing the list at every recursive call, but I am not sure what is the correct way. Also my reverse-list is working fine.
Thanks in advance!
A standard idiom in Scheme 'build-and-reverse' suggests you only reverse the list once, at the very end, when its reverse has been completely built (thus reducing the complexity down to O(N) from quadratic.)
So yes, you end up in a tail call to reverse but the list should be built without doing it. Scheme has plenty of local recursive binding constructs.
But.
If you build a range starting with the largest value (that should be one greater than the last element to the list) you don't need to reverse it in the end, at each iteration step you decrease a counter and prepend its new value to those already accumulated:
(define (range n)
(let rng ((m (- n 1)) (ret-val '())) ; named-let is very useful for small local recursive closures
(if (< m 0) ; that original (<= n 0) check is also handled here
ret-val ; here, the result is returned; note we don't need to reverse it
(rng (- m 1) (cons m ret-val))))))
(display (range 10))
(newline)
prints
(0 1 2 3 4 5 6 7 8 9)
Or, to demonstrate the build-and-reverse, we can start with the lowest value:
(define (range-asc n)
(let rng ((m 0) (ret-val '()))
(if (= m n)
(reverse ret-val) ; since we started from zero, we need to reverse it
(rng (+ m 1) (cons m ret-val)))))
(Looks like I still remember/can recover some Scheme. :-O)
First of all, your code. Properly formatted it should look something like:
(define (my-list n)
(cond ((<= n 0) '())
(else (reverse-list (cons (- n 1)
(my-list (- n 1)))))))
Problem you have, is reverse-list call. It happens every time you add new element to the list. You can fix it in many ways, but simple solution is to wrap your recursive code into local function, and do some additional operations (reverse in your case) when it returns.
(define (my-list n)
(define (build-list m)
(cond ((<= m 0) '())
(else (cons (- m 1)
(build-list (- m 1))))))
(reverse-list (build-list n)))
So, inside my-list function, first we define recursive part as a local function build-list. This is exactly your code, but with call to reverse-list removed. This part will build your list, but as you know, in reverse order. But that is no longer a problem, since we can reverse it when local function returns.
I have written a function called my_rotate that takes a number from a user and creates a list up to five numbers. my_rotate then, pops off the first element of the list and adds it to the end of the list. Any advice on how I could write my_rotate to take in another number n and rotate the list based on the number n, in which the user entered.
Example:
> (my_rotate 1 2)
Outputs:
(3 4 5 1 2)
This is what I have so far:
(defun my_rotate (y)
(append (loop for i from (+ 1 y) to (+ 4 y) collect i)
(list y)))
Here the function.
I create two lists and then concatenate them.
(defun my-rotate (length shift)
"Return a list of given LENGTH, rotated by SHIFT."
(nconc
(loop for i from (1+ shift) to (- length shift -2) collect i)
(loop for i from 1 to shift collect i)))
(my-rotate 7 2)
==> (3 4 5 6 7 1 2)
Note that since both loops produce fresh lists, I use nconc instead of append.
If, however, you want to rotate an existing list, you will need to do something else:
(defun rotate-list (list shift)
"Rotate the given LIST by the specified SHIFT."
(let ((len (length list)))
(setq shift (mod shift len)) ; handle circular shifts
(append (nthcdr (- len shift) list)
(butlast list shift))))
(rotate-list '(1 2 3 4 5 6) 2)
==> (5 6 1 2 3 4)
(rotate-list '(1 2 3 4 5 6) 20)
==> (5 6 1 2 3 4) ; same because 20 = 2 mod 6
(rotate-list '(1 2 3 4 5 6) 0)
==> (1 2 3 4 5 6) ; unchanged
Note that nthcdr points inside the original list, so we have to use append to avoid modifying the argument.
Note also that we scan the list argument twice (once in nthcdr and once in butlast).
If your lists are huge, and profiling shows that this function is the bottleneck, you might want to re-write this using a loop (this is scenario is so unlikely, that I already regret having wasted my time writing this note).
I am trying to take a list of 16 numbers I have and make it into a list of 4, 4 element sublists to represent the game board of a magic square. I made a method that can take a list and return a single sublist, and now I am trying to recursively use this method to build the full board.
My problem however, is my initBoard returns nil no matter what and I know every other method is working as desired. Any clarification of my error would be greatly appreciated!
Also here is an example input list:
(4 5 15 10 14 11 1 8 9 16 6 3 7 2 12 13)
And what I want as the output would be:
((4 5 15 10) (14 11 1 8) (9 16 6 3) (7 2 12 13))
(defun smallList (lst cnt)
(cond ((>= cnt 4) nil)
(t (cons (car lst) (smallList (cdr lst) (+ 1 cnt))))))
(defun isEmpty (lst)
(if lst 1 -1))
(defun initBoard (lst)
(cond ((= (isEmpty lst) -1) nil)
(t (cons (smallList lst 0) (initBoard (cddddr lst))))))
Some remarks:
someList, lst, cnt is not idiomatic, use some-list, list, count
You don't need is-empty, just use endp or null, which returns a boolean (not -1 or 1). You could make an alias if you want (but why?):
(setf (symbol-function 'is-empty) #'endp)
You could use a loop for small-list:
(defun small-list (list)
(values (loop repeat 4 collect (pop list)) list))
The secondary value is the rest of the list, so that you don't need to cddddr.
But in fact, it might be better to initialize the whole board inside a single function:
(defun init-board (list)
(loop repeat 4 collect
(loop repeat 4 collect (pop list))))
The first LOOP collect lists of 4 elements, which are collected by the inner LOOP. The collected elements are popped from the input list.
Now, if I wanted to be extremely careful, I would add some checks and report errors on bad inputs:
(defun init-board (list)
(flet ((failure ()
(error "Input list should contain exactly 16 integers: ~S"
list)))
(loop
with current = list
repeat 4 collect
(loop
repeat 4
collect (if current
(let ((element (pop current)))
(check-type element integer)
element)
(failure)))
into board
finally (if list (failure) (return board)))))
Also, I would use a multi-dimensional array for boards.
(make-array '(4 4) :initial-contents (init-board list))
I just tested your three functions and it gave me the correct output, so perhaps your issue isn't where you think it is.
(initBoard '(4 5 15 10 14 11 1 8 9 16 6 3 7 2 12 13))
=> ((4 5 15 10) (14 11 1 8) (9 16 6 3) (7 2 12 13))
I would use the following recursive function:
(defun smalllist (l n)
(when l
(cons (subseq l 0 (min n (length l)))
(smalllist (nthcdr n l) n))))
I want to reverse only the continuous sequences, not all the elements of my original list.
Ex:
(reverseC '( 1 2 ( 4 5 ) 5 ) ) => ( 2 1 ( 5 4 ) 5 )
(reverseC '(1 4 2 (3 4) 9 6 (7 8)))) => (2 4 1 (4 3) 6 9 (8 7))
I was thinking of splitting it into 2 functions: one to reverse a simple list ( 1 2 3 ) -> ( 3 2 1 ) and one function
(main) to determine the continuous sequences, make a list out of them, apply reverse on that list and the remake the whole reversed list.
(defun reverse-list ( lista )
(if (eql lista () )
()
(append (reverse-list (cdr lista )) (list ( car lista)))
)
)
This is the reverse function but I have no idea how to do the other one. I'm new to Lisp and I come from Prolog so it's a pretty big change of scenery. Any idea is welcome.
(defun reverse-more (L)
(if (eql L nil)
nil
(let ( el (car L)) (aux (cdr L)))
(if (eql (listp el) nil)
...No idea on the rest of the code ...
There's already an accepted answer, but this seems like a fun challenge. I've tried to abstract some of the details away a bit, and produced a map-contig function that calls a function with each contiguous sublist of the input list, and determines what's a contiguous list via a predicate that's passed in.
(defun map-contig (function predicate list)
"Returns a new list obtained by calling FUNCTION on each sublist of
LIST consisting of monotonically non-decreasing elements, as determined
by PREDICATE. FUNCTION should return a list."
;; Initialize an empty RESULT, loop until LIST is empty (we'll be
;; popping elements off of it), and finally return the reversed RESULT
;; (since we'll build it in reverse order).
(do ((result '())) ((endp list) (nreverse result))
(if (listp (first list))
;; If the first element is a list, then call MAP-CONTIG on it
;; and push the result into RESULTS.
(push (map-contig function predicate (pop list)) result)
;; Otherwise, build up sublist (in reverse order) of contiguous
;; elements. The sublist is finished when either: (i) LIST is
;; empty; (ii) another list is encountered; or (iii) the next
;; element in LIST is non-contiguous. Once the sublist is
;; complete, reverse it (since it's in reverse order), call
;; FUNCTION on it, and add the resulting elements, in reverse
;; order, to RESULTS.
(do ((sub (list (pop list)) (list* (pop list) sub)))
((or (endp list)
(listp (first list))
(not (funcall predicate (first sub) (first list))))
(setf result (nreconc (funcall function (nreverse sub)) result)))))))
Here's your original example:
(map-contig 'reverse '< '(1 2 (4 5) 5))
;=> (2 1 (5 4) 5)
It's worth noting that this will detect discontinuities within a single sublist. For instance, if we only want continuous sequences of integers (e.g., where each successive difference is one), we can do that with a special predicate:
(map-contig 'reverse (lambda (x y) (eql y (1+ x))) '(1 2 3 5 6 8 9 10))
;=> (3 2 1 6 5 10 9 8)
If you only want to break when a sublist occurs, you can just use a predicate that always returns true:
(map-contig 'reverse (constantly t) '(1 2 5 (4 5) 6 8 9 10))
;=> (5 2 1 (5 4) 10 9 8 6)
Here's another example where "contiguous" means "has the same sign", and instead of reversing the contiguous sequences, we sort them:
;; Contiguous elements are those with the same sign (-1, 0, 1),
;; and the function to apply is SORT (with predicate <).
(map-contig (lambda (l) (sort l '<))
(lambda (x y)
(eql (signum x)
(signum y)))
'(-1 -4 -2 5 7 2 (-6 7) -2 -5))
;=> (-4 -2 -1 2 5 7 (-6 7) -5 -2)
A more Prolog-ish approach
(defun reverse-contig (list)
(labels ((reverse-until (list accumulator)
"Returns a list of two elements. The first element is the reversed
portion of the first section of the list. The second element is the
tail of the list after the initial portion of the list. For example:
(reverse-until '(1 2 3 (4 5) 6 7 8))
;=> ((3 2 1) ((4 5) 6 7 8))"
(if (or (endp list) (listp (first list)))
(list accumulator list)
(reverse-until (rest list) (list* (first list) accumulator)))))
(cond
;; If LIST is empty, return the empty list.
((endp list) '())
;; If the first element of LIST is a list, then REVERSE-CONTIG it,
;; REVERSE-CONTIG the rest of LIST, and put them back together.
((listp (first list))
(list* (reverse-contig (first list))
(reverse-contig (rest list))))
;; Otherwise, call REVERSE-UNTIL on LIST to get the reversed
;; initial portion and the tail after it. Combine the initial
;; portion with the REVERSE-CONTIG of the tail.
(t (let* ((parts (reverse-until list '()))
(head (first parts))
(tail (second parts)))
(nconc head (reverse-contig tail)))))))
(reverse-contig '(1 2 3 (4 5) 6 7 8))
;=> (3 2 1 (5 4) 8 7 6)
(reverse-contig '(1 3 (4) 6 7 nil 8 9))
;=> (3 1 (4) 7 6 nil 9 8)
Just two notes about this. First, list* is very much like cons, in that (list* 'a '(b c d)) returns (a b c d). list** can take more arguments though (e.g., **(list* 'a 'b '(c d e)) returns (a b c d e)), and, in my opinion, it makes the intent of lists (as opposed to arbitrary cons-cells) a bit clearer. Second, the other answer explained the use of destructuring-bind; this approach could be a little bit shorter if
(let* ((parts (reverse-until list '()))
(head (first parts))
(tail (second parts)))
were replaced with
(destructuring-bind (head tail) (reverse-until list '())
You can perform all at once with a single recursive function, with the usual warning that you should favor looping constructs over recursive approaches (see below):
(defun reverse-consecutive (list &optional acc)
(etypecase list
;; BASE CASE
;; return accumulated list
(null acc)
;; GENERAL CASE
(cons (destructuring-bind (head . tail) list
(typecase head
(list
;; HEAD is a list:
;;
;; - stop accumulating values
;; - reverse HEAD recursively (LH)
;; - reverse TAIL recursively (LT)
;;
;; Result is `(,#ACC ,LH ,#LT)
;;
(nconc acc
(list (reverse-consecutive head))
(reverse-consecutive tail)))
;; HEAD is not a list
;;
;; - recurse for the result on TAIL with HEAD
;; in front of ACC
;;
(t (reverse-consecutive tail (cons head acc))))))))
Exemples
(reverse-consecutive '(1 2 (3 4) 5 6 (7 8)))
=> (2 1 (4 3) 6 5 (8 7))
(mapcar #'reverse-consecutive
'((1 3 (8 3) 2 )
(1 4 2 (3 4) 9 6 (7 8))
(1 2 (4 5) 5)))
=> ((3 1 (3 8) 2)
(2 4 1 (4 3) 6 9 (8 7))
(2 1 (5 4) 5))
Remarks
#Melye77 The destructuring-bind expression does the same thing as [Head|Tail] = List in Prolog. I could have written this instead
(let ((head (first list))
(tail (rest list)))
...)
Likewise, I prefer to use (e)typecase over the generic cond expression whenever possible, because I think it is more precise.
I could have written:
(if acc
(if (listp (first list))
(nconc ...)
(reverse-consecutive ...))
acc)
... but I think it is less clear and not a good thing to teach beginners.
On the contrary, I think it is useful, even (especially) for beginners, to introduce the full range of available constructs.
For example, overusing recursive functions is actually not recommended: there are plenty of existing iteration constructs for sequences that do not depend on the availability of tail-call optimizations (which are not guaranteed to be implemented, though it is generally available with appropriate declarations).
Iterative version
Here is an iterative version which uses of the standard reverse and nreverse functions. Contrary to the above method, inner lists are simply reversed (contiguous chunks are only detected at the first level of depth):
(defun reverse-consecutive (list)
(let (stack result)
(dolist (e list (nreverse result))
(typecase e
(list
(dolist (s stack)
(push s result))
(push (reverse e) result)
(setf stack nil))
(t (push e stack))))))
I've been messing around with common LISP for a couple of weeks now, mostly attempting to practice recursion. What I want to do is to have a function
(defun rem (n l)
; code here
)
where n is always a non-negative integer and l can be an atom/list/null. The function removes the n-th element (one-based indexing) of:
the list (l) itself
any-level sub-lists that the original list contains
I reckon using remove and nth would make this task a piece of cake, but I've yet to have any success.
Any answers/actual code would be greatly appreciated. Thanks!
You didn't say if you wanted remove functionality or delete functionality. I'll do the non destructive versions here.
You can make remove-nth for one list by making a new list of all the elements before the index, then use the tail of the cons you want to remove to share as much structure as possible. Here is an implementation using subseq, nconc, and nthcdr to show how easy it is without recursion.
(defun remove-nth (n list)
(nconc (subseq list 0 n) (nthcdr (1+ n) list)))
(defparameter *test* (list 0 1 2 3 4 5 6))
(remove-nth 3 *test*) ; ==> (0 1 2 4 5 6)
(remove-nth 0 *test*) ; ==> (1 2 3 4 5 6)
A recursive function would look something like this:
(defun remove-nth-rec (n list)
(assert (not (null list)))
(if (zerop <??>)
<??>
(cons <??> (remove-nth-rec <??> <??>))))
You can make function that does this on each sublist recursively too. I'd do this with mapcar:
(defun remove-all-nth (n lol)
(mapcar (lambda (x) (remove-nth n x)) lol))
(remove-all-nth 0 '((a b c) (0 1 2) (I II III))) ; ==> ((b c) (1 2) (II III))
A recursive function would look something like this:
(defun remove-all-nth-rec (n list)
(if (null <??>)
nil
(cons (remove-nth-rec n <??>)
(remove-all-nth-rec n <??>))))