如何判断球拍中的两组内容是否相等(无视顺序)?

时间:2015-05-30 01:19:46

标签: recursion racket

我有一个家庭作业问题,要求我告诉两套内容是否相等,无论顺序如何。

Ex :( set-equal?(list 1 2 3)(list 3 2 1))为真

到目前为止,我已经获得了此代码,

(define (set-equal? list1 list2)
  (cond
    [(and(empty? list1)(empty? list2)) true]
    [(and(cons? list1)(empty? list2)) false]
    [(and(empty? list1)(cons? list2)) false]
    [(and(cons? list1)(cons? list2))
      (if (member? (first list1)(list2)) (set-equal? (rest list1)(list2))(set-equal? (rest list1) list2))]))

这段代码显然不起作用,因为即使两个列表相等,递归也会导致列表1的(空),列表2仍会有数据,使最终输出为假。

我想我应该这样做: 检查list1中的数据与list2中的数据,如果有相同的数据,则从两个列表中删除它。然后继续检查,直到两个列表都为空(给出为真)或者一个为空,一个仍然有数据(输出为假)。问题是,我不知道如何编写代码。

有人能给我一些关于如何解决这个问题的提示吗?

5 个答案:

答案 0 :(得分:2)

回想一下将A集合作为B的子集意味着什么的数学定义。

     A is a subset of B 
<=>  for all a in A :  a is a member of B

数学定义可以像这样写在Racket中:

(define (subset? A B)
  (for/and ([a A])
    (member a B)))

两组AB之间的平等定义是:

     A = B
<=>  A is a subset of B  and  B is a subset of A

Racket版本是:

(define (set-equal? A B)
  (and (subset A B)
       (subset B A)))

然而对于有限集,我们可以做得更好(就速度而言):

For finite sets:
     A = B
<=>  A is a subset of B  and   size(A) = size(B)

在Racket中:

(define (set-equal? A B)
  (and (= (length A) (length B))
       (subset? A B)))

答案 1 :(得分:1)

是否有规定您 使用递归?如果没有,您可以执行以下操作:

如果长度不等,则结果为false。在这种情况下,没有必要继续进行。而且,我们知道and(expr..)一发现false表达式从左到右,就会返回false

来自 documentation

(and expr ...) 
  

如果没有提供exprs,则结果为#t。

     

如果提供了单个expr,那么它处于尾部位置,因此和表达式的结果是expr的结果。

     

否则,将评估第一个expr。 如果它产生#f,则表达式的结果为#f 。否则,结果与a和表达式相同,其余的exprs位于尾部位置相对于原始和表单。

鉴于它们的长度相等,输入列表按升序排序(或者只要它们以相同的方式排序,就会降序),并检查它们是否相等。

(define (set-equal? list1 list2)
  (and (equal? (length list1) (length list2)) (equal? (sort list1 <) (sort list2 <)))
)

(set-equal? (list 1 2 3) (list 3 2 1))
(set-equal? (list 2 1 2) (list 1 2 2))
(set-equal? (list 2 1 2) (list 7 2 2))

<强>输出true true false

答案 2 :(得分:1)

假设

  1. 列表实际上代表集合,因为它们没有重复的成员。
  2. 死亡简单解决方案

    #lang racket
    
    (define a '(1 2 3))
    (define b '(3 2 1))
    (define c '(1))
    
    (define (set-equal? a b)
      (equal? (list->set a)
              (list->set b)))
    

    用法

    eq-sets.rkt> (set-equal? a b)
    #t
    eq-sets.rkt> (set-equal? a c)
    #f
    eq-sets.rkt> (set-equal? a a)
    #t
    

    一种清单方法

    这在运行时方面不是很优雅或非常有效,但它显示了lambda以及函数如何返回评估布尔表达式的结果:

    (define (set-equal2? a b)
      (and (= (length a)
              (length b))
           (not (false?
             (andmap
              (lambda (e) (member e b))
              a)))))
    

    注释

      如果长度不相等,则
    1. and短路。

    2. (not (false? (andmap...用于返回#t而非评估为#t的值,例如(set-equal?2 a a)将返回'(1 2 3)而不是{{} 1}}没有它,因为这是#t的工作原理。是否值得通过andmap的仪式取决于你对类型的看法。

答案 3 :(得分:1)

Racket允许您编写程序,就像编写数学表达式一样。 2组相等的数学表达式可以如下:

如果对于A中的每个x,有两组A和B相等,则有x B。

因此,首先您需要编写一个过程来告诉您项目是否是集合的一部分。

;procedure in? : Tells if an element x is in set S.
;If S is empty, then x is not in it, 
;if the first element of S is eq. to x then x is in it. 
;otherwise, check with next element.
(define in? 
    (lambda (x S) 
      (cond ((empty? S) #f)
            ((equal? (car S) x) #t)
            (else (in? x (cdr S)))
      )))

现在我们可以使用该程序判断两个列表是否相等。

;procedure equal-sets? : Tells if 2 sets are equal.
;Uses andmap as a for-each loop.
(define equal-sets?
    (lambda (A B)
         (andmap (lambda (x) (in? x B)) A) ) )

让我们知道任何疑问!

答案 4 :(得分:0)

本拉奇斯的list->set解决方案是最好的。

但是我们可以通过最小的更改来解决问题的解决方案:

(define (set-equal? list1 list2)
  (cond
    [(and (empty? list1) (empty? list2)) true]
    [(and (cons? list1) (empty? list2)) false]
    [(and (empty? list1) (cons? list2)) false]
    [(and (cons? list1) (cons? list2))
      (if (member (first list1) list2) 
          ; compare rest of list1 with rest of list2
          (set-equal? (rest list1) (remove (first list1) list2))
          ; if (first list1) is not a member of list2 then they are not equal
          #f)]))

现在可以了,但我们可以做得更好:

(define (set-equal? list1 list2)
  (cond
    [(and (empty? list1) (empty? list2)) true]
    [(and (cons? list1) (empty? list2)) false]
    [(and (empty? list1) (cons? list2)) false]
    [else ; the last condition always true when first 3 are not
      (and (member (first list1) list2) 
           (set-equal? (rest list1) 
                       (remove (first list1) list2)))]))

现在我们可以删除一些条件,并用cond替换if

(define (set-equal? list1 list2)
  (if (empty? list1)
      (empty? list2)
      (and (member (first list1) list2) 
           (set-equal? (rest list1)
                       (remove (first list1) list2)))))

注意:由于性能不佳,请勿在实际项目中使用此功能。