第二次作业
这次作业做了大约两小时,大部分时间是花在了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")
}