Trying to apply a function on two lists - list

I wrote the following code in order to apply a function for two lists
which are part of a list of lists but for some reason I'm getting #<void> values in the result.
The code:
(define (applyFunc list)
(cond ((null? list) ())
((null? (cdr list)) (car list))
(else (cons (func (car list) (car (cdr list)))
(applyFunc (cdr (cdr list)))))))
func is a function that applies a function on two given lists
What I get from tracing my code is:
>(applyFunc '((1) (1 1) (1 1 1) (1 1 1 1)))
> (applyFunc '((1 1 1) (1 1 1 1)))
> >(applyFunc '())
< <'()
< '(#<void>)
<'(#<void> #<void>)
(#<void> #<void>)
[assuming the input was '((1) (1 1) (1 1 1) (1 1 1 1))]

A couple of errors to be taken care of first:
You should not call list a procedure parameter (or anything else for that matter), since that's a built-in procedure in Scheme and you'd be overwriting it.
In the first condition, the usual is to return '(), not ()
Other than that, your procedure works fine:
(define (applyFunc lst)
(cond ((null? lst) '())
((null? (cdr lst)) (car lst))
(else (cons (func (car lst) (car (cdr lst)))
(applyFunc (cdr (cdr lst)))))))
It's possible that the problem is in the func procedure, make sure that it does indeed work with two lists. I tested your code with this, and it worked without a hitch:
(define (func l1 l2)
(append l1 l2))

I agree with Oscar, above. The main problem with your code was that on the empty case, you were returning () instead of '().
In terms of your naming conventions, list should technically run just fine, but, as mentioned by Oscar, it is generally considered bad to run the risk of overwriting a built-in procedure.
I updated the code by changing the () to a '(), and it ran flawlessly.

Related

Delete every second item in the list Scheme

My program works with all lists except the improper lists (which have an atom in the cdr field of the last cons cell). Please help upgrade this program to work with the improper lists:
(define (ndelete lst)
(let recur ((i 1) (rest lst))
(cond ((null? rest) '())
((= i 2) (recur 1 (cdr rest)))
(else (cons (car rest) (recur (+ i 1) (cdr rest)))))))
You just need to fix your base condition, (null? rest). If you want to support improper lists, you should check for (not (pair? rest)) instead.
Of course, this has an annoying side-effect of making your function handle any object - not just lists. For any non-list object, it just returns nil. If that's a problem for you, you'll need to encapsulate your recursive function and make sure lst is in fact a list. Like so:
(define (ndelete lst)
(letrec ((recur (lambda (i rest)
(cond ((not (pair? rest)) '())
((= i 2) (recur 1 (cdr rest)))
(else (cons (car rest) (recur (+ i 1) (cdr rest))))))))
(if (pair? lst)
(recur 1 lst)
(raise (condition (make-error)
(make-message-condition `(,lst is not a pair)))))))

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

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.

In a simple script to return the minimum of a list in scheme only the first value of the list is being returned by my solution. What's the bug?

(define (minim lst)
(COND
((NULL? (CDR lst)) (CAR lst))
(< (CAR lst) (minim (CDR lst)) (CAR lst))
(ELSE (minim (CDR lst))))
)
(minim '(3 4 2 9 3 8))
3
I've figured out that it is the second line that is being evaluated and returning the (CAR of any list). What am I missing?
You are missing parenthesis in the second condition. This makes the "<" operator operate over three elements rather than two. The correct code looks like:
(define (minim lst)
(cond ((null? (cdr lst)) (car lst))
((< (car lst) (minim (cdr lst))) (car lst))
(else (minim (cdr lst)))) )
(minim '(3 4 2 9 3 8))
One note though: This code is not tail recursive. It goes all the way to the end of the list and starts comparing from there (i.e., the last element is compared with the one before that and so on).
A more efficient implementation would compare the first element to the current minimum, then proceed forward processing a shorter list every time. If you go this way, you will need an additional function argument holding the current minimum (this is equivalent to a left fold rather than the right fold you have implemented).