getting the largest number in a list in scheme

断了今生、忘了曾经 提交于 2019-12-02 03:59:39

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

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

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))))
E.Praneeth
(define (maxim lst)
  (vector-argmax (lambda (x) x) (list->vector lst)))
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!