如何写一个“set-equal?”谓词?

时间:2013-10-06 18:05:03

标签: list lisp scheme set racket

如何构建使用same?返回#t的{​​{1}}谓词? 我很难写一个(same? '(4 6) '(6 4)) - 谓词,如果(same? a b)#t相等,则返回a,否则返回b。也是一个类似的谓词#f,用于确定(element? el set)el的元素。

(是的,这是作业,所以我不是在完成一个完整的解决方案之后。我只需要在正确的方向上得到一个或几个,因为我们的教师几乎找不到任何帮助。)

我们使用列表来表示集合。我们被要求为自己建立我们需要的一切。像地图等高阶函数几乎被禁止了。

问题是我的元素?同样的?不起作用:

set

这些应该返回(same? '(4 6) '(6 4))<br/> (element? '(2 3) '(1 8 5 '(3 2) 4)) ,但他们没有,我明白为什么,但我仍然无法修复它。

我的#t看起来像这样,我知道它只适用于相同订单的列表,但问题是我如何改进它? (element?setEmptysetFirst被定义为setRestnull?car。我们被要求为自己制作一些原因。)

cdr

我有一个看似这样的工作(define element? (lambda (x set) (cond ((setEmpty? set) #f) ((equal? x (setFirst set)) #t) (else (element? x (setRest set))) ) ) ) - 谓词,可能有用:

set?

如果列表及其“子列表”没有重复,则返回(define set? (lambda (set) (cond ((setEmpty? set) #t) ((list? (setFirst set)) (if (element? (setFirst set) (setRest set)) #f (set? (setFirst set)))) (else (if (element? (setFirst set) (setRest set)) #f (set? (setRest set)) ) ) ) ) ) 。我还有一个程序,可以使列表中的真实集合具有可以正常工作的重复项。

4 个答案:

答案 0 :(得分:2)

一些指示,让你朝着正确的方向前进。

element?程序大多是正确的,但不应使用equal?进行密钥比较 - 它应使用same?,而same?应区分两个case:比较的元素是原子还是集合。

因此,不难想象整个练习的正确性取决于same?的实施。反过来,这取决于所选择的集合表示。在精彩的SICP书中有一整章关于representing sets(包括将列表作为列表),你应该从阅读它开始,以获得你的支持。

一旦你实现了集合的原始程序,很容易检查两个集合是否相等,我会留给你实现setSizesetUnion

(= (setSize a) (setSize b) (setSize (setUnion a b)))

或者,正如@sds在他的回答中指出的那样,你可以确定两个集合是否相同,如果它们是彼此的子集 - 你应该自己实现subset?过程:

(and (subset? a b) (subset? b a))

答案 1 :(得分:1)

您的问题似乎是您正在使用equal?来比较element?中的设置元素。

您需要编写自己的element-equal?,这会考虑到设置元素可能是列表而不是原子,而是使用它而不是equal?

关于same? - 我认为最简单的方法是这样实现:

(define same? 
  (lambda (a b) 
    (and (subset? a b)
         (subset? b a))))

(define subset? 
  (lambda (a b)
    (or (isEmpty a)
        (and (element? (first a) b) 
             (subset? (rest a) b)))))

答案 2 :(得分:1)

对于球拍程序员的注意事项:如果可以,请避免重新发明轮子。如果合适,请使用标准库的racket/set,它提供了良好的集合实现。

答案 3 :(得分:0)

我的实验室现在正在顺利运行。我要感谢所有发表评论的人,并向那些在同样的实施中苦苦挣扎的人提起一些事情。

从我的角度来看指针: - 抽象地思考。阅读设定理论的快速介绍。足以知道辩护 集,子集,空集,联合等。

- 写下论文中的所有程序,并考虑哪些程序需要其他程序。

- 在考虑如何写同样的时候?例如,假设您有一个已经有效的过程子集。事实上,你已经有很多有用的程序,(即使你还没有它们)=)不要担心,只是试着想一下哪些程序一样?需要尽可能整洁。对你的所有程序都这样继续。

- 您可能会遇到程序问题,只是在它们之间来回发送事物并且程序进入无限循环。如果你从一开始就小心并且认识到这个问题可能出现的时候,你就不应该参与其中。但偶尔你必须重新考虑一些程序。也许他们可以使用其他程序来完成同样的事情?

我还会分享一些程序,看看你的想法。随意屠宰他们,他们到目前为止工作=)..并且它应该在这个星期五到期。 PS。我的proc makeSet基本上听起来像它。它删除了所有“级别”中的所有重复元素。

;;; predicate that returns #t if a list is a set and #f otherwise
(define set?
  (lambda (set)
    (cond ((setEmpty? set) #t)
      ((not (list? set)) #f)
      ((equal? (makeSet set) set) #t)
      (else #f))
  )
)

;;; diff returns the difference between set1 and set2
(define diff
  (lambda (set1 set2)
    (cond ((null? set1) '())
       ((null? set2) set1)
       ((not (member? (car set1) set2))
        (cons (car set1) (diff (cdr set1) set2)))
       (else (diff (cdr set1) set2)))
  )
)

哦,我没有改变所有的车,cdr和cons到我们的“抽象”等于setFirst等,我会的。另外我可能会让diff返回其返回值的“makeSet-version”,以确保我总是得到一个set作为返回。

再次感谢大家! / REM