第二次作业
这次作业做了大约两小时,大部分时间是花在了map和exists上
其中map,我一开始的答案是
def map(s: Set, f: Int => Int): Set = {
x=>s(f(x)) // ERROR
}
但是这样的话,因果关系就反掉了,假如s = {9}, f: x=>x/3
那么最终的返回值其实是x=>s(x/3),也就是x/3要在s这个Set里存在,也就是说,返回值是{27}
所以最后仍然用了遍历,每当有和x/3相等的值时,就加入集合,最后返回这个集合
exists
挺难的,而且我觉得,就正如题目的Hint所说:
this assignment needs more thinking (whiteboard, pen and paper) than coding ;-).
因为这道exists其实不是考察编程能力,而是分析能力
我最后的思路是想到了数学中的集合运算,因为题目的要求是exists必须用到forall函数,可是我实在想不出有什么原因要用到它
后来把思路拓展到数学集合运算,发现forall(x,y)其实就是判断前者x是否是后者y的子集
而exists就是算出两个集合有没有非空公共子集,但是有个问题:空集是任何集合的子集,不能直接用interfact
最后苦思冥想想到:
exists 等价于
两个集合x,y有非空公共子集,等价于
两个集合x,y没有非空公共子集的取反,
等价于x集合取反是y的子集 逻辑与 && y
集合取反是x的子集
但是一个集合的取反要靠辅助函数构造一个全集,然后diff(全集,某个集合) 实现,于是最后代码如下:
!(forall(s, diff(
ful
, p)) && forall(p, diff(
ful
, s)))
https://class.coursera.org/progfun-003/assignment/view?assignment_id=3
package
funsets
import
common._
/**
* 2. Purely Functional Sets.
*/
object
FunSets {
/**
* We represent a set by its characteristic function, i.e.
* its `contains` predicate.
*/
type
Set = Int => Boolean
/**
* Indicates whether a set contains a given element.
*/
def
contains(s: Set, elem: Int): Boolean = s(elem)
/**
* Returns the set of the one given element.
*/
def
singletonSet(elem: Int): Set = {
x: Int => x == elem
}
/**
* Returns the union of the two given sets,
* the sets of all elements that are in either `s` or `t`.
*/
def
union(s: Set, t: Set): Set = {
x: Int => s(x) || t(x)
}
/**
* Returns the intersection of the two given sets,
* the set of all elements that are both in `s` and `t`.
*/
def
intersect(s: Set, t: Set): Set = {
x: Int => s(x) && t(x)
}
/**
* Returns the difference of the two given sets,
* the set of all elements of `s` that are not in `t`.
*/
def
diff(s: Set, t: Set): Set = {
x: Int => s(x) && !t(x)
}
/**
* Returns the subset of `s` for which `p` holds.
*/
def
filter(s: Set, p: Int => Boolean): Set = {
x: Int => s(x) && p(x)
}
/**
* The bounds for ` forall` and `exists` are +/- 1000.
*/
val
bound
=
1000
/**
* Returns whether all bounded integers within `s` satisfy `p`.
*/
def
forall(s: Set, p: Int => Boolean): Boolean = {
/**
* 1. Consider p: Int => Boolean as a Set
* 2. Consider function as an object
*/
def
iter(a: Int): Boolean = {
if
(a >
bound
)
true
else
if
(s(a) && !p(a))
false
else
iter(a +
1
)
}
iter(-
bound
)
}
/**
* Returns whether there exists a bounded integer within `s`
* that satisfies `p`.
*/
def
exists(s: Set, p: Int => Boolean): Boolean = {
def
iter(a: Int, set: Set): Set = {
if
(a >
bound
) set
else
iter(a +
1
, union(set, singletonSet(a)))
}
val
ful
= iter(-
bound
,
Set
())
!(forall(s, diff(
ful
, p)) && forall(p, diff(
ful
, s)))
}
/**
* Returns a set transformed by applying `f` to each element of `s`.
*/
def
map(s: Set, f: Int => Int): Set = {
def
iter(a: Int, set: Set): Set = {
if
(a >
bound
) set
else
if
(s(a)) iter(a +
1
, union(set, singletonSet(f(a))))
else
iter(a +
1
, set)
}
iter(-
bound
,
Set
())
// x=>s(f(x)) // ERROR
}
/**
* Displays the contents of a set
*/
def
toString(s: Set): String = {
val
xs
=
for
(
i
<- -
bound
to
bound
if
contains(s, i))
yield
i
xs
.mkString(
"{"
,
","
,
"}"
)
}
/**
* Prints the contents of a set on the console.
*/
def
printSet(s: Set) {
println(toString(s))
}
}
new
TestSets {
val
r
= union(
s1
,
s3
)
val
s
= union(
s1
,
s2
)
val
t
= union(
s1
,
s2
)
assert(forall(
s
,
t
),
"forall 1"
)
assert(!forall(
s
,
r
),
"forall 2"
)
assert(exists(
s
,
r
),
"exists 1"
)
val
sMap
= singletonSet(
9
)
assert(exists(map(
sMap
, x => x /
3
),
s3
),
"exists 2"
)
assert(exists(
s1
,
s1
),
"exists 3"
)
assert(!exists(
s2
,
r
),
"exists 4"
)
}