在使用递归的球拍中,如果列表“ L”的总和为n但L中的值没有重复,我如何返回#true

时间:2019-07-03 02:29:38

标签: list recursion boolean racket

这个问题可能有点复杂,但是我不确定,这个问题对我来说似乎至少很复杂。我本质上是在尝试编写由(listof Num)和Num组成的一段代码。如果L是表示n的埃及分数,则我的函数将输出#true。埃及分数是分子为1的不同分数的总和,以防万一某些人不知道。目前,我已经开始编写代码,并且有解决该问题的想法,但不知道下一步该怎么做。我非常希望答案保持现在的格式。我正在练习递归并尝试对其进行改进。

在我的代码中,我有一个基本情况,如果列表为空,则输出#false。

然后我写了一个情况,如果重复L中的任何值,则函数输出#false

然后我写了一个情况,如果L的所有值的总和等于n的值,则该函数将返回#true。

我的最后一种情况只是输出#false,这意味着L中的值之和不等于n。

我的代码的思考过程似乎是正确的,但是我的代码实际上不起作用。 这是我的代码

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

这是函数应该输出的内容

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

如您所见,前两种情况为#true,因为列表中值的总和等于“ n”。第三种情况是不正确的,因为列表中的值之和不等于“ n”。第四种情况是不正确的,因为列表中的值是重复的。希望我能提供有关我正在努力解决的问题的足够信息。

1 个答案:

答案 0 :(得分:2)

对此(以及许多其他问题)的最佳策略是将问题分成较小的部分。让我们从查找列表中所有数字的总和开始,这应该很容易:

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

现在,让我们编写一个过程来检查列表中的元素是否唯一。这并不像将列表中的一项与下一项检查一样简单,重复的项可能在列表中的任何地方!

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

有了这些程序,我们的主要问题就变得难以解决:

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

现在您知道,功能组合的概念多么强大!在您尝试的解决方案中,您在一个过程中混合了三个不同问题的代码,这使事情变得很难理解。

将问题分解为较小部分的另一个不错的效果是,您可以稍后切换实现,以获得更有效的解决方案。例如,这就是我们在惯用的球拍中编写sumunique?过程的方式:

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

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