Product of squares of odd elements in list in Scheme - 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.

Related

Scheme - returning first n-elements of an array

I'm trying to write a function in Scheme that returns the first n elements in a list. I'm want to do that without loops, just with this basic structure below.
What I've tried is:
(define n-first
(lambda (lst n)
(if (or(empty? lst) (= n 0))
(list)
(append (car lst) (n-first (cdr lst) (- n 1))))))
But I'm getting an error:
append: contract violation
expected: list?
given: 'in
I've tried to debug it and it looks that the tail of the recursion crashes it, meaning, just after returning the empty list the program crashes.
When replacing "append" operator with "list" I get:
Input: (n-first '(the cat in the hat) 3)
Output:
'(the (cat (in ())))
But I want to get an appended list.
A list that looks like (1 2 3) i constructed like (1 . (2 . (3 . ()))) or if you're more familiar with cons (cons 1 (cons 2 (cons 3 '()))). Thus (list 1 2 3)) does exactly that under the hood. This is crucial information in order to be good at procedures that works on them. Notice that the first cons cannot be applied before the (cons 2 (cons 3 '())) is finished so a list is always created from end to beginning. Also a list is iterated from beginning to end.
So you want:
(define lst '(1 2 3 4 5))
(n-first lst 0) ; == '()
(n-first lst 1) ; == (cons (car lst) (n-first (- 1 1) (cdr lst)))
(n-first lst 2) ; == (cons (car lst) (n-first (- 2 1) (cdr lst)))
append works like this:
(define (append lst1 lst2)
(if (null? lst1)
lst2
(cons (car lst1)
(append (cdr lst1) lst2))))
append is O(n) time complexity so if you use that each iteration of n parts of a list then you get O(n^2). For small lists you won't notice it but even a medium sized lists of a hundred thousand elements you'll notice append uses about 50 times longer to complete than the cons one and for large lists you don't want to wait for the result since it grows exponentially.
try so
(define first-n
(lambda (l)
(lambda (n)
((lambda (s)
(s s l n (lambda (x) x)))
(lambda (s l n k)
(if (or (zero? n)
(null? l))
(k '())
(s s (cdr l) (- n 1)
(lambda (rest)
(k (cons (car l) rest))))))))))
(display ((first-n '(a b c d e f)) 4))
(display ((first-n '(a b)) 4))
In scheme you must compute mentally the types of each expression, as it does not have a type checker/ type inference included.

Mirror in scheme returns nested list w/o helper functions [duplicate]

For my programming languages class I'm supposed to write a function in Scheme to reverse a list without using the pre-made reverse function. So far what I got was
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (CONS (reverseList(CDR lst)) (CAR lst)))
))
The problem I'm having is that if I input a list, lets say (a b c) it gives me (((() . c) . b) . a).
How am I supposed to get a clean list without multiple sets of parenthesis and the .'s?
The problem with your implementation is that cons isn't receiving a list as its second parameter, so the answer you're building isn't a proper list, remember: a proper list is constructed by consing an element with a list, and the last list is empty.
One possible workaround for this is to use a helper function that builds the answer in an accumulator parameter, consing the elements in reverse - incidentally, this solution is tail recursive:
(define (reverse lst)
(reverse-helper lst '()))
(define (reverse-helper lst acc)
(if (null? lst)
acc
(reverse-helper (cdr lst) (cons (car lst) acc))))
(reverse '(1 2 3 4 5))
=> '(5 4 3 2 1)
You are half way there. The order of the elements in your result is correct, only the structure needs fixing.
What you want is to perform this transformation:
(((() . c) . b) . a) ; input
--------------------
(((() . c) . b) . a) () ; trans-
((() . c) . b) (a) ; for-
(() . c) (b a) ; mation
() (c b a) ; steps
--------------------
(c b a) ; result
This is easy to code. The car and cdr of the interim value are immediately available to us. At each step, the next interim-result is constructed by (cons (cdr interim-value) interim-result), and interim-result starts up as an empty list, because this is what we construct here - a list:
(define (transform-rev input)
(let step ( (interim-value input) ; initial set-up of
(interim-result '() ) ) ; the two loop variables
(if (null? interim-value)
interim-result ; return it in the end, or else
(step (car interim-value) ; go on with the next interim value
(cons ; and the next interim result
(... what goes here? ...)
interim-result )))))
interim-result serves as an accumulator. This is what's known as "accumulator technique". step represents a loop's step coded with "named-let" syntax.
So overall reverse is
(define (my-reverse lst)
(transform-rev
(reverseList lst)))
Can you tweak transform-rev so that it is able to accept the original list as an input, and thus skip the reverseList call? You only need to change the data-access parts, i.e. how you get the next interim value, and what you add into the interim result.
(define (my-reverse L)
(fold cons '() L)) ;;left fold
Step through the list and keep appending the car of the list to the recursive call.
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR lst))))
))
Instead of using cons, try append
(define (reverseList lst)
(if (null? lst)
'()
(append (reverseList (cdr lst)) (list (car lst)) )
)
)
a sample run would be:
1]=> (reverseList '(a b c 1 2 + -))
>>> (- + 2 1 c b a)
car will give you just one symbol but cdr a list
Always make sure that you provide append with two lists.
If you don't give two lists to the cons it will give you dotted pair (a . b) rather than a list.
See Pairs and Lists for more information.

Is this scheme code tail recursive?

EDIT: Thanks to everyone. I'm new to the language(just started using it two days ago), so that's why I'm unfamiliar with conds. I may rewrite it if I have time, but I just wanted to make sure I had the basic logic right. Thanks again!
My assignment is to make a tail-recursive function that removes the nth element from the list, 1 <= n <= listlength, with only two parameters, list x and element n. So, (remove 1 '(a b c d)) will return (b c d). I have written the following, and would like some reassurance that it is indeed tail recursive. The only thing I'm fuzzy on is if the recursive call can be nested inside an IF statement.
(define (remove n x)
; if n is 1, just return the cdr
(if (and (not (list? (car x))) (= n 1))
(cdr x)
; if the car is not a list, make it one, and call recursively
(if (not (list? (car x)))
(remove (- n 1) (cons (list (car x)) (cdr x)))
; if n !=1, insert the cadr into the list at the car.
; Else, append the list at the car with the cddr
(if (not(= n 1))
(remove (- n 1) (cons (append (car x) (list(cadr x))) (cddr x)))
(append (car x) (cddr x))))))
Yes, the procedure is tail-recursive, meaning: wherever a recursive call is performed, it's the last thing that happens in that particular branch of execution, with nothing more to do after the recursion returns - hence, we say that the recursive call is in tail position.
This can be clearly seen if we rewrite the procedure using cond instead of nested ifs, here you'll see that every branch of execution leads to either a base case or a recursive case, and all recursive calls are in tail position:
(define (remove n x)
; base case #1
(cond ((and (not (list? (car x))) (= n 1))
; return from base case, it's not recursive
(cdr x))
; recursive case #1
((not (list? (car x)))
; recursive call is in tail position
(remove (- n 1) (cons (list (car x)) (cdr x))))
; recursive case #2
((not (= n 1))
; recursive call is in tail position
(remove (- n 1) (cons (append (car x) (list(cadr x))) (cddr x))))
; base case #2
(else
; return from base case, it's not recursive
(append (car x) (cddr x)))))
For a more technical explanation of why the consequent/alternative parts of an if special form can be considered tail-recursive, take a look at section 3.5 of the current draft of the Revised^7 Report on the Algorithmic Language Scheme - the language specification, here's a link to the pdf file (in essence the same considerations apply to R5RS, it's just that they're explained in more detail in R7RS). In particular:
If one of the following expressions is in a tail context, then the subexpressions shown as ⟨tail expression⟩ are in a tail context
...
(if ⟨expression⟩ ⟨tail expression⟩ ⟨tail expression⟩)
(if ⟨expression⟩ ⟨tail expression⟩)
Here is the Scheme specification on the tail recursion position for syntactic forms:

Simple Scheme, squaring all elements in a list

Okay, I'm new to Scheme and I thought I understood it, but got confused on this problem. I want to square all the elements of a list. So, (mapsq '(1 2 3)) returns (list 1 4 9).
my code:
(define mapsq
(lambda (ls)
(cond ((null? ls) 0)
(else (cons (car ls) (car ls))
(mapsq (cdr ls)))))))
In a practical (non-academic) context, this problem can be easily solved by using the map procedure:
(define mapsq
(lambda (ls)
(map (lambda (x) (* x x))
ls)))
Of course, if this is homework and you need to implement the solution from scratch, I shouldn't spoon-feed the answer. Better find out the solution by yourself, filling-in the blanks:
(define mapsq
(lambda (ls)
(cond ((null? ls) ; If the list is empty
<???>) ; ... then return the empty list.
(else ; Otherwise
(cons (* <???> <???>) ; ... square the first element in the list
(mapsq <???>)))))) ; ... and advance the recursion.
There are two problems in your solution: first, the base case should not return 0 - if we're building a list as an answer, then you must return the empty list. Second, in the recursive step you aren't actually squaring the current element in the list - to do that just multiply it by itself with the * operator.
You could write it like this:
(define (mapsq xs)
(define (square x) (* x x))
(map square xs))
Or this:
(define (mapsq xs)
(map (lambda (x) (* x x)) xs))
Or maybe like this:
(define (mapsq xs)
(let loop ((xs xs) (sqs '()))
(if (null? xs)
(reverse sqs)
(loop (cdr xs) (cons (* (car xs) (car xs)) sqs)))))
Or even like this:
(define (mapsq xs)
(if (null? xs)
'()
(cons (* (car xs) (car xs)) (mapsq (cdr xs)))))
My preference would be the first option. The second option is shorter, but the auxiliary function makes the first option easier to read. I would probably not use either the third or fourth options.
By the way, the solution by laser_wizard doesn't work, either.
I notice that you're new here. If you like an answer, click the up arrow next to the answer so the person who gave the answer gets points; this mark also lets the community of readers know that there is something of value in the answer. Once you have an answer that you are confident is correct, click the check mark next to the answer; that also gives points to the person that gave the answer, and more importantly lets other readers know that you believe this answer most correctly addresses your question.
(define (mapsq xs)
(map * xs xs))
> (mapsq '(1 2 3 4 5))
'(1 4 9 16 25)

Finding the overall average of nested lists in Scheme?

Hey guys, I'm using MIT Scheme and trying to write a procedure to find the average of all the numbers in a bunch of nested lists, for example:
(average-lists (list 1 2 (list 3 (list 4 5)) 6)))
Should return 3.5. I've played with the following code for days, and right now I've got it returning the sum, but not the average. Also, it is important that the values of the inner-most lists are calculated first, so no extracting all values and simply averaging them.
Here's what I have so far:
(define (average-lists data)
(if (null? data)
0.0
(if (list? (car data))
(+ (average-lists (car data)) (average-lists (cdr data)))
(+ (car data) (average-lists (cdr data))))))
I've tried this approach, as well as trying to use map to map a lambda function to it recursively, and a few others, but I just can't find one. I think I'm making thing harder than it should be.
I wrote the following in an effort to pursue some other paths as well, which you may find useful:
(define (list-num? x) ;Checks to see if list only contains numbers
(= (length (filter number? x)) (length x)))
(define (list-avg x) ;Returns the average of a list of numbers
(/ (accumulate + 0 x) (length x)))
Your help is really appreciated! This problem has been a nightmare for me. :)
Unless the parameters require otherwise, you'll want to define a helper procedure that can calculate both the sum and the count of how many items are in each list. Once you can average a single list, it's easy to adapt it to nested lists by checking to see if the car is a list.
This method will get you the average in one pass over the list, rather than the two or more passes that solutions that flatten the list or do the count and the sums in two separate passes. You would have to get the sum and counts separately from the sublists to get the overall average, though (re. zinglon's comment below).
Edit:
One way to get both the sum and the count back is to pass it back in a pair:
(define sum-and-count ; returns (sum . count)
(lambda (ls)
(if (null? ls)
(cons 0 0)
(let ((r (sum-and-count (cdr ls))))
(cons (+ (car ls) (car r))
(add1 (cdr r)))))))
That procedure gets the sum and number of elements of a list. Do what you did to your own average-lists to it to get it to examine deeply-nested lists. Then you can get the average by doing (/ (car result) (cdr result)).
Or, you can write separate deep-sum and deep-count procedures, and then do (/ (deep-sum ls) (deep-count ls)), but that requires two passes over the list.
(define (flatten mylist)
(cond ((null? mylist) '())
((list? (car mylist)) (append (flatten (car mylist)) (flatten (cdr mylist))))
(else (cons (car mylist) (flatten (cdr mylist))))))
(define (myavg mylist)
(let ((flatlist (flatten mylist)))
(/ (apply + flatlist) (length flatlist))))
The first function flattens the list. That is, it converts '(1 2 (3 (4 5)) 6) to '(1 2 3 4 5 6)
Then its just a matter of applying + to the flat list and doing the average.
Reference for the first function:
http://www.dreamincode.net/code/snippet3229.htm

Resources