removing last element of a list(scheme) - scheme

So I have to remove the last element of a list in scheme.
For example, let's say I have a list (1 2 3 4). I need to return:
(1 2 3)
My idea:
reverse(list)
car(list)
reverse(list)
Is there a reverse function in scheme(racket)?

You wrote: "reverse, car, reverse". I believe you meant to write "reverse, cdr, reverse". There's nothing wrong with this solution; it's linear in the size of the list, just like any solution to this that uses the standard lists.
As code:
;; all-but-last: return the list, not including the last element
;; list? -> list?
(define (all-but-last l) (reverse (cdr (reverse l))))
If the multiple traversal of the list or the needless construction of another list copy bothers you, you can certainly avoid it, by writing the thing directly.
Given your almost-solution, I'm going to assume that this isn't homework.
Here's what it would look like, in racket:
#lang racket
(require rackunit)
;; all-but-last : return the list, except for the last element
;; non-empty-list? -> list?
(define (all-but-last l)
(cond [(empty? l) (error 'all-but-last "empty list")]
[(empty? (rest l)) empty]
[else (cons (first l) (all-but-last (rest l)))]))
(check-equal? (all-but-last '(3 4 5))
'(3 4))

There is a reverse, but using it would not be very efficient. I suggest the following recursive function.
(define (remove-last lst)
(if (null? (cdr lst))
'()
(cons (car lst) (remove-last (cdr lst)))))
(remove-last '(1 2 3 4)) ; returns '(1 2 3)
The if checks whether it is at the last element of the list.

SRFI 1 (activate in Racket using (require srfi/1)) has a drop-right function:
(drop-right '(1 2 3 4) 1) ; => (1 2 3)

I would do a recursive function that goes down the list and attaches the element (using cons) if the element after it is not the last, and appends nothing if it isn't.
I haven't done scheme for years though so that's as far as I can go.
Someone can run with how to implement it (unless it's homework then they probably shouldn't!)

I've done something simpler than: reverse(list), car(list), reverse(list) to get the last element, check out:
(define (last-one liste)
(if(null? (cdr liste))
null
(cons (car liste) (last-one (cdr liste)))
)
)

Those who are looking for another way can check this out:
(define (removing-last xx)
(remove (list-ref xx (- (length xx) 1)) xx))

I would write a simple recursion, altering the typical "empty? mylist" base case to "empty? (rest mylist)," so that I can return empty when the input list is only 1 element.
(define (removelast mylist)
(cond
[(empty? (rest mylist)) empty]
[(cons? mylist) (cons (first mylist) (removelast (rest mylist)))]))
(removelast (list 1 2 3 4 5))
By the way, this code is in Racket/PLT Scheme, a subset of Scheme.

Related

Can't get the end list i want in swapping procedure

Ultimately, i shall be trying to reimplement sorting algorithms in scheme for linked lists. I have written a subprocedure that will help me along the way. The goal is to simply swap 2 elements, given as arguments "pair1 and pair2" and then return the list.
(define (cons-til lst until)
(cond
((or (null? lst) (eq? (car lst) until)) '())
(else (cons (car lst) (cons-til (cdr lst) until)))))
(define (swap lst pair1 pair2)
(cons (cons (append (cons-til lst (car pair1))
(car pair2)) (car pair1)) (cdr pair2)))
(define my-list '(1 2 3 4 5 6 7))
(swap my-list (cdr (cdr my-list)) (cdr (cdr (cdr my-list))))
When the code is executed, it returns:
(((1 2 . 4) . 3) 5 6 7)
How can i fix this in order to have a plain scheme list. The element seems to have swapped correctly.
Two suggestions:
Do you really want to write n cdr calls to index the nth element? I recommend strongly using integer indexes (if you need them, that is).
Referring to elements by index in a linked list (i. e. “random access”) is not very efficient most of the time, especially when done in loops. I strongly recommend using either vectors or a better suited algorithm that doesn't need random access, e. g. merge sort.
(define (swap2 lst pair1 pair2)
(append (append (append (cons-til lst (car pair1))
(list (car pair2)))
(list (car pair1))) (cdr pair2)))
This code seems to work. I'm not sure this is completely efficient or a smart solution to the problem. Looking forward to other suggestions. The value given back is '(1 2 4 3 5 6 7)

Return the first and last element in the list Scheme

Pretty straightforward question. My initial approach was to define another procedure to find the last element of lst within first-last. After finding the last element I appended it with the first element of lst (car lst).
This is how append works.
(append list1 list2)
e.g., (append '(1 2 3) '(2 1 5)) -> (1 2 3 2 1 5)
I'm wondering if the problem is just with my syntax but I am not sure.
(define (first-last lst)
(define (last lst)
(cond ((null? (cdr lst))(car lst))
(else (last (cdr lst)))))
(append(car lst)(last lst)))
The error occurs in the
(append(car lst)(last lst)))
"mcar: contract violation
expected: mpair?
given: 1"
This is my first question on stack, so I'm sorry if the question is not presented in the correct way.
append is only for joining two or more lists. Here, though, you're not joining existing lists, but building a list from two elements. For that, use list:
(list (car lst) (last lst))
If you can use match, a neat solution is possible:
(define first-last
(lambda (x)
(match x
((first rest ... last)
(list first last))
((only) (list only only))
(_ #f))))
Of course, you could return something other than #f in the catch-all clause.

Scheme - Using cons properly to create lists

I've been trying to solve exercise 2.20 of SICP, where "dotted-tail" notation is introduced. My problem is that, instead of returning a proper list with results, my function returns a nested list.
I know that there is something wrong with the way I'm calling cons, but I still have no clue of how to solve the issue.
So here is my function:
(define (same-parity first . items)
(define (speccar items)
(cond ((null? items) 2)
((not (pair? items)) (modulo items 2))
(else (modulo (car items) 2))))
(define (iter-parity first items result)
(let ((parityFirst (modulo first 2)) (samepar (speccar items)))
(if (null? items)
result
(if (= parityFirst samepar)
;; This next line is where the problem is...
(iter-parity first (cdr items) (cons (list result) (list (car items))))
(iter-parity first (cdr items) result)))))
(iter-parity first items first))
Test:
(same-parity 1 2 3 4 5)
((((1) 3)) 5)
Now, I've read the following answers that deal with a similar problem:
Cons element to list vs cons list to element in Scheme
How to use 'cons' without generating nested lists in Scheme?
They certainly make it clear where the problem is coming from, but how does one go about to actually implement a proper solution?
And, if possible, what is the correct way of "thinking" in Scheme to avoid these traps/pitfalls?
You're incorrectly building the output list - remember: the first argument to cons should be the current element and the second argument, the result list.
Also, given that you're using tail recursion, you'll have to reverse the output at the end to preserve the same order as in the original list. Try this:
(define (same-parity first . items)
(define (speccar items)
(cond ((null? items) 2)
((not (pair? items)) (modulo items 2))
(else (modulo (car items) 2))))
(define (iter-parity first items result)
(let ((parityFirst (modulo first 2))
(samepar (speccar items)))
(if (null? items)
(reverse result)
(if (= parityFirst samepar)
(iter-parity first
(cdr items)
(cons (car items) result))
(iter-parity first
(cdr items)
result)))))
(iter-parity first items (list first)))
The above solution can be greatly simplified if we use built-in procedures (don't reinvent the wheel!). This is the recommended way to write programs in Scheme - adhering to a functional style:
(define (same-parity head . tail)
(if (even? head)
(filter even? (cons head tail))
(filter odd? (cons head tail))))
Either way, it works as expected:
(same-parity 1 2 3 4 5)
=> '(1 3 5)

Converting a list to a circular list in Chicken scheme?

In trying to find how to convert such a list, I came across
Scheme streams and circular lists. However, that answer requires features in Racket not available in Chicken scheme. Can Anyone point Me in the direction of how to do this in Chicken scheme instead? Or in a scheme-variant-neutral fashion?
If you can mutate the list, here's a standard way:
(define (make-circular lst)
; helper for finding the last pair in a list
(define (last-pair lst)
(if (null? (cdr lst))
lst
(last-pair (cdr lst))))
; special case: if the list is empty
(cond ((null? lst) '())
(else
; set the last pair to point to the head of the list
(set-cdr! (last-pair lst) lst)
lst)))
Be aware that the above will modify the input list. Other than that, it works as expected:
(make-circular '(1 2 3 4 5))
=> #0=(1 2 3 4 5 . #0#)
(car (cdr (cdr (cdr (cdr (cdr (make-circular '(1 2 3 4 5))))))))
=> 1
It is pretty simple when you use SRFIs:
(use srfi-1)
(define l '(1 2 3 4))
(apply circular-list l)

recursive function accepts list in scheme

I'm new to Scheme and this is my very first Functional language. Implementing almost everything recursively seems to be awkward for me. Nevertheless, was able to implement functions of Factorial and Fibonacci problems having a single integer input.
However, what about when your function has an input of a list? Suppose this exercise:
FUNCTION: ret10 - extracts and returns as a list all the numbers greater than 10
that are found in a given list, guile> (ret10 ‘(x e (h n) 1 23 12 o))
OUTPUT: (23 12)
Should I have (define c(list)) as the argument of my function in this? or is there any other way?
Please help. Thanks!
Here's my derived solution based on sir Óscar López's answer below.. hope this helps others:
(define (ret10 lst)
(cond
((null? lst) '())
((and (number? (car lst)) (> (car lst) 10))
(cons (car lst)
(ret10 (cdr lst))))
(else (ret10 (cdr lst)))
)
)
This kind of problem where you receive a list as input and return another list as output has a well-known template for a solution. I'd start by recommending you take a look at The Little Schemer or How to Design Programs, either book will teach you the correct way to start thinking about the solution.
First, I'll show you how to solve a similar problem: copying a list, exactly as it comes. That'll demonstrate the general structure of the solution:
(define (copy lst)
(cond ((null? lst) ; if the input list is empty
'()) ; then return the empty list
(else ; otherwise create a new list
(cons (car lst) ; `cons` the first element
(copy (cdr lst)))))) ; and advance recursion over rest of list
Now let's see how the above relates to your problem. Clearly, the base case for the recursion will be the same. What's different is that we cons the first element with the rest of the list only if it's a number (hint: use the number? procedure) and it's greater than 10. If the condition doesn't hold, we just advance the recursion, without consing anything. Here's the general idea, fill-in the blanks:
(define (ret10 lst)
(cond (<???> <???>) ; base case: empty list
(<???> ; if the condition holds
(cons <???> ; `cons` first element
(ret10 <???>))) ; and advance recursion
(else ; otherwise
(ret10 <???>)))) ; simply advance recursion
Don't forget to test it:
(ret10 '(x e (h n) 1 23 12 o))
=> '(23 12)
As a final note: normally you'd solve this problem using the filter procedure - which takes as input a list and returns as output another list with only the elements that satisfy a given predicate. After you learn and understand how to write a solution "by hand", take a look at filter and write the solution using it, just to compare different approaches.
Solve the problem for the first element of the list and the recurse on rest of the list. Make sure you handle the termination condition (list is null?) and combine results (cons or append in the following)
(define (extract pred? list)
(if (null? list)
'()
(let ((head (car list))
(rest (cdr list)))
(cond ((pred? head) (cons head (extract pred? rest)))
((list? head) (append (extract pred? head)
(extract pred? rest)))
(else (extract pred? rest))))))
(define (ret10 list)
(extract (lambda (x) (and (number? x) (> x 10))) list))
> (ret10 '(0 11 (12 2) 13 3))
(11 12 13)

Resources