I want to create a function in Scheme that takes a list of numbers and displays the number that are less than the average. The answer should be 3 but returns 2. I believe it is not reading "15." What am I doing wrong?
(define x (list 10 60 3 55 15 45 40))
(display "The list: ")
(let ((average (/ (apply + (cdr x)) (car x))))
(length (filter (lambda (x) (< x average)) (cdr x))))
Output:
The list:
(10 60 3 55 15 45 40)
The average:
32.57
Number of values less than average:
2
Sure, let's do this step by step!
First off, let's define a function to get us the average of a list. We'll call this function mean.
(define (mean lst)
(/ (apply + lst) (length lst)))
We get the average by adding all the numbers together and dividing that sum by how many numbers were in the list (that is to say, the length of the list). There are Racket libraries that could provide us with this function, such as the Statistics Functions library from the math-lib package. But we'll do it ourselves since it's simple enough.
Next we have the meat of our algorithm, where we define a function that takes a list, gets the average, and filters out every element less than the average.
(define (less-than-average lst)
(filter (λ (x) (< x (mean lst))) lst))
Looks pretty similar to your code, right? Let's see if it works:
(less-than-average (list 10 60 3 55 15 45 40))
I ran this in DrRacket and it gave me 10 3 15, which is the correct answer. So why did this work, when you (very similar) code does not?
The problem with your code is that the value you are storing in average is incorrect. Viz,
(define x (list 10 60 3 55 15 45 40))
(let ((average (/ (apply + (cdr x)) (car x))))
average)
evaluates to 21.8. As you state, the correct average is 32.57. Your current technique for computing this average is to add up everything in the list after the first element (that's what (apply + (cdr x)) does) then dividing that sum by the first element. This will not give you the mean value of the list. What you ought to be doing is summing up the entire list (via (apply + x)), then dividing that by how many numbers were in the list (ie (length x)).
This answer tries to pay attention to performance. The other answer by Alex has a mean function which walks the list twice: once to add up the elements, and once to compute the length. It then calls this function for every element of the list when filtering it, resulting a function which takes time quadratic in the length of the list being averaged. This is not a problem for small lists.
Here is a mean function which walks the list once.
(define (list-average l)
(let average-loop ([tail l] [sum 0] [len 0])
(if (null? tail)
(/ sum len)
(average-loop (rest tail) (+ sum (first tail)) (+ len 1)))))
This is a little better than one which walks it twice, but the difference is probably not significant (naively it might be twice as fast, in practice probably less).
Here is a filtering function which is careful to call the mean function only once. This is a whole complexity class faster than one which calls it for every element, resulting in a function which takes time proportional to the length of the list, not the length of the list squared.
(define (<=-average l)
(define average (list-average l))
(filter (λ (e) (<= e average)) l))
I will not comment too much, I have just written such a function here and you can study it:
(define less-than-average
(lambda (list return)
((lambda (self) (self self list 0 0 return))
(lambda ( self list acc n col)
(if (null? list)
(col (/ acc n) list)
(let ((a (car list)))
(self self
(cdr list)
(+ acc a)
(+ n 1)
(lambda (average l*) ; when the average is known,
(if (< a average)
(col average (cons a l*))
(col average l* ))))))))))
1 ]=> (less-than-average (list 10 60 3 55 15 45 40)
(lambda (avg l*)
(newline)
(display avg)
(newline)
(display l*)
(newline)) )
228/7
(10 3 15)
Related
Im trying to learn scheme and Im having trouble with the arithmetic in the Scheme syntax.
Would anyone be able to write out a function in Scheme that represents the Geometric Series?
You have expt, which is Scheme power procedure. (expt 2 8) ; ==> 256 and you have * that does multiplication. eg. (* 2 3) ; ==> 6. From that you should be able to make a procedure that takes a n and produce the nth number in a specific geometric series.
You can also produce a list with the n first if you instead of using expt just muliply in a named let, basically doing the expt one step at a time and accumulate the values in a list. Here is an example of a procedure that makes a list of numbers:
(define (range from to)
(let loop ((n to) (acc '())
(if (< n from)
acc
(loop (- 1 n) (cons n acc)))))
(range 3 10) ; ==> (3 4 5 6 7 8 9 10)
Notice I'm doing them in reverse. If I cannot do it in reverse I would in the base case do (reverse acc) to get the right order as lists are always made from end to beginning. Good luck with your series.
range behaves exactly like Python's range.
(define (range from (below '()) (step 1) (acc '()))
(cond ((null? below) (range 0 from step))
((> (+ from step) below) (reverse acc))
(else (range (+ from step) below step (cons from acc)))))
Python's range can take only one argument (the upper limit).
If you take from and below as required arguments, the definition is shorter:
(define (range from below (step 1) (acc '()))
(cond ((> (+ from step) below) (reverse acc))
(else (range (+ from step) below step (cons from acc)))))
Here is an answer, in Racket, that you probably cannot submit as homework.
(define/contract (geometric-series x n)
;; Return a list of x^k for k from 0 to n (inclusive).
;; This will be questionable if x is not exact.
(-> number? natural-number/c (listof number?))
(let gsl ((m n)
(c (expt x n))
(a '()))
(if (zero? m)
(cons 1 a)
(gsl (- m 1)
(/ c x)
(cons c a)))))
How to I create a function called numDivisors. The function is defined as (numDivisors n listOfNums) and it counts the number of integers in the list that divide n without any remainder.
Example of the function call
(numDivisors 10 '(1 20 30 2 5 40 10 60))
returns 4 from (1 2 5 10)
Current code:
(define numDivisors
(lambda (x lst)
(cond
((null? lst) 0)
((eq? (remainder 10 (car lst)) 0) (+ 1 (numDivisors x (cdr lst))))
)
)
)
Your solution is close.
First you need to change eq? to =, which tests equality of numbers, and change (remainder 10 ...) to (remainder x ...), so that 10 is no longer hard-wired into your solution.
Second, you need to add a third clause to your cond to handle the case where the remainder is not 0. I'll let you think about that; given what you have done so far, I am confident you will figure it out.
And you should stack those three closing parentheses at the end of the last line of code instead of placing them on lines by themselves.
An experienced Scheme programmer would probably write:
(define (numDivisors n xs)
(define (divides? d n) (zero? (modulo n d)))
(length (filter (lambda (d) (divides? d n)) xs)))
If that makes no sense at all, you should probably wait a few weeks. I'm sure your instructor will soon have you writing code like that.
So I have code that should find the average of a list but I see no printed value in console
#lang racket
(define x (list '10 '60 '3 '55 '15 '45 '40))
(define (average x)
(/ (sum x) (length x)))
(display average (current-output-port))
(define (sum)
(if (null? x)
0
(+ (car x) (sum (cdr x)))))
it simply displays
#<procedure:average>
Your code has following problems:
sum was used before it was defined.
sum did not take a parameter.
average function was not evaluated in display.
I have used exact->inexact because that's what I think your intention is.
Following works.
(define x (list 10 60 3 55 15 45 40))
(define (sum x)
(if (null? x)
0
(+ (car x) (sum (cdr x)))))
(define (average x)
(/ (sum x) (length x)))
(display (exact->inexact (average x)) (current-output-port))
(define (average l)
(/ (foldr (lambda (x y) (+ x y)) 0 l)
(length l)))
sum and length are each O(n) resulting in a O(2n) process for average. Below we show how continuation passing style can be used to make average a O(n) process as well.
(define (average xs (return /))
(if (empty? xs)
(return 0 0)
(average (cdr xs)
(lambda (sum len)
(return (+ sum (car xs))
(+ len 1))))))
(printf "~a~n" (average '(10 60 3 55 15 45 40)))
;; 228/7
Using exact->inexact in average means only an inexact result can be returned. Making additional computations with inexact numbers leads to additional inexactitude. You might think that inexact->exact could reverse any of this however it can only make an approximation.
(average '(10 60 3 55 15 45 40)
;; 32 4/7
(inexact->exact (exact->inexact (average '(10 60 3 55 15 45 40))))
;; 32 40210710958665/70368744177664
For this reason it generally make sense only to convert an exact number to an inexact one just before it is displayed.
(printf "~a\n" (exact->inexact (average '(10 60 3 55 15 45 40))))
;; 32.57142857142857
Our average procedure also throws an error when an empty list is given.
(average '())
;; error /: division by zero
Alternatively, we could write average using a named let expression. Also O(n).
(define (average xs)
(let loop ((xs xs)
(sum 0)
(len 0))
(if (empty? xs)
(/ sum len)
(loop (cdr xs)
(+ sum (car xs))
(+ len 1)))))
(average '(10 60 3 55 15 45 40)
;; 32 4/7
I might be using a different version of scheme; https://scheme.cs61a.org/ is the compiler I use. It worked for me when I included the a parameter for the function sum like this:
(define (sum x)
(if (null? x)
0
(+ (car x) (sum (cdr x)))))
Hope this helps!
I'm trying to print the first 2 numbers in a list coded in Scheme. I'm having a bit of trouble doing this. I get an error when I run the procedure. Any suggestions on how I can get this to work
(define (print-two-nums n nums)
( list-ref nums(+ (cdr nums) n)))
( print-two-nums 2'(5 5 4 4))
It looks like you were wavering between the ideas of "print two numbers" and "print n numbers." If you really want just the two first numbers of a list, you can write:
(define (print-two-nums nums)
(print (list (car nums) (cadr nums))))
But for the more general first n numbers, you can use:
(define (print-n-nums n nums)
(print (take nums n)))
To print the first n numbers, you could use this simple procedure
(define (print-n-nums L n) (cond
((or (= 0 n) (null? L)) '())
(else (cons (car L) (print-n-nums (cdr L) (- n 1))))))
(print-n-nums (list 1 2 3) 2)
;Output: (1 2)
You could further abstract the cons operation and define print-n-nums as a higher order procedure to carry out the desired operation. For example, if we wanted to add the first n numbers of a list, we could define the following procedure. Here OPERATION is a function that we pass to the list-operator function. Thus, here we want to perform the + operation. In the case above, we want to perform the cons operation. The initial parameter is just how we want to handle the edge case.
(define (list-operator L n OPERATION initial) (cond
((or (= 0 n) (null? L)) initial)
(else (OPERATION (car L) (list-operator (cdr L) (- n 1) OPERATION initial)))))
(list-operator (list 1 2 3) 2 + 0)
;Output: 3
Now, if you wanted the product of the first 2 numbers, you would just do
(list-operator (list 1 2 3) 2 * 1)
(define (checksum-2 ls)
(if (null? ls)
0
(let ([n 0])
(+ (+ n 1))(* n (car ls))(checksum-2 (cdr ls)))))
Ok, I have this code, its suppose to, if I wrote it right, the number (n) should increase by one every time it goes through the list, so n (in reality) should be like 1 2 3 4, but I want n to be multiplied by the car of the list.
Everything loads, but when the answer is returned I get 0.
Thanks!
If you format your code differently, you might have an easier time seeing what is going on:
(define (checksum-2 ls)
(if (null? ls)
0
(let ([n 0])
(+ (+ n 1))
(* n (car ls))
(checksum-2 (cdr ls)))))
Inside the let form, the expressions are evaluated in sequence but you're not using the results for any of them (except the last one). The results of the addition and multiplication are simply discarded.
What you need to do in this case is define a new helper function that uses an accumulator and performs the recursive call. I'm going to guess this is homework or a learning exercise, so I'm not going to give away the complete answer.
UPDATE: As a demonstration of the sort of thing you might need to do, here is a similar function in Scheme to sum the integers from 1 to n:
(define (sum n)
(define (sum-helper n a)
(if (<= n 0)
a
(sum-helper (- n 1) (+ a n))))
(sum-helper n 0))
You should be able to use a similar framework to implement your checksum-2 function.