Racket: Graphing a parabola with elements from a list - 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

Related

How to print a list element by element vertically? Racket

Im a noob in Racket, and I am trying to figure out how to print the elements of one list vertically, thus:
(printv '(1 2 3 4))
1
2
3
4
T
I try with if and cond, thus:
(define (delete x lst)
(cond [(member x lst)(append(reverse(rest(member x(reverse lst))))(rest(member x lst)))]
[else "Error"]
))
(define (printv lst)
(cond [(< 0 (length lst)) ((printf "~a ~%" (first lst))(printv (delete (first lst) lst)))]
[else "T"]))
But I got this error in the moment the list becomes empty
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
Help is appreciated
You should use built-in procedures to make your life easier. And why do you want to delete the elements? just iterate over the list. Try this:
(define (printv lst)
(for-each displayln lst)
(displayln "T"))
Just removing the extra parentheses fixes your problem:
(define (printv lst)
(cond [(< 0 (length lst))
(printf "~a ~%" (first lst))
(printv (delete (first lst) lst))]
[else "T"]))
Some hints:
Doing length at each iteration makes makes your function exponential time. Eg. doubling the list to display squares the time it takes. A beter approach to check if a list is empty is using (empty? lst)
How you get the rest of the list using delete is perhaps the most complicated I've seen. Since you know you are removing the first element you can just replace it with (rest lst).
Just printing with a linefeed has a function: displayln
All combined:
(define (printv lst)
(cond [(empty? lst) "T"]
[else
(displayln (first lst))
(printv (rest lst))]))
Pure Scheme version:
(define (printv lst)
(cond [(null? lst) "T"]
[else
(display (car lst))
(newline)
(printv (cdr lst))]))

Permutations of a list in scheme, works for numbers but not character as elements in list

I'm trying to do a program in scheme for a school assignment. Given a list, it's supposed to return all given permutations of that list. My issue is that I don't know why it would work for numbers but not characters. Doesn't seem like it would change any of the logic!
Here is my code:
(define (remove1 x lst)
(cond
((null? lst) '())
((= x (car lst)) (remove1 x (cdr lst)))
(else (cons (car lst)
(remove1 x (cdr lst))))))
(define (permute lst)
(cond
((= (length lst) 1) (list lst))
(else (apply append (map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove1 i lst))))
lst)))))
(permute '(1 2 3))
= is used for comparing numbers; for more general comparisons, use eq?, equal? or (as has been suggested) eqv?.

Return the second element for every element in a list

Let's say we have this list '( (4 (1 2)) (5 (5 5)) (7 (3 1)) (1 (2 3)))
I am trying to write smth in Scheme in order to get the second element for every element in the list.. So the result will look like '( (1 2) (5 5) (3 1) (2 3))
I have this code so far..
(define (second list1)
(if (null? (cdr list1))
(cdr (car list1))
((cdr (car list1))(second (cdr list1)))))
Here's a straightforward solution:
(define (seconds lst)
(map cadr lst))
In general, when you want to transform every element of a list, map is the way to go.
All you need to do is map the built-in function second onto the list lst:
(map second lst)
Your error is that you lack an operator, perhaps cons. If you look at the consequent:
((cdr (car list1))(second (cdr list1)))
So Scheme expects (cdr (car list)) to be a procedure since it's in operator position in the form, but since it isn't you get an error. In addition (cdr (car x)) == cdar wont take the second element in every element but the tail of each element. cadar is what you're lookig for.
(define (second list1)00+
(if (null? (cdr list1))
(cons (cadar list1) '())
(cons (cadar list1) (second (cdr list1)))))
It will fail for the empty list. To fix this you let the consequemt take care of every element and the base case only to stop:
(define (second list1)
(if (null? list1)
'()
(cons (cadar list1) (second (cdr list1)))))
The result for a list will be the same. There is a procedure called map. It supports several list arguments, but the implementation for one is:
(define (map fun lst)
(if (null? lst)
'()
(cons (fun (car lst)) (map fun (cdr lst)))))
Looks familiar? Both make a list based on each element, but map is generic. Thus we should try to make (fun (car lst)) do the same as (cadar lst).
(define (second lst)
(map cadr lst)) ; (cadr (car x)) == (cadar x)
There you have it. Chris beat me to it, but I'd like to comment one of the other answers that uses the abbreviation second. It's defined in racket/base and the library SRFI-1, but it's not mentioned in the last Scheme reports. I.e. some implementations might require an extra library to be imported for it to work.

How to get the even elements in a list recursively

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])")))

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)))))))))))