scheme multiply list items - scheme

I looked and looked, but was surprised not to find an answer to this question.
In R5RS scheme, how would you write a procedure that multiplies each element of the list with one-another. If I'm given a list '(4 5 6), the procedure, multiply-list, should return 120. 4*5*6=120.
Thanks in advance.

(define (multiply-list l) (apply * l))
As trivial as it gets. That's probably why you never found the answer: no one ever bothered writing it down…

The "suggested" way:
(define mult
(lambda (the-list)
(apply * the-list)))
An iterative implementation:
(define mult-it
(lambda (the-list)
(let ((result 1))
(begin
(for-each
(lambda (x)
(set! result (* result x)))
the-list)
result))))
A purely functional and recursive implementation:
(define mult-rec
(lambda (the-list)
(if (null? the-list)
1
(* (car the-list) (mult-rec (cdr the-list))))))

(define (multiply-list list)
(let loop ((list list) (accum 1))
(cond
((null? list) accum)
((not (number? (car list))) '())
(else (loop (cdr list) (* accum (car list)))))))

Related

How to find the mean of a list with mixed symbols (numbers and characters) in scheme?

Given a list of the type '('a 1 'b 2 'c 3) I want to calculate the mean of the numbers in the list.
This is what I have done so far: I have written 3 functions that work correctly, one to remove the characters, the other to calculate the sum of the numbers in a list, and the other to find the average. But I do not know how to put them together to solve my problem.
;remove all non numbers from a list:
(define (all-numbers x)
(cond ((null? x) null)
((integer? (car x)) (cons (car x) (all-numbers (cdr x))))
(else (all-numbers (cdr x)))))
;sum the elements of the list
(define (sumlist lst)
(cond ((null? lst) 0)
(( + (car lst) (sumlist (cdr lst))))))
; find the mean of the list
(define (a_mean lst)
(cond ((null? lst) 0)
((/ (sumlist lst) (length lst)))))
(a_mean '(1 2 3))
;find the mean of a mixed list
(define (m_mean lst)
(cond ((null? lst) 0)
((/ (sumlist ((all-numbers lst)) (length (all-numbers lst)))))))
(m_mean '('a 1 'b 2 'c 3))
I get an error in the above code for m_mean. Please help! Thanks.
The answer by Óscar López should fix your problems.
I will now provide a more concise way of solving the same problem:
(define (m-mean lst)
(define all-numbers (filter number? lst)) ; Filter out all the non-numbers.
(if (null? all-numbers)
0 ; The mean is 0 if there are no numbers.
(/ (apply + all-numbers) (length all-numbers)))) ; Calculate mean.
This way, you do not have to explicitly define the all-numbers and sumlist functions.
For starters, some of your cond expressions are missing the else keyword in the final condition - this is mandatory, as you did in all-numbers. Also, in m_mean there are a couple of incorrect brackets; this should fix the errors:
(define (m_mean lst)
(cond ((null? lst) 0)
(else (/ (sumlist (all-numbers lst))
(length (all-numbers lst))))))
Now it works as expected:
(m_mean '(a 1 b 2 c 3))
=> 2

Scheme quick-sort with filter

I need to write the function (quick-sort pred lst)
lst is the list of numbers to be sorted
pred is the predicate by which the list is ordered, the signature of this predicate is: (lambda (x y) …)
- (quick-sort < lst) will sort ascending (small to large)
- (quick-sort > lst) will sort descending (large to small)
- (quick-sort (lambda (x y) (< (car x) (car y))) lst) will sort a list
with inner lists according to the first element of the inner list, ascending.
I started with regular quick-sort:
(define (quick-sort lst)
(cond
((null? lst) '())
((= (length lst) 1) lst)
(else (append (quick-sort (filter (lambda (n) (< n (car lst))) lst))
(list (car lst))
(quick-sort (filter (lambda (n) (> n (car lst))) lst))))))
And now I'm trying to do this with pred:
(define (quick-sort pred lst)
(define (quick-sort-help lst)
(cond ((null? lst) ())
((= (length lst) 1) lst)
(else
(append (quick-sort-help (filter (lambda (n) (pred n (car lst))) lst))
(list (car lst))
(quick-sort-help (filter (lambda (n) (not(pred n (car lst)))) lst)))))) (quick-sort-help lst))
And I get an infinite recursion or something.
Can you help me solve this problem please?
Thanks!
First of you don't need the helper function quick-sort-help.
It recurs infinitely because you apply your helper function to lst instead cdr lst. In your regular quicksort you have (filter (lambda (n) (< n (car lst))) and (filter (lambda (n) (> n (car lst))). But then in the one with the predicate you have the problem that (not (pred ...) would cover the cases for <= and not < if the predicate is > and vice versa. So it gets stuck because the first element in the list is always equal with itself.
Here a correct quicksort:
(define (qsort f lst)
(if (null? lst)
null
(let ([pivot (car lst)])
(append (qsort f (filter (λ (n) (f n pivot)) (cdr lst)))
(list pivot)
(qsort f (filter (λ (n) (not (f n pivot))) (cdr lst)))))))

Scheme write a function that returns number of odd numbers in a list

I'm having trouble writing a function in Scheme that returns the number of odd numbers in a list without using any assignment statements. I'm trying to use the predicate odd? as well. Any help/tips would be appreciated.
Ex: (odds '(1 2 3 4 5) // returns 3
Also, the list is of integers
Well, if no assignment statements can be used, you can still use the built-in procedures for this. In particular, count will work nicely in Racket:
(define (odds lst)
(count odd? lst))
... But I'm guessing that you're supposed to implement the solution from scratch. Some hints for finding the solution on your own, fill-in the blanks:
(define (odds lst)
(cond (<???> ; if the list is empty
<???>) ; then how many odd numbers are in it?
((odd? <???>) ; if the first element is odd
(<???> (odds <???>))) ; then add one and advance recursion
(else ; otherwise
(odds <???>)))) ; just advance the recursion
Anyway, it works as expected:
(odds '(1 2 3 4 5))
=> 3
Regardless if you use (R6RS?) Scheme or Racket, this will work for both:
(define (odds lst)
(length (filter odd? lst)))
(define l '(1 2 3 4 5 6 7 8 9 10))
(odds l)
As low level as I can get it :
(define odds
(lambda (lst)
(cond ((empty? lst) 0)
((not (= 0 (modulo (car lst) 2))) (+ 1 (odds (rest lst))))
(else (odds (cdr lst))))))
Here's another one-liner
(define (odds L)
(reduce + 0 (map (lambda (x) (if (odd? x) 1 0)) L)))
Here is a function that returns a function that counts anything based on a predicate:
(define (counter-for predicate)
(define (counting list)
(if (null? list)
0
(+ (if (predicate (car list)) 1 0)
(counting (cdr list)))))
counting))
which is used like:
(define odds (counter-for odd?))
[MORE OPTIONS] Here is a nice recursive solution
(define (odds list)
(if (null? list)
0
(+ (if (odd? (car list)) 1 0)
(odds (cdr list)))))
here is a tail recursive solution:
(define (odds list)
(let odding ((list list) (count 0)))
(if (null? list)
count
(odding (cdr list)
(+ count (if (odd? (car list)) 1 0))))))
Here is a routine that counts anything based on a predicate:
(define (count-if predicate list)
(if (null? list)
0
(+ (if (predicate (car list)) 1 0)
(count-if predicate (cdr list)))))

Deep-reverse for trees in Scheme (Lisp)

I have a deep reverse for a basic tree data structure in Scheme
(define (deep-reverse t)
(cond ((null? t) '())
((not (pair? t)) t)
(else (cons (deep-reverse (cdr t)) (deep-reverse (car t))))))
(define stree (cons (list 1 2) (list 3 4)))
1 ]=> (deep-reverse stree)
;Value: (((() . 4) . 3) (() . 2) . 1)
I feel like a cleaner, better result would be:
(4 3 (2 1))
Can anyone provide some guidance as to where I'm going wrong in my deep-reverse function? Thank you.
It's better to split the task into simple operations instead of trying to do all at once. What you want to achieve can be described like this: Reverse the current list itself, then deep-reverse all sublists in it (or the other way round, the order of the two steps doesn't really matter. I choose this order because it results in nicer formatting of the source code).
Now, there already is a function in the standard library for simply reversing a list, reverse. So all you need to do is to combine that with the recursion on those elements that are sublists:
(define (deep-reverse t)
(map (lambda (x)
(if (list? x)
(deep-reverse x)
x))
(reverse t)))
Try this:
(define (deep-reverse t)
(let loop ((t t)
(acc '()))
(cond ((null? t) acc)
((not (pair? t)) t)
(else (loop (cdr t)
(cons (loop (car t) '()) acc))))))
Call it like this:
(define stree (cons (list 1 2) (list 3 4)))
(deep-reverse stree)
> (4 3 (2 1))
For creating a reversed list, one technique is to accumulate the answer in a parameter (I usually call it acc). Since we're operating on a list of lists, the recursion has to be called on both the car and the cdr part of the list. Lastly, I'm using a named let as a shorthand for avoiding the creation of an extra function, but the same result could be obtained by defining a helper function with two parameters, the tree and the accumulator:
(define (deep-reverse t)
(aux t '()))
(define (aux t acc)
(cond ((null? t) acc)
((not (pair? t)) t)
(else (aux (cdr t)
(cons (aux (car t) '()) acc)))))
I think it better to reverse a list based on its element count:
an empty list is reverse, a single element list is also reverted, more than 1 element is concatenation of the reverse of tail and head.
(defun deep-reverse (tree)
(cond ((zerop (length tree)) nil)
((and (= 1 (length tree)) (atom (car tree))) tree)
((consp (car tree)) (append (deep-reverse (cdr tree))
(list (deep-reverse (car tree)))))
(t (append (deep-reverse (cdr tree)) (list (car tree))))))
The following worked for me:
(define (deep-reverse tree)
(define (deep-reverse-iter items acc)
(cond
((null? items) acc)
((not (pair? items)) items)
(else (deep-reverse-iter
(cdr items)
(cons (deep-reverse (car items)) acc)))))
(deep-reverse-iter tree ()))
(define x (list (list 1 2) (list 3 4 (list 5 6))))
(newline)
(display (deep-reverse x))
It prints (((6 5) 4 3) (2 1)) as expected and uses the minimum of standard library functions: pair? to check if the tree is a cons and null? to check for an empty tree/list.
This solution for trees is a generalization of the reverse function for lists:
(define (reverse items)
(define (reverse-iter items acc)
(cond
((null? items) acc)
((not (pair? items)) items)
(else (reverse-iter (cdr items) (cons (car items) acc)))))
(reverse-iter items ()))
the difference being that deep-reverse is also applied to car items

Scheme Factorial (fact* l) Question

I'm a newbie at Scheme, so forgive the question: I have a function that calculates the factorials of a list of numbers, but it gives me a period before the last number in the results. Where am I going wrong?
code:
#lang scheme
(define fact
(lambda (n)
(cond
((= n 0) 1)
((= n 1) 1)
(else (* n (fact (- n 1)))))))
(define fact*
(lambda (l)
(cond
((null? (cdr l)) (fact (car l)))
(else
(cons (fact (car l)) (fact* (cdr l)))))))
output:
> (fact* '(3 6 7 2 4 5))
(6 720 5040 2 24 . 120)
What you have done is create an improper list. Try this:
(define fact*
(lambda (l)
(cond
((null? (cdr l)) (list (fact (car l))))
(else
(cons (fact (car l)) (fact* (cdr l)))))))
The addition of the list in the fourth line should make this work as you expect. Better might be the following:
(define fact*
(lambda (l)
(cond
(null? l) '())
(else
(cons (fact (car l)) (fact* (cdr l)))))))
This allows your fact* function to work on the empty list, as well as reducing the number of places where you make a call to fact.
The other answers have pointed out the reason why you get an improper list as a result of your fact* function. I would only like to point out that you could use the higher-order function map:
(define fact*
(lambda (l)
(map fact l))
(fact* '(3 6 7 2 4 5))
map takes a function and a list as arguments and applies the function to every element in the list, producing a new list.
Use append instead of cons. cons is used to construct pairs, which is why you have the "." that is used to separate the elements of a pair. Here's an example:
(define (factorial n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
(define (factorial-list l)
(if (null? l)
'()
(append (list (factorial (car l)))
(factorial-list (cdr l)))))

Resources