getting the largest number in a list in scheme

倾然丶 夕夏残阳落幕 提交于 2019-12-04 05:06:36

问题


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 then you call the function minus the first one in the list, else you construct the first atom, largest one, with the rest of the list. relevant code:

(define (getlargest a_list)
  (cond
    ((null? a_list) '())
    ((< (car a_list) (cadr a_list)) (getlargest (cdr a_list)))
    (else (cons (car a_list) (getlargest(cdr a_list))))))

回答1:


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)



回答2:


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



回答3:


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



回答4:


(define (maxim lst)
  (vector-argmax (lambda (x) x) (list->vector lst)))


来源:https://stackoverflow.com/questions/27128960/getting-the-largest-number-in-a-list-in-scheme

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!