Compare a list of numbers with a variable - scheme

The function below is intended to compare every number in a list (2nd parameter) with the first parameter and for every num in the list that is greater than the second param, count it and return the total amount of elements in the list that were greater than the 'threshold'
The code I have doesn't run because I have tried to learn how recursion in Dr. Racket works, but I can't seem to understand. I am just frustrated so just know the code below isn't supposed to be close to working; functional programming isn't my thing, haha.
(define (comp-list threshold list-nums)
(cond [(empty? list-nums) 0]
[(cons? list-nums) (let {[my-var 0]}
(map (if (> threshold (first list-nums))
threshold 2) list-nums ))]))

The following doesn't use lambda of foldl (and is recursive) - can you understand how it works?
(define (comp-list threshold list-nums)
(cond [(empty? list-nums) 0]
[else
(cond [(> (car list-nums) threshold) (+ 1 (comp-list threshold (cdr list-nums)))]
[else (comp-list threshold (cdr list-nums))])]))
Tested:
> (comp-list 1 '(1 1 2 2 3 3))
4
> (comp-list 2 '(1 1 2 2 3 3))
2
> (comp-list 3 '(1 1 2 2 3 3))
0

map takes a procedure as first argument and applied that to every element in the given list(s). Since you are counting something making a list would be wrong.
foldl takes a procedure as first argument, the starting value as second and one or more lists. It applies the procedure with the elements and the starting value (or the intermediate value) and the procedure get to decide the next intermediate value. eg. you can use it to count a list:
(define (my-length lst)
(foldl (lambda (x acc) (+ acc 1))
0
lst))
(my-length '(a b c)) ; ==> 3
You can easily change this to only count when x is greater than some threshold, just evaluate to acc to keep it unchanged when you are not increasing the value.
UPDATE
A recursive solution of my-length:
(define (my-length lst)
;; auxiliary procedure since we need
;; an extra argument for counting
(define (aux lst count)
(if (null? lst)
count
(aux (cdr lst)
(+ count 1))))
;; call auxiliary procedure
(aux lst 0))
The same alteration to the procedure to foldl have to be done with this to only count in some circumstances.

(define (comp-list threshold list-nums)
(cond
[(empty? list-nums) ; there are 0 elements over the threshold in an empty list
0]
[(cons? list-nums) ; in a constructed list, we look at the the first number
(cond
[(< threshold (first list-nums))
(+ 1 ; the first number is over
(comp-list threshold (rest list-nums))] ; add the rest
[else
(comp-list threshold (rest list-nums))])])) ; the first number is lower

A simple functional start
#lang racket
(define (comp-list threshold list-nums)
(define (my-filter-function num)
(< num threshold))
(length (filter my-filter-function list-nums)))
Replacing define with lambda
#lang racket
(define (comp-list threshold list-nums)
(length (filter (lambda (num) (< num threshold))
list-nums)))
Racket's implementation of filter
In DrRacket highlighting the name of a procedure and right clicking and selecting "jump to definition in other file" will allow review of the source code. The source code for filter is instructive:
(define (filter f list)
(unless (and (procedure? f)
(procedure-arity-includes? f 1))
(raise-argument-error 'filter "(any/c . -> . any/c)" f))
(unless (list? list)
(raise-argument-error 'filter "list?" list))
;; accumulating the result and reversing it is currently slightly
;; faster than a plain loop
(let loop ([l list] [result null])
(if (null? l)
(reverse result)
(loop (cdr l) (if (f (car l)) (cons (car l) result) result)))))

Related

Improving an iterative function in scheme

I often struggle writing iterative functions in scheme: it makes writing recursive procedures much simpler. Here is an example of trying to square items in a list using an iterative procedure:
(define square (lambda (x) (* x x)))
(define (square-list items)
(define result nil) ; set result
(define (iter items-remaining)
(if (null? items-remaining)
result
(set! result (cons (car items-remaining) (iter (cdr items-remaining))))))
(iter items))
(square-list '(1 2 3 4 5))
; (4 9 16 25)
My main question about this is:
Is there a way to do this procedure without having to first define the result before the inner procedure? I was trying to make the iterative procedure have the function prototype of define (iter items-remaining answer) but was having a hard time implementing it that way.
And if not, why isn't that possible?
The posted code does not work; but even when fixed up so that it does work, this would not be an idiomatic Scheme solution.
To make the posted code work:
nil must be replaced with '(), since Scheme does not represent the empty list with nil
square must be called on the car of items-remaining
set! should modify result by adding squared numbers to it, not by trying to add the result of a recursive call. This won't work at all here because set! returns unspecified values; but even if it did work, this would not be tail-recursive (i.e., this would not be an iterative process)
The value of result must be returned, and it will have to be reversed first since result is really an accumulator
Here is a fixed-up version:
(define (square-list-0 items)
(define result '()) ; set result
(define (iter items-remaining)
(cond ((null? items-remaining)
result)
(else
(set! result (cons (square (car items-remaining))
result))
(iter (cdr items-remaining)))))
(iter items)
(reverse result))
A better solution would not use mutation, and would not need (define result '()):
(define (square-list-1 xs)
(define (iter xs acc)
(if (null? xs)
(reverse acc)
(iter (cdr xs) (cons (square (car xs)) acc))))
(iter xs '()))
Here an accumulator, acc, is added to the lambda list for the iter procedure. As results are calculated, they are consed onto acc, which means that at the end of this process the first number in acc is based on the last number in xs. So, the accumulator is reversed before it is returned.
Another way to do this, and probably a more idiomatic solution, is to use a named let:
(define (square-list-2 xs)
(let iter ((xs xs)
(acc '()))
(if (null? xs)
(reverse acc)
(iter (cdr xs) (cons (square (car xs)) acc)))))
This is a bit more concise, and it lets you bind arguments to their parameters right at the beginning of the definition of the iter procedure.
All three of the above solutions define iterative processes, and all three give the same results:
> (square-list-0 '(1 2 3 4 5))
(1 4 9 16 25)
> (square-list-1 '(1 2 3 4 5))
(1 4 9 16 25)
> (square-list-2 '(1 2 3 4 5))
(1 4 9 16 25)
Of course, you could just use map:
> (map square '(1 2 3 4 5))
(1 4 9 16 25)

How do you obtain the largest n elements of a list using Scheme?

I'm stuck on a homework question and could use any hints or suggestions. I need to find the n largest numbers in a list using Scheme. I am trying to do this by creating helper functions that are called by the main function. So far I have this:
(define (get_max_value L)
(if (null? L)
'()
(apply max L)
)
(define (biggest_nums L n)
(if (null? n)
'()
(cons (get_max_value L) (biggest_nums L (- n 1)))
)
)
When I type (biggest_num '(3 1 4 2 5) 3) at the command prompt drRacket just hangs and doesn't even return an error message. Where am I going wrong?
The simplest solution is to first sort the numbers in ascending order and then take the n first. This translates quite literally in Racket code:
(define (biggest_nums L n)
(take (sort L >) n))
It works as expected:
(biggest_nums '(3 1 4 2 5) 3)
=> '(5 4 3)
Two mains problems with your code:
L always stays the same. L doesn't decrease in size when you make the recursive call, so the max will always be the same number in every recursive call.
You don't ever check n to make sure it contains the correct amount of numbers before returning the answer.
To solve these two problems in the most trivial way possible, you can put a (< n 1) condition in the if, and use something like (cdr L) to make L decrease in size in each recursive call by removing an element each time.
(define (biggest-nums n L)
(if (or (empty? L)
(< n 1))
'()
(cons (apply max L) (biggest-nums (- n 1) (cdr L)))))
So when we run it:
> (biggest-nums 3 '(1 59 2 10 33 4 5))
What should the output be?
'(59 33 10)
What is the actual output?
'(59 59 33)
OK, so we got your code running, but there are still some issues with it. Do you know why that's happening? Can you step through the code to figure out what you could do to fix it?
Just sort the list and then return the first n elements.
However, if the list is very long and n is not very large, then you probably don't want to sort the whole list first. In that case, I would suggest something like this:
(define insert-sorted
(lambda (item lst)
(cond ((null? lst)
(list item))
((<= item (car lst))
(cons item lst))
(else
(cons (car lst) (insert-sorted item (cdr lst)))))))
(define largest-n
(lambda (count lst)
(if (<= (length lst) count)
lst
(let loop ((todo (cdr lst))
(result (list (car lst))))
(if (null? todo)
result
(let* ((item (car todo))
(new-result
(if (< (car result) item)
(let ((new-result (insert-sorted item result)))
(if (< count (length new-result))
(cdr new-result)
new-result))
result)))
(loop (cdr todo)
new-result)))))))

Product of squares of odd elements in list in Scheme

I wanted to write a code in Scheme that writes the square odd elements in list.For example (list 1 2 3 4 5) for this list it should write 225.For this purpose i write this code:
(define (square x)(* x x))
(define (product-of-square-of-odd-elements sequence)
(cond[(odd? (car sequence)) '() (product-of-square-of-odd-elements (cdr sequence))]
[else ((square (car sequence)) (product-of-square-of-odd-elements (cdr sequence)))]))
For run i write this (product-of-square-of-odd-elements (list 1 2 3 4 5))
and i get error like this:
car: contract violation
expected: pair?
given: '()
What should i do to make this code to run properly? Thank you for your answers.
First of all, you need to do proper formatting:
(define (square x) (* x x))
(define (product-of-square-of-odd-elements sequence)
(cond
[(odd? (car sequence))
'() (product-of-square-of-odd-elements (cdr sequence))]
[else
((square (car sequence)) (product-of-square-of-odd-elements (cdr sequence)))]))
Now there are multiple issues with your code:
You are trying to work recursively on a sequence, but you are missing a termination case: What happens when you pass '() - the empty sequence? This is the source of your error: You cannot access the first element of an empty sequence.
You need to build up your result somehow: Currently you're sending a '() into nirvana in the first branch of your cond and put a value into function call position in the second.
So let's start from scratch:
You process a sequence recursively, so you need to handle two cases:
(define (fn seq)
(if (null? seq)
;; termination case
;; recursive case
))
Let's take the recursive case first: You need to compute the square and multiply it with the rest of the squares (that you'll compute next).
(* (if (odd? (car seq)
(square (car seq))
1)
(fn (cdr seq)))
In the termination case you have no value to square. So you just use the unit value of multiplication: 1
This is not a good solution, as you can transform it into a tail recursive form and use higher order functions to abstract the recursion altogether. But I think that's enough for a start.
With transducers:
(define prod-square-odds
(let ((prod-square-odds
((compose (filtering odd?)
(mapping square)) *)))
(lambda (lst)
(foldl prod-square-odds 1 lst))))
(prod-square-odds '(1 2 3 4 5))
; ==> 225
It uses reusable transducers:
(define (mapping procedure)
(lambda (kons)
(lambda (e acc)
(kons (procedure e) acc))))
(define (filtering predicate?)
(lambda (kons)
(lambda (e acc)
(if (predicate? e)
(kons e acc)
acc))))
You can decompose the problem into, for example:
Skip the even elements
Square each element
take the product of the elements
With this, an implementation is naturally expressed using simpler functions (most of which exist in Scheme) as:
(define product-of-square-of-odd-elements (l)
(reduce * 1 (map square (skip-every-n 1 l))))
and then you implement a helper function or two, like skip-every-n.

Scheme return a list with first half of its elements

Write a procedure (first-half lst) that returns a list with the first half of its elements. If the length of the given list is odd, the returned list should have (length - 1) / 2 elements.
I am given these program as a example and as I am new to Scheme I need your help in solving this problem.
(define list-head
(lambda (lst k)
(if (= k 0)
'()
(cons (car lst)(list-head (cdr lst)(- k 1)))))))
(list-head '(0 1 2 3 4) 3)
; list the first 3 element in the list (list 0 1 2)
Also the expected output for the program I want is :
(first-half '(43 23 14 5 9 57 0 125))
(43 23 14 5)
This is pretty simple to implement in terms of existing procedures, check your interpreter's documentation for the availability of the take procedure:
(define (first-half lst)
(take lst (quotient (length lst) 2)))
Apart from that, the code provided in the question is basically reinventing take, and it looks correct. The only detail left to implement would be, how to obtain the half of the lists' length? same as above, just use the quotient procedure:
(define (first-half lst)
(list-head lst (quotient (length lst) 2)))
It looks like you are learning about recursion? One recursive approach is to walk the list with a 'slow' and 'fast' pointer; when the fast pointer reaches the end you are done; use the slow pointer to grow the result. Like this:
(define (half list)
(let halving ((rslt '()) (slow list) (fast list))
(if (or (null? fast) (null? (cdr fast)))
(reverse rslt)
(halving (cons (car slow) rslt)
(cdr slow)
(cdr (cdr fast))))))
Another way to approach it is to have a function that divides the list at a specific index, and then a wrapper to calculate floor(length/2):
(define (cleave_at n a)
(cond
((null? a) '())
((zero? n) (list '() a))
(#t
((lambda (x)
(cons (cons (car a) (car x)) (cdr x)))
(cleave_at (- n 1) (cdr a))))))
(define (first-half a)
(car (cleave_at (floor (/ (length a) 2)) a)))

How do I find the location of an element in a list?

I am a beginner in scheme and I want to know how you find the location of an element in a list. For example, in this given list,
(list 1 2 13)
I found the maximum using accumulative recursion, but I need to also find the location of the maximum, so if the function is:
(max-with-location (list 1 2 13)), I need to get: (list 13 (list 3))
Please help me out.
This sounds like homework, and if this is the case then any of these solutions won't help. What you're likely expected to do is to revise the code that you wrote to find the maximum: instead of a single accumulator input to the loop, add one more for the position of the maximum-so-far. That will not be too hard given that you already have implemented max.
I don't use Scheme, but in CL it's (position 13 (list 1 2 13))
Maybe it's the same...
So for your code, you'd want something like this:
(list (max (list 1 2 13)) (position (max (list 1 2 13)))
which would return (13 2)
edit: max is supposed to be your max algorithm, though I imagine there might already be a function for this
double edit: if that still doesn't work, you could always use a counter that increments each time through your recursive function, then return that as well...
first you have to determinate the max number:
(define max_list1
(lambda (l)
(cond
((empty? (rest l)) l)
(else (max_aux_list (first l) (rest l))))))
(define (max_aux_list n lista)
(cond
((empty? lista) n)
((> n (first lista)) (max_aux_list n (rest lista)))
(else (max_aux_list (first lista) (rest lista)))))
then you have to count the position number of an element.
(define find_in_position
(lambda (n lista)
(cond
((empty? lista) 0)
((= n (first lista)) 1)
(else (+ 1 (find_in_position n (rest lista)))))))
finally, list both resoults.
(define (the_max_in_position lista)
(list (max_list1 lista)
(list (find_in_position (max_list1 lista) lista))))
This should do the trick:
(define (find-position list element #!optional (pred eq?))
(letrec ((loop (lambda (list count)
(if (null? list) #f ;No such element found
(if (pred (car list) element) count
(loop (cdr list) (+ count 1)))))))
(loop list 0)))
Then:
(find-position (list 1 3 13) 13)
>>> 2
Use list-ref like so:
(define tlist '(a b c d))
(list-ref tlist 2)
>> c

Resources