I don't know how I can append an element in n position in a list.
For example:
(insert-at new k lis)
(insert-at ’N 2 ’(a b c d e f))
=>
’(a b N c d e f)
It is ok?:
(define (insert-at new k lis)
(cond (( null? lis)
(list new))
(zero? k
(cons new lis))
(else
(cons (car lis)
(insert-at new (- k 1) (cdr lis))))))
I'll give you some hints - because this looks like homework, I can't give you a straight answer, and it'll be much more useful if you arrive at the solution by your own means. Fill-in the blanks:
(define (insert-at new k lis)
(cond (<???> ; if the list is empty
<???>) ; return a list with the single element `new`
(<???> ; if `k` is zero
<???>) ; cons `new` with the list
(else ; otherwise
(cons <???> ; cons the lists' current element and
(insert-at new <???> <???>))))) ; advance the recursion
Notice that here, "advancing the recursion" means passing the rest of the list and decrementing the k index by one unit. We're done once the k index is zero or the list's end is reached. Don't forget to test the procedure:
(insert-at 'N 2 '(a b c d e f))
=> '(a b N c d e f)
(insert-at 'N 0 '(a b c))
=> '(N a b c)
(insert-at 'N 3 '(a b c))
=> '(a b c N)
If you had two functions:
take-n - which returns as a list the first N elements, and
last-n - which returns as a list the last N elements
then you could write:
(define (insert-at value index list)
(let ((len (length list)))
(assert (<= 0 index len))
(append (take-n index list)
(list value)
(last-n (- len index) list))))
(DEFUN INS-ELEM (Nth item list)
(COND
((< Nth 1) (ERROR "Index too small ~A" Nth))
((= Nth 1) (CONS item list))
((ENDP list) (ERROR "Index too big"))
(T (CONS (FIRST list) (INS-ELEM (1- Nth) item(REST list))))))
Then, just call (INS-ELEM 2 'A '(B C D E F)) and view the result for yourself.
Good luck!
#lang racket
(define (insert-at Index item lst)
(cond
[(< Index 1) (error "Index too small: " Index)]
[(= Index 1) (cons item lst)]
[(> Index (length lst)) (error "Index too big: " Index)]
[else (cons (first lst) (insert-at (- Index 1) item (rest lst)))]))
user3660248
Your idea of how to solve this problem seems right and makes sense, but your implementation of it in Racket was not right and I fixed it and now it works :)
Related
Write a function that takes a list and a length as input and returns two lists: (1) The first length elements of the input list, and (2) the remainder of the input list. Hint: Use a helper method with an "accumulator" parameter. I'm stuck guys and could really use some help.
I keep getting error when I try to do (split-list '(a b c d e f g) 7) which is the number equal to length otherwise any number less than than that does what its supposed to do
:
Argument #1 '()' to 'car' has wrong type (empty-list)
(split-list '(a b c d e f g) 0) should return '(() (a b c d e f g))
(split-list '(a b c d e f g) 1) should return '((a) (b c d e f g))
(split-list '(a b c d e f g) 3) should return '((a b c) (d e f g))
(define (split-list lst length)
(define(split-list-head accum length)
(if (= length 0)
(cdr '(accum))
(cons (car accum) (split-list-head (cdr accum)(- length 1)))
)
)
(define(split-list-tail accum length)
(if (= length 0)
(cons (car accum)(cdr accum))
(split-list-tail (cdr accum)(- length 1))
)
)
(if (eq? length 0)
(append(list (list))(list lst))
(append(list(split-list-head lst length)) (list(split-list-tail lst length)))
)
)
Unless you are particularly attached to GNU Scheme, I would consider moving to Dr Racket.
Although it was written for a similar language called Racket, it can be set up to run vanilla Scheme, by putting in a first line #lang scheme
The nice about Dr Racket is that it has a very nice debugger.
My code, with the #lang line at the start, and the erroring line at the bottom:
#lang scheme
(define (split-list lst length)
(define(split-list-head accum length)
(if (= length 0)
(cdr '(accum))
(cons (car accum) (split-list-head (cdr accum)(- length 1)))
)
)
(define(split-list-tail accum length)
(if (= length 0)
(cons (car accum)(cdr accum))
(split-list-tail (cdr accum)(- length 1))
)
)
(if (eq? length 0)
(append(list (list))(list lst))
(append(list(split-list-head lst length)) (list(split-list-tail lst length)))
)
)
(split-list '(a b c d e f g) 7)
If I just run the code, it highlights the error in split-list-tail, where car causes a contract violation. It also shows the call sequence.
That's probably enough to identify the fault, but I can also run the debugger. By clicking on the Debug button I move to the debug mode. By moving the mouse pointer over a parenthesis, and right clicking, I can enable or disable a pause at this point - show by a pink circle. The variables are shown on the right hand side. When I run the code in the debugger, variable accum is empty, hence car accum fails.
My suggestion is that you use pair? or null? to test accum before calling car on it.
Try this. It makes use of three accumulating parameters. A subtraction is also kind of accumulation.
(define (split n xs k)
(define (loop xs n k)
(if
(and (> n 0) (not (null? xs)))
(loop (cdr xs) (- n 1)
(lambda (a b) (k (cons (car xs) a) b)))
(k '() xs)))
(loop xs n k))
Can you see how it is to be called?
Can you explain how it works?
Or a bit shorter,
(define (split n xs k)
(define ((+ f a) b) (f (cons (car a) b)))
(define (loop xs n k)
(if
(and (> n 0) (not (null? xs)))
(loop (cdr xs) (- n 1) (+ k xs))
((k '()) xs)))
(loop xs n k))
Can you find a way how should this function be called? I'll give you a hint, how should this function
(define ((add a) b) (list a b))
be called?
Suppose, I got a list(s) in Racket of:
`(1 2 3)
`(1 2 3 4)
`((1 2) (3) (4)))
Then when I exchange it (first and third element), it will look like:
`(3 2 1)
`(3 2 1 4)
`((4) (3) (1 2))
Please note: I may only use things such as cons, first, and rest for this.
Here's my current try:
(define new-list
(lambda(list)
(first (rest (rest list))))) ; Get third element.
I cannot replicate the results above. I would like to be shown how it's done.
Just play with it a little:
> '(one)
'(one)
> '(one two three)
'(one two three)
> (first '(one two three four))
'one
> (rest '(one two three four))
'(two three four)
> (define foo (lambda (lst)
(cons (first lst) (rest lst))))
> (foo '(one two three four))
'(one two three four)
> (define bar (lambda (lst)
(cons (first (rest lst))
(cons (first lst) (rest lst)))))
> (bar '(one two three four))
'(two one two three four)
Now you have everything to complete the process.
To write your procedure, we want to take an input list xs, and construct a new list like
(cons (third-element xs)
(cons (second-element xs)
(cons (first-element xs)
(everything-except-the-first-three-elements xs)))
In racket you have car and cdr, but you also have cadr, caddr, cddddr and everything in betweeen.
To get an intuition for them, a reads the head, d reads the tail, so
car gets the head (the first element in a list)
cdr gets the tail (everything except the first element in a list)
cadr gets the head of the tail (the second element in a list)
cddr gets the tail of the tail (everything except the first and second elements in a list)
caddr gets the head of the tail of the tail (the third element in a list)
and so on ...
We can write this easily using our car and cdr helpers
(define (swap xs)
(cons (caddr xs) ; cons the third element ...
(cons (cadr xs) ; onto the second element ...
(cons (car xs) ; onto the first element ...
(cdddr xs))))) ; onto the tail of the third element
(swap '(1 2 3)) ; '(3 2 1)
(swap '(1 2 3 4)) ; '(3 2 1 4)
(swap '((1 2) (3) (4))) ; '((4) (3) (1 2))
(define nth
;; Return nth element of list
(lambda (lst n)
(cond ((null? lst) 'nil)
((zero? n) (car lst))
(else (nth (cdr lst) (- n 1))))))
(define slice
;; Return lst sliced like python
(lambda (lst a b acc)
(cond ((null? lst) (reverse acc))
((< b a) (reverse acc))
((zero? b) (reverse acc))
((zero? a) (slice (cdr lst) 0 (- b 1) (cons (car lst) acc)))
(else (slice (cdr lst) (- a 1) (- b 1) acc)))))
(define swap
;; Return nth and mth element swapped list
(lambda (lst n m)
`(,#(slice lst 0 n '())
,(nth lst m)
,#(slice lst (+ n 1) m '())
,(nth lst n)
,#(slice lst (+ m 1) (length lst) '()))))
This swaps any two given positions m and n and returns the resulting list.
(swap your-list 0 2) ; returns your-list 1st and 3rd elements swapped
How do i do in Racket a function that replaces the element of a list at the position n by e.
(repl-elem '(a b c d e) 2 d)
should return a d c d e
In order to replace the element with index 2 in a list with a new element 'A,
one can do the following:
#lang racket
(define xs (list 1 2 3 4 5))
(append (take xs 2)
(list 'A)
(drop xs (+ 2 1)))
I'll leave it as an exercise to turn this into a function.
To see "the mechanics behind this list-set" one can use 'named let' recursion:
(define (f L n c)
(let loop ((x 1)
(ol '()))
(cond
[(> x (length L))
(reverse ol)]
[(= x n)
(loop (add1 x) (cons c ol))]
[else
(loop (add1 x) (cons (list-ref L (sub1 x)) ol))])))
Testing:
(f '(a b c d e) 2 'd)
Output:
'(a d c d e)
OP can figure out how it is working.
Is it possible to add or remove elements in the middle of a linked list in Scheme? I can't seem to think of a way doing this with car/cdr/cons, but I reccon there must be a way to this.
If I have a list '(1 3 5 6), and I need to put in 4 between 5 and 6 for example, is this doable?
Adding an element at a given position was done in a previous answer. Removing an element at a given position is similar:
(define (delete-at k lst)
(cond ((null? lst)
'())
((zero? k)
(cdr lst))
(else
(cons (car lst)
(delete-at (sub1 k) (cdr lst))))))
Here are two versions:
; list-insert : value index list -> list
; return list where the ith element is x
(define (list-insert x i xs)
(if (= i 0)
(cons x xs)
(cons (first xs) (list-insert x (- i 1) (rest xs)))))
(define (list-insert/version2 x i xs)
(define-values (before after) (split-at xs i))
(append before (list x) after))
(list-insert/version2 'x 2 '(a b c d))
(list-insert 'x 2 '(a b c d))
Both versions will allocate a new list. For large lists it will become inefficient.
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)))))