Could anyone help me spot what is wrong in the following way of finding a min and a max in a list and returning them as a list? It should be working logically. I suppose there's something wrong with the parentheses.
(define (find-min-and-max my-list)
(find-min-max-rec (car my-list) (car my-list) my-list)
)
(define (find-min-max-rec smallest largest ls)
(if (null? ls)
(list smallest largest)
)
(cond
((and (< smallest (car ls)) (> largest (car ls)) ) (find-min-max-rec (car ls) (car ls) (cdr ls)))
((< smallest (car ls)) (find-min-max-rec (car ls) largest (cdr ls)))
((> largest (car ls)) (find-min-max-rec smallest (car ls) (cdr ls)))
(else (find-min-max-rec smallest largest (cdr ls)))
)
)
(display (find-min-and-max '(1 2 3 4)))
Console output
*** ERROR: pair required, but got ()
While loading "./jdoodle.sc" at line 17
Stack Trace:
_______________________________________
0 (car ls)
at "./jdoodle.sc":10
1 (find-min-and-max '(1 2 3 4))
at "./jdoodle.sc":17
Command exited with non-zero status 70
Expected
(1 4)
In addition, is there any debugging tool that you would recommend using?
Note: I have been running my code in here: https://www.jdoodle.com/execute-scheme-online
Yep, actually you're right. There's something wrong with the parentheses.
Here's a clue: What does this evaluate to?
(define (f x)
(if (< x 5) 10)
12)
(f 3)
Why?
Related
I'm currently learning about recursion in Scheme. I found this recursive definition but I don't understand what it is trying to do. If someone could explain it to me, I would appreciate it. Here is the definition:
(define (function ls)
(if (null? ls) '()
(append
(map (lambda (x) (cons (car ls) x))
(function (cdr ls))
)
(function (cdr ls))
)
)
)
In its current state, function simply returns the empty list, no matter the input. However, it does ring a bell. It looks like a failed attempt to implement the powerset function:
(define (powerset ls)
(if (null? ls)
'(())
(append (map (lambda (x) (cons (car ls) x))
(powerset (cdr ls)))
(powerset (cdr ls)))))
Can you spot the difference? the base case in your code is wrong! In case you were wondering, powerset returns the set of all possible subsets of a list:
(powerset '(1 2 3))
=> '((1 2 3) (1 2) (1 3) (1) (2 3) (2) (3) ())
i need to create a list such that the min is always at the outside in a list.
Example
input (1 2 3)
output (1 (2 3))
Here is my code, assuming that the numbers are in descending order, which i wish to extent later to a general case.
I am getting an unexpected output of (3 2 1 0 -1 -2 -3 ()).
How do I achieve this in scheme any ideas?'
(define (find-min-rest L)
(if (null? (cdr L)) (let ( (x (car L))) (cons x '( ())))
(let* ((ret-ans (find-min-rest (cdr L))) (cur-elem (car L)) (mini (car ret-ans)) (rem-list (cdr ret-ans)))
(cond ((> cur-elem mini) (cons cur-elem (cons mini rem-list)))))))
It'll be simpler if you use built-in procedures, and split the problem in parts. Notice that the following assumes that there's a single minimum, adjust as necessary:
(define (find-min-rest L)
(let* ((the-min (apply min L))
(the-rest (remove the-min L)))
(list the-min the-rest)))
(find-min-rest '(1 2 3))
=> '(1 (2 3))
The code
(define (find-min-rest L)
(if (null? (cdr L)) (let ( (x (car L))) (cons x '( ())))
(let* ((ret-ans (find-min-rest (cdr L))) (cur-elem (car L)) (mini (car ret-ans)) (rem-list (cdr ret-ans)))
(cond ((> cur-elem mini) (cons cur-elem (cons mini rem-list)))))))
I have a requirement to write a scheme procedure that takes a list as a parameter, which defines points awarded, player A score, and player B score. The function should determine who is the winner based on the scores:
For example, this the list of lists of scores I use below:
(define scores '(
(5 . (5 . 3)) ; points awarded = (car (car scores)) 5; player A score = cadr (car scores)) 5; player B score (cddr (car scores)) 3;
(5 . (6 . 2))
(5 . (8 . 4))
(5 . (5 . 1))))
So just to clarify, breaking down the first list in the list:
5 = points awarded (car (car scores)) ;
A = Player A Score (cadr (car scores)) ; (which is 5 on the first element, 6 on the 2nd, etc.)
B = Player B Score (cddr (car scores)) ; (which is 3 on the first element, 2 on the 2nd, etc.)
The problem is I have made a recursive function which blows up on the 1st iteration of the recursion. But I don't understand why?
#lang scheme
(define (game-winner scores)
(define A 0)
(define B 0)
(cond
((empty? scores) '()))
(if ( > (cadr (car scores)) (cddr (car scores)) )
(+ A (car (car scores)))
(+ B (car (car scores))))
(game-winner (cdr scores)))
OUTPUT:
car: contract violation
expected: pair?
given: ()
The part that confuses me is that when I simulate running through the 1st iteration of the recursion and get the values the function should have, I get correct values:
;first loop through function
(car (car scores)) ; 5
(cadr (car scores)) ; 5
(cddr (car scores)) ; 3
;second loop (1st recursive call)
(cadr (car (cdr scores))) ; 6
(cddr (car (cdr scores))) ; 2
So if I don't understand why it's blowing up? It should work in the same way as the first call before the recursion. But I obviously am missing something. Any ideas?
P.S.
if I just return the A or B instead of the recursive call I get 0:
(define (game-winner scores)
(define A 0)
(define B 0)
(cond
((empty? scores) '()))
(if ( > (cadr (car scores)) (cddr (car scores)) )
(+ A (car (car scores)))
(+ B (car (car scores))))
A)
OUTPUT:
0
How come the value of A (which should be 5) after the first call doesn't show when I oupout A? Is A only in scope of the if loop? If so, how do I get it to exist outside that scope?
based on feedback from #Sylwester I modified by procedure to:
#lang scheme
(define (game-winner scores)
(define A 0)
(define B 0)
(cond
((empty? scores) '())
(( > (cadr (car scores)) (cddr (car scores)))
(cons (+ A (car (car scores))) (game-winner (cdr scores))))
(cons (+ B (car (car scores))) (game-winner (cdr scores)))))
OUTPUT:
(5 5 5 5)
So I feel like I'm getting closer. But I need to be able to add these all together for A or for B and output the winner (A or B). How do I build on top of this to get that to work?
You code has a lot of dead code that is never used no matter what is the outcome and in the end the last expression will do (cdr scores) no matter if it's empty or not.
(define (game-winner scores)
;; Two constants that never change from 0
(define A 0)
(define B 0)
;; Dead code. Werther it's '() or #<undefined>
(cond
((empty? scores) '()))
;; Dead code. Becomes (+ 0 (car scores)) but never used
(if ( > (cadr (car scores)) (cddr (car scores)) )
(+ A (car (car scores))) ; + never mutates A
(+ B (car (car scores)))) ; + never mutates B
;; Infinite recursion. Happens no matter what is the outcome of the dead code
(game-winner (cdr scores)))
So when you write a cond or if it should handle all the things that happen so that it is the last expression:
(define (game-winner scores)
; local defines
(define some-var some-expression)
...
; one expression, the result of this is the result of the procedure.
(if (empty? scores)
'()
(if ....)))
EDIT
Here is an example of a recursion using arguments to accumulate the scores and in the end determine who has the highest score:
(define (game-winner scores)
(let loop ((scores scores) (a 0) (b 0))
(if (empty? scores)
(cond ((> a b) 'A)
((< a b) 'B)
(else 'TIE)))
(loop (cdr scores)
(+ a (cadar scores))
(+ b (cddar scores))))))
(game-winner scores)
; ==> A
I'm trying to implement a function which calc sum of list , its name is sum -
(define (sum elemList)
(if
(null? elemList)
(+ (car elemList) (sum (cdr elemList)))
0
)
)
The above implementation gives wrong result , for example -
> (sum (list 1 2 3 4 ))
0
What I did wrong here ?
I think you swapped the then and the else part of the if:
(define (sum elemList)
(if
(null? elemList)
0
(+ (car elemList) (sum (cdr elemList)))
)
)
In the original function, for every non-empty list, 0 is returned.
You can also use apply
(define (sum elemList) (apply + elemList))
Should give you the same results
Please refer by this link for more details.
-http://groups.umd.umich.edu/cis/course.des/cis400/scheme/listsum.htm
(define(list-sum lst)
(cond
((null ? lst)
0)
((pair? (car lst))
(+(list-sum (car lst)) (list-sum (cdr lst))))
(else
(+ (car lst) (list-sum (cdr lst))))))
First off, this is homework, but I am simply looking for a hint or pseudocode on how to do this.
I need to sum all the items in the list, using recursion. However, it needs to return the empty set if it encounters something in the list that is not a number. Here is my attempt:
(DEFINE sum-list
(LAMBDA (lst)
(IF (OR (NULL? lst) (NOT (NUMBER? (CAR lst))))
'()
(+
(CAR lst)
(sum-list (CDR lst))
)
)
)
)
This fails because it can't add the empty set to something else. Normally I would just return 0 if its not a number and keep processing the list.
I suggest you use and return an accumulator for storing the sum; if you find a non-number while traversing the list you can return the empty list immediately, otherwise the recursion continues until the list is exhausted.
Something along these lines (fill in the blanks!):
(define sum-list
(lambda (lst acc)
(cond ((null? lst) ???)
((not (number? (car lst))) ???)
(else (sum-list (cdr lst) ???)))))
(sum-list '(1 2 3 4 5) 0)
> 15
(sum-list '(1 2 x 4 5) 0)
> ()
I'd go for this:
(define (mysum lst)
(let loop ((lst lst) (accum 0))
(cond
((empty? lst) accum)
((not (number? (car lst))) '())
(else (loop (cdr lst) (+ accum (car lst)))))))
Your issue is that you need to use cond, not if - there are three possible branches that you need to consider. The first is if you run into a non-number, the second is when you run into the end of the list, and the third is when you need to recurse to the next element of the list. The first issue is that you are combining the non-number case and the empty-list case, which need to return different values. The recursive case is mostly correct, but you will have to check the return value, since the recursive call can return an empty list.
Because I'm not smart enough to figure out how to do this in one function, let's be painfully explicit:
#lang racket
; This checks the entire list for numericness
(define is-numeric-list?
(lambda (lst)
(cond
((null? lst) true)
((not (number? (car lst))) false)
(else (is-numeric-list? (cdr lst))))))
; This naively sums the list, and will fail if there are problems
(define sum-list-naive
(lambda (lst)
(cond
((null? lst) 0)
(else (+ (car lst) (sum-list-naive (cdr lst)))))))
; This is a smarter sum-list that first checks numericness, and then
; calls the naive version. Note that this is inefficient, because the
; entire list is traversed twice: once for the check, and a second time
; for the sum. Oscar's accumulator version is better!
(define sum-list
(lambda (lst)
(cond
((is-numeric-list? lst) (sum-list-naive lst))
(else '()))))
(is-numeric-list? '(1 2 3 4 5))
(is-numeric-list? '(1 2 x 4 5))
(sum-list '(1 2 3 4 5))
(sum-list '(1 2 x 4 5))
Output:
Welcome to DrRacket, version 5.2 [3m].
Language: racket; memory limit: 128 MB.
#t
#f
15
'()
>
I suspect your homework is expecting something more academic though.
Try making a "is-any-nonnumeric" function (using recursion); then you just (or (is-any-numeric list) (sum list)) tomfoolery.