简体   繁体   中英

Scheme - Larger list of 2 lists and its sum

Given two lists of the same length, compute the sum of the larger numbers in each corresponding pair of numbers (at the same index) from the lists, without using any inbuilt functions, lambda or set., For example: given these two lists:

list A: (5 3 -4 6 10)

list B: (4 4 9 6 4)

The larger numbers of each pair of numbers are:

larger List: 5, 4, 9, 6, 10

So the sum is 34. My code is:

(define (sum list1 list2)
  (cond ((null? list1) 0)
        ((null? list2) 0)
        ((>= (car list1) (car list2))
         (+ (car list1) (sum (cdr list1) (cdr list2)))
         (+ (car list2) (sum (cdr list1) (cdr list2)))
        )
   )
)

I encounter different errors for different inputs:

(sum '(5) '(3)) 3 ----the opposite of what's needed (sum '(5) '(13)) ----no output (sum '(5 1) '(3 12)). . +: contract violation expected: number? given: # ----error

Correct output is

(sum '(1 9 0) '(-5 6 10))
> 20

I'm not sure what doesn't count as an inbuilt function.

(define (sum L1 L2)
      (if (null? L1)
          0
          (+ (if (> (car L1) (car L2)) 
                 (car L1)
                 (car L2))
             (sum (cdr L1) (cdr L2))))) 

About as minimal as I can get.

You forgot else in your cond -

(define (sum list1 list2)
  (cond ((null? list1) 0)
        ((null? list2) 0)
        ((>= (car list1) (car list2))
         (+ (car list1) (sum (cdr list1) (cdr list2))))
        ( (+ (car list2) (sum (cdr list1) (cdr list2))))))

Here's another way to write it -

(define (max a b)
  (if (> a b) a b))

(define (sum a b)
  (if (or (null? a) (null? b))
      0
      (+ (max (car a) (car b))
         (sum (cdr a) (cdr b)))))

When you have no else clause the Scheme implementation is free to choose whatever they seem fit. It seems your implementation returns something that is not a number.

Here is your code with the uncertainty inserted:

(define (sum list1 list2)
  (cond ((null? list1) 0)
        ((null? list2) 0)
        ((>= (car list1) (car list2))
         ;; the code line below is dead code. It is the last
         ;; expression that is the tail call and result 
         (+ (car list1) (sum (cdr list1) (cdr list2))) ; dead
         (+ (car list2) (sum (cdr list1) (cdr list2))))
        ;; this is what hapens when the first element of
        ;; list1 is smaller than the first element of list2
        (else 'i-choose-you-pikachu)))

So instead of #<void> when you pass it (sum '(1) '(2)) you get i-choose-you-pikachu and that is not a number. So if you pass it (sum '(2 1) '(1 2)) it will do (+ 1 'i-choose-you-pikachu) and that should signal an error from R6RS and newer, while in R5RS pigs might fly since the standard doesn't really cover such cases directly.

Also notice that it doesn't take the largest in the third term, but the smallest... (sum '(2 2 2 2) '(1 1 1 1)); ==> 4 (sum '(2 2 2 2) '(1 1 1 1)); ==> 4

So what you want is to handle the consequences for each term and then add an else term for the last posibiity:

(define (sum list1 list2)
  (cond ((null? list1) 0)
        ((null? list2) 0)
        ((>= (car list1) (car list2))
         (+ (car list1) (sum (cdr list1) (cdr list2))))
        (else 
         (+ (car list2) (sum (cdr list1) (cdr list2))))))

Also notice the indentation tells you the terms and the closing parentheses from your question were lonely. If you need to match them up like that you are using the wrong editor!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM