简体   繁体   中英

In Racket using recursion how do I return #true if a list “L” sums to n but no values in L are duplicated

This question may be a little complex, I am unsure though, this question appears at least pretty complicated to me. I am essentially trying to write a piece of code that consists of a (listof Num) and a Num. My function is meant to output #true if L is an Egyptian Fraction that represents n. An Egyptian Fraction is the sum of distinct fractions where the numerators are 1 just in case some don't know. I currently have a start to my code and have an idea to solve the question but don't know where to go next. I would highly prefer if the answer was kept in the same format as it is now. I am practicing recursion and trying to improve with it.

In my code I have a base case where if the list is empty it outputs #false.

I then wrote a case where if any values in L were repeated then the function outputs #false

I then wrote a case where if the sum of all the values of L equals the value of n the function would return #true.

My last case simply outputs #false meaning that the sum of the values in L did not equal n.

The thought process for my code appears to be correct but my code does not actually work. This is my code

(define (egyptian? L n)
  (cond
    [(empty? L) #false]
    [(equal? (first L) (first (rest L)) (egyptian? (rest L))) #false]
    [( = n (+ (first L) (egyptian? (rest L))))#true]
    [else #false]))

This is what the function should output

(check-expect (egyptian? (list 1/2 1/3 1/6) 1) #true)
(check-expect (egyptian? (list 1/2 1/4 1/5 1/20) 1) #true)
(check-expect (egyptian? (list 1/2 1/3 1/4 1/5 1/6) 1.5) #false)
(check-expect (egyptian? (list 1/2 1/2 1/2 1/2) 1) #false)

As you can see the first two cases are #true because the sum of the values in the lists are equal to "n". The third case is incorrect because the sum of values in the list do not equal "n". The fourth case is incorrect because values in the list are duplicated. Hopefully I have provided enough information about the question I am struggling on.

The best strategy for this (and many other problems) is to split the problem in smaller parts. Let's start with just finding the sum of all the numbers in a list, this should be easy:

(define (sum L)
  (if (empty? L)
      0
      (+ (first L)
         (sum (rest L)))))

Now, let's write a procedure that checks if the elements in a list are unique. This is not as simple as checking one item in the list with the next one, the repeated item could be anywhere in the list!

(define (unique? L)
  (cond ((empty? L) #true)
        ((member (first L) (rest L)) #false)
        (else (unique? (rest L)))))

With these procedures in place, our main problem becomes trivial to solve:

(define (egyptian? L n)
  (and (unique? L)
       (= (sum L) n)))

You see now, how powerful is the idea of function composition! In your attempted solution you were mixing the code for three different concerns in a single procedure, and that made things real hard to understand.

Another nice effect of splitting the problem in smaller parts is that you can switch implementations later, for more efficient solutions. For example, this is how we'd write the sum and unique? procedures in idiomatic Racket:

(define (sum L)
  (apply + L))

(define (unique? L)
  (= (length L) (set-count (list->set L))))

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