Im trying to get the sum of every even element in scheme - scheme

This is what i have so far, kindly assist on where im going wrong
(define helper
(lambda (lis)
(cond
((null? lis) 0)
((null? (cdr lis)) 0)
(else (+ (helper (cdr (cdr lis))))))))
(define (sumEven lis)
(display (helper lis)))
This is how i call the function:
(define (sumEven lis)
(display (helper lis)))

You forgot to add the element:
(else (+ (car (cdr lis)) (helper (cdr (cdr lis))))))))

Related

How can i get the positive even elements in scheme

I am trying to get all the even and positive elements in scheme
I have the following code
(define (getVals lis)
(cond
((null? lis) lis)
(((> (car lis) 0) (even? (car lis)))
(cons (getVals (cdr lis))))
)
)
To check my code im using
getVals '(2 -2 4 6 5))
Which should output a new list with positive and even numbers (2 4 6)
Thank you
The simplest way would be to use built-in procedures:
(define (getVals lis)
(filter (lambda (x) (and (even? x) (positive? x)))
lis))
If you want to implement it from scratch, you need to fix your code:
It's missing the case where the current element does not meet the conditions (the else case).
It's missing one parameter when calling cons.
The condition is missing an and.
This is what I mean:
(define (getVals lis)
(cond
((null? lis) lis)
((and (even? (car lis)) (positive? (car lis)))
(cons (car lis) (getVals (cdr lis))))
(else (getVals (cdr lis)))))
Either way, it works as expected:
(getVals '(2 -2 4 6 5))
=> '(2 4 6)
And just to add to #OscarLopez's answer - if you have a second look you will see, that getVals is just the specific case of `filter.
(define (getVals lis)
(cond
((null? lis) lis)
((and (even? (car lis)) (positive? (car lis)))
(cons (car lis) (getVals (cdr lis))))
(else (getVals (cdr lis)))))
Versus:
(define (filter func lst)
(cond
((null? lis) lst)
((func (car lst))
(cons (car lst) (filter func (cdr lst))))
(else (filter func (cdr lst)))))
With filter func as getVales, and
with func as:
(lambda (x) (and (even? x) (positive? x)))
getVals is just a special case of filter:
(define (getVals lst)
(filter (lambda (x) (and (even? x) (positive? x))) lst))
But you should follow the style guide for Lisp languages -
don't use camelCase for function names but prefer the lisp-typic form get-vals.

Racket Append Undesired Reversal of List

I wrote a small function that takes a list and returns a list composed of only positive numbers. This all works fine, but for some reason, it is reversing the order. More information below on that. Could someone please tell me if this is normal, or if I miss-wrote something? Thank you in advance.
(define (positive-nums-only lst)
(if (empty? lst)
'()
(append (positive-nums-only (cdr lst))
(if (>= (car lst) 0)
(list (car lst))
'()))))
(positive-nums-only '(1 2 -4 90 -4))
The above test case returns '(90 2 1)
You did not make a mistake, the program is making what you asked.
See, the program finishes the recursion calls first, before going into resolving the if statement. This causes the (list ... ) to start listing from the last element that is positive, in this example it will be 90.
Changing the code order will produce the result you want.
(define (positive-nums-only lst)
(if (empty? lst) '()
(append (if (>= (car lst) 0 )
(list (car lst))
'())
(positive-nums-only (cdr lst)))
)
)
On the other hand, this kind of recursion could be expensive to the computer. I'd use tail recursion, like this:
(define positive-nums-only-tail
(λ (lst r)
(cond ((empty? lst) (reverse r))
((positive? (car lst))
(positive-nums-only-tail (cdr lst)
(cons (car lst) r)))
(else (positive-nums-only-tail (cdr lst) r))
)
)
)
Have you tried reversing the append?
(define (positive-nums-only lst)
(if (empty? lst)
'()
(append (if (>= (car lst) 0) (list (car lst)) '())
(positive-nums-only (cdr lst)))))
Personally I find it more natural to write it like this:
(define (positive-nums-only lst)
(if (empty? lst)
'()
(let ((rest (positive-nums-only (cdr lst))))
(if (>= (car lst) 0)
(cons (car lst) rest)
rest))))

Combining count and flatten functions in scheme

So i have these two functions that work fine alone. I am trying to write one function to accomplish both but i keep getting a car error. Any guidance on the best way to solve this?
(define (countNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ 1 (countNumbers (cdr lst))))
(else (countNumbers (cdr lst)))))
(define (flatten x)
(cond ((null? x) '())
((pair? x) (append (flatten (car x)) (flatten (cdr x))))
(else (list x))))
I tried something like this im rather new to functional programming in general so im still trying to wrap my mind around it it says the problem is after number?(car lst)
(define (flatten lst)
(cond ((null? lst) '())
((pair? lst) (append (flatten (car lst)) (flatten (cdr lst))))
(else (list(cond
((null? lst) 0)
((number? (car lst))(+ 1 (flatten (cdr lst))))
(else (flatten (cdr lst))))))))
As I mentioned in my comment, I don't think it's a good idea to stick everything in a single function. Anyway, you were kinda on the right track, but we have to remember that if we're going to return a number as the final result, then our base case should reflect this and also return a number (not an empty list), and the combining step should add numbers, not append them. This is what I mean:
(define (count-flatten lst)
(cond ((null? lst) 0)
((pair? lst)
(+ (count-flatten (car lst))
(count-flatten (cdr lst))))
((number? lst) 1)
(else 0)))
But I'd rather do this:
(define (count-flatten lst)
(countNumbers (flatten lst)))
We can even write an idiomatic solution using only built-in procedures, check your interpreter's documentation, but in Racket we can do this:
(define (count-flatten lst)
(count number? (flatten lst)))
Anyway, it works as expected:
(count-flatten '(1 x (x 2) x (3 (4 x (5) 6) 7)))
=> 7

How can i remove the side effects of cons?

I can get the odd elements of a list using the following code:
(define (odds lis)
(cond
((null? lis) '())
((not (list? lis)) (quote (Usage: odds(list))))
((null? (car lis)) '())
((= (length lis) 1) (car lis))
(else (cons (car lis) (odds (cddr lis))))))
but when input list of odd length
For example: (odds '(a b c d e))
It will return
(a c . e)
How can i get rid of this obnoxious period?
Try this, it's a change in only one line:
(define (odds lis)
(cond
((null? lis) '())
((not (list? lis)) (quote (Usage: odds(list))))
((null? (car lis)) '())
((= (length lis) 1) lis) ; change here
(else (cons (car lis) (odds (cddr lis))))))
In the highlighted line, you were returning a single element instead of a proper list (a null-terminated list), that's what was causing the problem.

Writing flatten method in Scheme

I have been working on the following function flatten and so far have it working for just lists. I was wondering if someone could provide me with some insight on how to get it work with pairs? For example (flatten '(a .a)) would return (a a). Thanks.
(define (flatten list)
(cond ((null? list) null)
((list? (car list)) (append (flatten (car list)) (flatten (cdr list))))
(else
(cons (car list) (flatten (cdr list))))))
Here's one option:
(define (flatten x)
(cond ((null? x) '())
((pair? x) (append (flatten (car x)) (flatten (cdr x))))
(else (list x))))
This does what you want, without requiring append, making it o(n). I walks the list as a tree. Some schemes might throw a stack overflow error if the list is too deeply nested. In guile this is not the case.
I claim no copyright for this code.
(define (flatten lst)
(let loop ((lst lst) (acc '()))
(cond
((null? lst) acc)
((pair? lst) (loop (car lst) (loop (cdr lst) acc)))
(else (cons lst acc)))))
(define (flatten l)
(cond
[(empty? l) empty]
[(list? l)
(append (flatten (first l))
(flatten (rest l)))]
[else (list l)]))

Resources