I do not understand why my function to get the largest number does not want to work. If I am thinking about this correctly, if the first atom is smaller than the second atom the
First mistake is that you are returning list as output in base case. You need to return a number.
You can implement this procedure in recursive way by storing the max value in MaxVal
accumulator as we recurse through list.
input : List of positive unique numbers inList
output : Maximum value in list MaxVal
Follow is the implementation for above specification:
(define (GetMaxVal MaxVal inList)
(cond ( (null? inList ) MaxVal )
( (> (car inList) MaxVal ) (GetMaxVal (car inList) (cdr inList)) )
( else ( GetMaxVal MaxVal (cdr inList)) ) ))
(define inList '(1 67 3 5 176 4745 34 575))
(display (GetMaxVal 0 inList) ) ; prints 4745 to screen
MaxVal
MaxVal
than update MaxVal
; pass MaxVal
and (cdr inList)
in argument in recursive call.else
the first element is not greater so recurse by passing list without first element i.e. (cdr inList)
There are 2 errors in your code:
1) in the else
clause, you should recursively call yourself, dropping the second element:
(else (getlargest (cons (car a_list) (cddr a_list))))))
2) you are missing the case of a list of only one element, where cadr
will fail
((null? (cdr a_list)) (car a_list))
And I personally prefer to yield #f
if the list is empty. Thus the code would look like
(define (getlargest a_list)
(cond
((null? a_list)
#f)
((null? (cdr a_list))
(car a_list))
((< (car a_list) (cadr a_list))
(getlargest (cdr a_list)))
(else
(getlargest (cons (car a_list) (cddr a_list))))))
Of course, a solution using foldl
is preferable:
(define (getlargest lst)
(foldl (lambda (e r) (if (or (not r) (> e r)) e r))
#f
lst))
or, probably slightly more efficient:
(define (getlargest lst)
(if (null? lst)
#f
(foldl (lambda (e r) (if (> e r) e r))
(car lst)
(cdr lst))))
(define (max-list-element list)
(define (aux list actual-max)
(if (pair? (cdr list))
(if (>= (car list) actual-max)
(aux (cdr list) (car list))
(aux (cdr list) actual-max))
(if (> (car list) actual-max)
(car list)
actual-max)))
(aux list (car list)))
My implementation.
This is incorrect because when you type (maximum '(2 1))
there is an error (any test with reverse order fails )
Without any loop, using recursivity:
(define (maximum L)
(if (null? (cdr L))
(car L)
(if (< (car L) (maximum (cdr L)))
(maximum (cdr L))
(car L)
)
)
)
(define (maxim lst)
(vector-argmax (lambda (x) x) (list->vector lst)))
Your current procedure is failing at runtime. Even if it didn't, you're comparing one element with the next, but that won't work for finding a maximum, for instance in a list such as this it'll return 1
, which is incorrect: '(10 2 0 1)
. There are other mistakes, for instance - why are you building a list as output, when the answer should be a number? also you have to be very careful with the edge cases, your procedure is failing when there's a single element left in the list.
The correct way is to compare one element assumed to be the maximum with all the rest, if we find one that is greater than the assumed maximum, then we've found a new maximum. This is what I mean:
(define (getlargest a_list)
(if (null? a_list) ; edge case: empty list
#f ; return a special value signaling error
(let loop ((a_list (cdr a_list)) ; rest of the list
(maxval (car a_list))) ; assumed maximum
(cond ((null? a_list) maxval) ; if the list is empty, return max
((> (car a_list) maxval) ; current element > max
(loop (cdr a_list) (car a_list))) ; found new max
(else ; otherwise
(loop (cdr a_list) maxval)))))) ; keep the same max
Of course, in real life we would use the built-in max
procedure for the same purpose:
(apply max a_list)