I'm currently working on a program that increments through a list and creates a sublist within a list for each time it's incremented. for example if I had a list of
(1 2 3 4 5 6)
. Then I want to increment through it and create
(1 (2 (3 (4 (5 (6))))))
. So far I have:
(defun INCREMENT (L) (unless (endp L) (cons (list (first L)) (INC (rest L)))))
but all this will return is
((1) (2) (3) (4))
I know it's just increment the number of times list is used along with going through the elements of the list but I'm still kind of learning the syntax of Lisp. Can anybody help me out with this?
Here's a possible solution, the trick is to use list before calling the recursion. Also notice that we must handle the base cases: when the list is empty and when there's only one element left:
(defun INCREMENT (L)
(cond ((endp L) '())
((endp (rest L)) (list (first L)))
(t (cons (first L)
(list (INCREMENT (rest L)))))))
Related
I need help merging two lists together. My goal is to replace "a" with "abc". I've already done a counter etc but somehow I can't append these two lists (list which is an empty list and '("abc") as my new list that I want to add).
I've tried to add more brackets but the problem just keeps getting worse the more I add.
(define (umwandl tr)
(cond ((null? tr) (display "Kein Text eingegeben"))
(else (uff (string->list tr) '())))) ; string wird nict inliste umgweandel
(define (uff tr liste)
(cond ((null? tr)(list->string liste))
(else
(cond ((equal? (first (rest (first (start1 (first tr))))) 1)
**((append list (list '("abc"))))))**
(uff (rest tr) liste))))
My error messages are either that ('("abc")) isn't an argument or it just gives me "" as an answer. It would be super nice if anyone could help!
Learning Scheme or any Lisp means getting to know list structure. A list (1 2 3) can be made like (cons 1 (cons 2 (cons 3 '()))) and I like to think that element in a list that does not have a . means there is one and the rest has an extra set of paranthesis. Done recursive! Thus:
'(1 2 3) ; ==
'(1 . (2 3)) ; ==
'(1 . (2 . (3))) ; ==
'(1 . (2 . (3 . ()))) ; ==> (1 2 3)
I see the dots that aren't there when I see lists so I know 3 is caddr since I pass . ( 2 times (dd) and then jump into the car, thus caddr.
Appending two lists together means copying the first list and replaceing () with the second list. Thus append can be defined as:
(define (my-append l1 l2)
(if (null? l1)
l2
(cons (car l1)
(my-append (cdr l1) l2))))
Replacing one element with another. You need to do the same BUT you compare the first element in each iteration and based on that either use the element you found or the replacement. If you want to compare strings then you need to use equal? since (eqv? "hello" "hello") ; ==> #f is a valid result.
I have a circular list, eg: #0=(1 2 3 4 . #0#).
What I want to do is to insert a new element (x) into this list so that the outcome is #0=(x 1 2 3 4 . #0#). I have been trying using this code (x is the circular list):
(define (insert! elm)
(let ((temp x))
(set-car! x elm)
(set-cdr! x temp)))
However, I think that set-cdr! is not working like I want it to. What am I missing here? Maybe I am way off?
The easiest way to prepend an element to a list is to modify the car of the list, and set the cdr of the list to a new cons whose car is the original first element of the list and whose cdr is the original tail of the list:
(define (prepend! x list) ; list = (a . (b ...))
(set-cdr! list (cons (car list) (cdr list))) ; list = (a . (a . (b ...)))
(set-car! list x)) ; list = (x . (a . (b ...)))
(let ((l (list 1 2 3)))
(prepend! 'x l)
(display l))
;=> (x 1 2 3)
Now, that will still work with circular lists, because the cons cell (i.e., pair) that is the beginning of the list remains the same, so the "final" cdr will still point back to object that is the beginning. To test this, though, we need some functions to create and sample from circular lists, since they're not included in the language (as far as I know).
(define (make-circular list)
(let loop ((tail list))
(cond
((null? (cdr tail))
(set-cdr! tail list)
list)
(else
(loop (cdr tail))))))
(define (take n list)
(if (= n 0)
'()
(cons (car list)
(take (- n 1)
(cdr list)))))
(display (take 10 (make-circular (list 1 2 3))))
;=> (1 2 3 1 2 3 1 2 3 1)
Now we can check what happens if we prepend to a circular list:
(let ((l (make-circular (list 1 2 3))))
(prepend! 'x l)
(display (take 15 l)))
;=> (x 1 2 3 x 1 2 3 x 1 2 3 x 1 2)
Since you're trying to prepend an element to a circular list, you need to do two things:
Insert a new cons cell at the front of the list containing the additional element. This is easy because you can just perform a simple (cons elm x).
You also need to modify the recursive portion of the circular list to point at the newly created cons cell, otherwise the circular portion will only include the old parts of the list.
To perform the latter, you need a way to figure out where the "end" of the circular list is. This doesn't actually exist, since the list is, of course, circular, but it can be determined by performing an eq? check on each element of the list until it finds an element equal to the head of the list.
Creating a helper function to do this, a simple implementation of insert! would look like this:
(define (find-cdr v lst)
(if (eq? v (cdr lst)) lst
(find-cdr v (cdr lst))))
(define (insert! elm)
(set! x (cons elm x))
(set-cdr! (find-cdr (cdr x) (cdr x)) x))
I'm trying to write a function using Scheme that :
take a list of integers with more than two elements as a parameter
sum the n-th-element and (n+1)-th-element
return this list
Result should be as follows :
> (SumNeighbors (list 1 2 3 4))
(3 5 7)
I think I get the way to add elements but my recursion is totally wrong...
(define (SumNeighbors lst)
(if (not (null? (cdr lst)))
(append (list (+ (car lst) (car (cdr lst)))) (SumNeighbors (cdr lst)))))
Any help would be appreciated.
The solution to this problem follows a well-known pattern. I'll give you some hints, it'll be more fun if you find the answer by your own means:
(define (SumNeighbors lst)
(if <???> ; if there's only one element left
<???> ; we're done, return the empty list
(cons ; otherwise call `cons`
(+ <???> <???>) ; add first and second elements
(SumNeighbors <???>)))) ; and advance recursion
Notice the following:
Your solution is lacking the base case - what happens when the list we're traversing only has one element left? it's time to finish the recursion! and because we're building a list as the output, what should be the value returned?
We normally use cons to build an output list, not append. That's the natural way to build a list
The part of this procedure that falls outside the solution template is the fact that we stop when there's a single elment left in the list, not when the list is empty (as is the usual case)
You'll see that many procedures that iterate over an input list and return a list as output follow the same solution template, it's very important that you learn how and why this works, it's the foundation for writing solutions to other similar problems.
#!r6rs
(import (except (rnrs base) map)
(only (srfi :1) map))
(define (sum-neighbors lst)
(map + lst (cdr lst)))
The higher order function map as defined in SRFI-1 supports uneven lenght arguments. It will stop at the shortest list.
If you call (sum-neighbors '(1 2 3 4)) it will become (map + (1 2 3 4) (2 3 4)) which is the same as (cons (+ 1 2) (cons (+ 2 3) (cons (+ 3 4) '())))
I'm having trouble with the output of my code, I think it's when I'm checking conditions for the null of my lists.
The question I am trying to complete is: Write a function vecmul that will take as inputs two simple lists of numbers. vecmul should multiply these lists coordinate-wise as one would multiply vectors. Assume the two lists are the same length. [For example, (vecmul '(2 3 4 5) '(1 4 5 2)) returns (2*1 3*4 4*5 5*2) or (2 12 20 10). You are not allowed to use mapcar for this function]
So far I have
(defun vecmul (list list2)
(cond ((null list) 0)
(t (cons (* (car list) (car list2))
(vecmul (cdr list) (cdr list2))))))
[170]> (setq l '(2 4 6))
(2 4 6)
[171]> (setq r '(1 3 5))
(1 3 5)
[172]> (vecmul l r)
(2 12 30 . 0)
I'm getting the correct numbers, it's just that the list is adding the "." and the "0" at the end of the list. I'm pretty sure it's because i'm not stopping the recursion right or not working the cond right. I'm just not entirely sure how to correct it.
You've got it almost right. However, you're terminating your list with 0, when the correct termination is nil. This code works:
(defun vecmul (list list2)
(cond ((null list) nil)
(t (cons (* (car list) (car list2)) (vecmul (cdr list) (cdr list2))))))
When you call (cons 1 2), the cons cell you get is written (1 . 2). the notation (1 2 3 4 5) is just shorthand for (1 . (2 . (3 . (4 . (5 . nil))))). If the cdr of the last cons cell is 6, not nil, then you get (1 . (2 . (3 . (4 . (5 . 6))))), which shortens to (1 2 3 4 5 . 6).
Neil Forrester answered your question.
Some more remarks. Use modern names in Lisp: first and rest.
(defun vecmul (list1 list2)
(cond ((null list1) nil)
(t (cons (* (first list1) (first list2))
(vecmul (rest list1) (rest list2))))))
If you have a simple true and false decision, IF might be better. Since list operations are involved, I would write it as the following and not use WHEN.
(defun vecmul (list1 list2)
(if (null list1)
nil
(cons (* (first list1) (first list2))
(vecmul (rest list1) (rest list2)))))
Best use a loop construct or mapping in real code. Recursion, as above, has a stack depth limit. A loop does not have that restriction.
(defun vecmul (list1 list2)
(loop for e1 in list1 and e2 in list2
collect (* e1 e2)))
or
(defun vecmul (list1 list2)
(mapcar #'* list1 list2))
How would you define a function which takes one argument, which should be a list, and returns the elements in the
list which are themselves lists?
(check-expect (find-sublists ’(1 2 () (3) (a b c) a b c))
’(() (3) (a b c)))
Do you have experience designing functions that can filter through a list?
A simpler problem with the same flavor as the original is something like this: design a function that takes a list of numbers and keeps only the even numbers. Would you be able to do that function?
Looking at http://www.ccs.neu.edu/home/matthias/HtDP2e/htdp2e-part2.html and going through its guided exercises may also help.
Two useful tools which should start you on your way:
1) Traversing through a list:
; traverse: takes a list of numbers
; Goes through each element, one-by-one, and alters it
(define traverse
(lambda (the_list)
(if (empty? the_list)
empty
(cons (+ 1 (first the_list))
(traverse (rest the_list))))))
(traverse (cons 3 (cons 4 empty))) returns (cons 4 (cons 5 empty))
2) list?:
(list? (list 1 2 3)) returns #t
(list? 5) returns #f