我有一个家庭作业问题,要求我告诉两套内容是否相等,无论顺序如何。
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中的数据,如果有相同的数据,则从两个列表中删除它。然后继续检查,直到两个列表都为空(给出为真)或者一个为空,一个仍然有数据(输出为假)。问题是,我不知道如何编写代码。
有人能给我一些关于如何解决这个问题的提示吗?
答案 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)))
两组A
和B
之间的平等定义是:
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)
#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)))))
and
短路。
(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)))))
注意:由于性能不佳,请勿在实际项目中使用此功能。