How to get the even elements in a list recursively - list

I'm trying to create a function that will return the even numbered elements in a list.
For example:
(evens '(a b c d))
should return
(b d)
The code below seems to work for lists that have and odd numbers of elements, but if I give it a list with an even number of elements, it is incorrect.
For example:
(evens '(a b c d e))
will return
(b d)
But:
(evens '(a b c d))
will return
(a c)
Any thoughts?
Changed my code to:
(DEFINE (evens lis)
(cond
((null? lis) '())
(else (cons (cadr lis) (evens (cdr lis))))
))
Gets a error saying that the object passed to safe-car is not a pair?

The problem is that if your list has an even number of elements, the modulo branch is matched and you start consing with the car of the list ... hence in your example, you get the a, and so on.
More importantly, though, you don't need to use length for this function ... and you shouldn't: since length takes linear time in the length of the list, evens now takes quadratic time.
Suggestion: your program should 'remember' whether it's in an 'odd' or 'even' location at each recursive step ... how could you do this (there are several ways)?

Your code has few missing checks and a bit of incorrect logic.
(define (evens lis)
(cond
((null? lis) '())
((eq? (cdr lis) '()) '()) ;missing condition
(else (cons (cadr lis) (evens (cddr lis)))))) ; it is cddr not cdr

I'm going to answer your question with commented examples, in the hope that you actually learn something instead of just being given code that works. Actually, looking at several pieces of code may be more enlightening, assuming that you're new to scheme.
Your original definition looked like this:
(define (evens lis)
(cond (;; Check: Recursion stop condition
(null? lis)
'())
(;; Wrong: Calling length at each step => O(n^2)
;; Wrong: Assuming even element if list has even number of elements
(= (modulo (length lis) 2) 0)
;; Wrong: Recursing with the rest of the list, you'll get odds
(cons (car lis) (evens (cdr lis))))
(else
;; Wrong: Recursing with the rest of the list with cdr, you'll get odds
(evens (cdr lis)))))
Afterwards, you've edited your question to update it to something like this:
(define (evens lis)
(cond (;; Check: Recursion stop condition
(null? lis)
'())
(else
;; Check: Building list with second element
;; Wrong: If lis only has 1 element,
;; (cdr lis) is null and (car (cdr list)) is an error.
(cons (cadr lis)
;; Wrong: Recursing with cdr, you'll get odds
(evens (cdr lis))))))
A solution is to check if the list has at least a second element:
(define (evens lis)
(cond (;; Check: Recursion stop condition 1
(null? lis)
'())
(;; Check: Recursion stop condition 2: list of length = 1
(null? (cdr lis))
'())
(else
;; Check: Building list with second element
;; The previous cond clauses have already sorted out
;; that lis and (cdr lis) are not null.
(cons (cadr lis)
;; Check: Recurse "the rest of the rest" of lis with cddr
(evens (cddr lis)))))
Exercise: Use if and or to simplify this solution to only have 2 branches.

This same question has been asked time and again over the last couple of days. I'll give a direct answer this time, to set it straight:
(define (evens lst)
(if (or (null? lst) ; if the list is empty
(null? (cdr lst))) ; or the list has a single element
'() ; then return the empty list
(cons (cadr lst) ; otherwise `cons` the second element
(evens (cddr lst))))) ; and recursively advance two elements
And here's how to do some error checking first:
(define (find-evens lst)
(if (list? lst)
(evens lst)
(error "USAGE: (find-evens [LIST])")))

Related

Racket: Graphing a parabola with elements from a list

I have created the following expression which I would like to graph parabolas based on the last two elements in a list. It looks like this:
#lang racket
(require plot)
(define list-sqr-graph
(lambda (lst)
(cond
[(null? lst) (plot (function sqr 0 0))]
[(<= (car lst) 0) (list-sqr-graph (cdr lst))]
[(not (equal? (length lst) 2)) (list-sqr-graph (cdr lst))]
[else (plot (function sqr (car lst) (cdr lst)))])))
The first conditional statement checks if the list is null, and returns a blank graph if true. The second conditional statement skips past numbers from the list which are less than or equal to 0. The third conditional statement checks if the length of the list is equal to 2, and goes down the list until the length is equal to 2.
The else statement is where I get trouble when running an expression such as:
(list-sqr-graph '(1 2 3))
Which will result in an error reading:
function: contract violation
expected: (or/c rational? #f)
given: '(4)
From this error I am led to believe that the first element of the list is being read as a number, but that the second element is having trouble. Why is this?
Thank you in advance!
You are passing a list when ploting. Remember cdr returns a list and not an element (like car does).
You want to use cadr.
#lang racket
(require plot)
(define list-sqr-graph
(lambda (lst)
(cond
[(null? lst) (plot (function sqr 0 0))]
[(<= (car lst) 0) (list-sqr-graph (cdr lst))]
[(not (equal? (length lst) 2)) (list-sqr-graph (cdr lst))]
[else (plot (function sqr (car lst) (cadr lst)))]))) <- HERE

Recursive method in Scheme

I have a (in theory) simple method in Scheme, that has to use recursion. The problem is that I can't seem to figure out the recursion part... I have a procedure that takes a 'pointer' and arbitrary many arguments, and I need to pass the arguments one by one to another method. Here is what I got so far:
(define (push-elements ptr . args)
(define (push-all ptr list)
(if (null? list)
'()
(ptr 'push-elements (car list))))
(push-all ptr list))
I know there is no recursion here, but I can't understand where to put it/how to do it. The thought is clear, inside 'push-all' I need to call:
(push-all ptr (cdr list))
If anyone could help me (and I would be very grateful for an explanation on how to go about making such a recursive method), that would be great.
It's helpful to consider the base case and each incremental case. If you try to push-all onto a stack but have no items, what should the result be? Just the stack. If you try to push-all onto a stack and you have multiple items, what's the result? Well, first you'd push the first of the items onto the stack, giving you a new stack. Then you can push-all the rest of the items onto that stack:
(define (push-all stack items)
(if (null? items)
stack
(let ((new-stack (cons (car items) stack))
(remaining-items (cdr items)))
(push-all new-stack remaining-items))))
(display (push-all '(1 2) '(a b c)))
;=> (c b a 1 2)
Now, your original version was variadic. That is, it accepts any number (well, greater than zero) of arguments because of the dotted arglist. That's fine, but it does mean that you'll need to use apply in setting up the recursive call:
(define (push-all stack . items)
(if (null? items)
stack
(let ((new-stack (cons (car items) stack))
(remaining-items (cdr items)))
(apply push-all new-stack remaining-items))))
(display (push-all '(1 2) 'a 'b 'c))
;=> (c b a 1 2)
Basically you are implementing a variant of for-each, which is like map just for the side effects:
(define (for-each procedure lst)
(let loop ((lst lst))
(if (null? lst)
'undefined-value
(begin
(procedure (car lst))
(loop (cdr lst))))))
(for-each display (list 1 2 3 4)) ; prints 1234
But you wanted to be able to specify the values as arguments so you need to change lst to be a rest argument:
(define (for-each-arg procedure . lst) ; changed to dotted list / rest here
(let loop ((lst lst))
(if (null? lst)
'undefined-value
(begin
(procedure (car lst))
(loop (cdr lst))))))
(for-each-arg display 1 2 3 4) ; prints 1234
If you want a more functional approach you are indeed making either a map or a fold. Perhaps a fold-left would be preferred:
(define (fold-args join init . lst)
(let loop ((acc init) (lst lst))
(if (null? lst)
acc
(loop (join (car lst) acc) (cdr lst)))))
(fold-args cons '() 1 2 3 4) ; ==> (4 3 2 1)
You can actually implement for-each-arg with this:
(define (for-each-arg procedure . lst)
(apply fold-args
(lambda (x acc)
(procedure x)
'undefined)
'undefined
lst))
(for-each-arg display 1 2 3 4) ; => undefined-value; prints 1234

Scheme function to reverse a list

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.

Scheme, Check if anything in two lists are the same

Is it possible to check two list against each other if anything is the same in them?
(check-list '(hey cookie monkey) '(apple pizza cookie) ==> #t
I tried something like
(define (check-list list element)
(let ((x list))
(cond ((null? x) #f)
((eq? (car x) (car element)) #t)
(else (check-list (cdr x) element))))
(check-list list (cdr element)))
I know this is not correctly written but don't know how to tackle this problem.
Anyone that can help me?
Sometimes it helps to formulate the process of the solution to a problem in your natural language. Let's simplify the problem a bit.
How do you check if one element is contained in a list? One way to do that would be to compare that one element with each element in the list until you found it - somewhere along the lines you have already done - but not quite. A quick draft would be:
(define (member? e lst)
(cond ((null? lst) #f) ; empty list doesn't contain e
(or (eq? e <??>) ; either the first element is e or
(member? e <??>))) ; the rest of the list contains e
We can use that previous knowledge to solve the real problem at hand. We know how to search for one element in a list, and now we need to search for each element in a list in another list.
(define (check-list lst1 lst2)
(if (or (null? lst1) (null? lst2)) #f ; empty list(s) share no elements
(or (member? <??> <??>) ; first element of lst1 in lst2?
(member? <??> <??>)))) ; rest of lst1 in lst2?
The <??> should be substituded with the appropriate expressions for selecting the parts of the lists.
Similar to a prior answer but exploiting logic primitives:
(define (intersect? list1 list2)
(and (not (null? list1))
(or (member (car list1) list2)
(intersect? (cdr list1) list2))))
If the lists are wicket long you might want to hash the first list and then just iterate through the second. This uses R5RS with srfi-69 and for small lists you'll get a little overhead but
(require srfi/69); alist->hash-table, hash-table-ref/default
(define (intersect? list1 list2)
(let ((hash (alist->hash-table (map (lambda (x) (cons x x)) list2) equal? )))
(let loop ((list list1))
(and (not (null? list))
(or (hash-table-ref/default hash (car list) #f)
(loop (cdr list)))))))
There seems to be a little confusion. The "big" problem here is how to determine if two lists share at least one element in common, let's write a procedure for that called element-in-common?. Before tackling this problem, we need to determine if a single element belongs in one list, that's what check-list should do (notice that in your code check-list receives as a second parameter an element, but you're treating it as if it were a list of elements).
You don't have to write the check-list procedure, it already exists and it's called member. With that knowledge in hand, we can solve the big problem - how to determine if at least one of the elements in one list (let's call it lst1) is in another list (called lst2)?
Simple: we iterate over each of the elements in lst1 using recursion, asking for each one if it belongs in lst2. If just one element of lst1 is a member of lst2, we return #t. If none of the elements in lst1 is in lst2, we return #f. Something like this:
(define (element-in-common? lst1 lst2)
(cond (<???> ; is the first list empty?
<???>) ; then there are no elements in common
((member <???> lst2) ; is the current element of `lst1` in `lst2`?
<???>) ; then there IS an element in common
(else ; otherwise
(element-in-common? <???> lst2)))) ; advance recursion
Don't forget to test your code:
(element-in-common? '(hey cookie monkey) '(apple pizza cookie))
=> #t
(element-in-common? '(hey cookie monkey) '(apple pizza pie))
=> #f
You can use memq to check if first element on the first list is on the second list, and if not then check recursively if something in the rest of the first list is in the second list:
(define (check-list list1 list2)
(cond ((null? list1) #f)
((memq (car list1) list2) #t)
(else (check-list (cdr list1) list2))))
Here's an answer using higher-order functions
in mit-schme
(define (check-list L1 L2)
(apply boolean/or (map (lambda (x) (member? x L2)) L1)))
(define remove-item
(lambda (lst ele)
(if (null? lst)
'()
(if (equal? (car lst) ele)
(remove-item (cdr lst) ele)
(cons (car lst)
(remove-item (cdr lst) ele))))))

Scheme List Derangement (Rearrangement of sorts)

im trying to write a function in Scheme where i accept a list and return all the different derangements (look below for definition) as a list of lists
derangement: A list where no item is in the same place as the original list
ex: '(a b c) -> '(cab)
any help is appreciated!
Compute all of the permutations of the input list and then filter out the ones that have an element in the same position as the input list. If you need more detail, leave a comment.
Edit 1:
Define (or maybe it's defined already? Good exercise, anyway) a procedure called filter that takes as its first argument a procedure p and a list l as its second argument. Return a list containing only the values for which (p l) returns a truthy value.
Define a procedure derangement? that tests if a list l1 is a derangement of l2. This will be handy when paired with filter.
The most obvious solution would be something like this:
(define filtered-permutations
(lambda (lst)
(filter
(lambda (permuted-list)
(deranged? permuted-list lst))
(permute lst))))
Since the number of derangements is considerably lower than then number of permutations, however, this is not very efficient. Here is a solution that mostly avoids generating permutations that are not derangements, but does use filter once, for the sake of simplicity:
(define deranged?
(lambda (lst1 lst2)
(if (null? lst1)
#t
(if (eq? (car lst1) (car lst2))
#f
(deranged? (cdr lst1) (cdr lst2))))))
(define derange
(lambda (lst)
(if (< (length lst) 2)
;; a list of zero or one elements can not be deranged
'()
(permute-helper lst lst))))
(define derange-helper
(lambda (lst template)
(if (= 2 (length lst))
(let ((one (car lst))
(two (cadr lst)))
(filter
(lambda (x)
(deranged? x template))
(list (list one two) (list two one))))
(let ((anchor (car template)))
(let loop ((todo lst)
(done '())
(result '()))
(if (null? todo)
result
(let ((item (car todo)))
(if (eq? item anchor)
;; this permutation would not be a derangement
(loop (cdr todo)
(cons item done)
result)
(let ((permutations
(map
(lambda (x)
(cons item x))
(derange-helper (append (cdr todo) done)
(cdr template)))))
(loop (cdr todo)
(cons item done)
(append result permutations)))))))))))