在Scheme中创建集合的分区

时间:2017-04-26 19:50:10

标签: scheme racket partition-problem

我对整体计划很陌生,而且我在解决学校作业方面遇到了一些问题。所以请不要完整的答案,只是寻找一点点的洞察力或正确的方向推动所以我可以自己解决这个问题。

问题如下:给定一个数字列表,确定是否可以从这些数量的等价和项数中制作两个子集。因此,例如,如果给定的集合是(1 1)那么我的程序应该返回#t,否则返回#f。

这是我到目前为止所写的内容(即使它目前没有输出)

(define l (list '(7 5)))

(define s1 0)
(define s2 0)
(define l1 0)
(define l2 0)

(define two-subsets
  (lambda (l s1 s2 l1 l2)
    (if (null? l)
          (if (and (= s1 s2) (= l1 l2))
              (#t))
          (if (not (and (= s1 s2) (= l1 l2)))
              (#f)))
    (or ((two-subsets(cdr l) (+ s1 1) s2 (+ l1 1) l2) (two-subsets(cdr l) s1 (+s2 1) l1 (+ l2 1))))))

我的函数应递归地将项添加到子集1(s1,l1)或子集2(s2,l2),直到它到达基本情况,其中它确定子集是否具有相等的大小和总和。我觉得我的逻辑在那里/接近,但我不确定如何在计划中正确地实现这些想法。

编辑我应该补充一点,作为赋值的一部分,我必须使用递归。我希望DrRacket提供更多调试信息,因为当我点击运行它没有错误,但也没有输出。

2 个答案:

答案 0 :(得分:2)

问题

您的代码中存在一些问题。

第一

这会创建一个列表列表:

(list '(7 5))  ; => ((7 5))

cdr总是一个空列表。

(cdr (list '(7 5)))  ; => ()

以这种方式创建单个列表:

(define l (list 7 5))

或者这样:

(define l '(7 5))

第二

您在Scheme中使用括号进行申请。这样:

(#t)

表示"执行函数#t"。但#t不是函数,而是布尔值。并且无法执行布尔值。

您可以直接返回布尔值

#t

或者您可以返回一个返回值

的函数
(lambda () #t)

但你不能执行true。

第三

or中的同样问题。以下代码:

(or ((two-subsets (cdr l) (+ s1 1) s2 (+ l1 1) l2)
     (two-subsets (cdr l) s1 (+s2 1) l1 (+ l2 1))))

表示:two-subsets必须返回一个函数。第一个two-subsets调用返回的函数将使用第二个two-subsets调用返回的函数执行。并且单个结果值将传递给or。这可能不是你想要的。

如果您希望or两次调用two-subsets的两个返回值,则必须删除两个括号。

(or (two-subsets (cdr l) (+ s1 1) s2 (+ l1 1) l2)
    (two-subsets (cdr l) s1 (+s2 1) l1 (+ l2 1)))

提示

  • 定义与您的最终条件匹配的函数。该函数采用两个列表参数和检查,如果它们具有相同的大小(length)和总和(您可以使用apply将列表传递给+)。 Spoiler
  • 编写一个迭代所有可能子集的函数。并使用每种组合调用您的匹配功能。迭代通过Scheme中的递归完成。定义一个函数,该函数调用自身或使用命名的let

答案 1 :(得分:1)

对于第一遍,您可能希望避免尝试将“子集”逻辑耦合到“将两个子集添加到相同值”逻辑。小程序比长程序更容易编写。

但这可能是一个复杂的问题。

接近它的一种方法叫做“一厢情愿”。我们将从最后开始工作:解决此问题的最后步骤是什么?比较相同长度的两个子集是否相加到相同的值。所以,让我们解决这个问题。然后我们只对相同长度的所有子集执行此操作。但现在我们需要知道:相同长度的所有子集组是什么?如果我们解决了这个问题,那么到目前为止的一切都已完成所以让我们解决这个问题。然后我们将它应用于所有子集的集合。但现在我们需要知道:我们如何获得所有子集的集合?如果我们解决了这个问题,那么到目前为止的一切都已完成我们只是将它应用到我们的套装中。但现在我们需要知道:我们的设定是什么? -哦!这就是问题本身。所以我们完成了!

实际上在细节上有点棘手,但是通过上述说明,我认为你可以看到这个链条的逻辑:

(find-first-equal-sum ; we can stop as soon as #t, if there is #t
  (make-pairs ; problem only wants us to consider pairs
    (sum-subsets ;we need sums eventually
       (at-least-two-in-a-group ; can't make pairs without at least two in a group
        (group-by-length ; only care about matching subsets of the same length
         (at-least-length-2 ; singles can't match because each element of a set is unique
          (subsets problem-set)))))))

注意:我确实写过这个程序并在发布之前对其进行测试。上述“大纲”直接从DrRacket复制。

相关问题