【问题标题】:Scala set function斯卡拉集合函数
【发布时间】:2019-02-10 12:20:33
【问题描述】:

在斯坦福 Scala 课程中,我遇到了以下作业:

练习 1 – 集合为函数:

在本练习中,我们将集合表示为从 Ints 到 Booleans 的函数:

type Set = Int => Boolean

a) 编写一个函数“set”,它接受一个 Int 参数并返回一个包含该 Int 的 Set。

b) 编写一个“包含”函数,该函数接受一个 Set 和一个 Int 作为参数,如果 Int 在 Set 中则返回 true,否则返回 false。

c) 编写函数“union”、“intersect”和“minus”,以两个 Set 作为参数并返回一个 Set。

d) 你能写一个函数“子集”,它接受两个 Set 作为参数,如果第一个是第二个的子集则返回 true,否则返回 false?

abc 的解决方案相当简单:

def set(i: Int): Set = n => n == i

def contains(s: Set, i: Int) = s(i)

def union(a: Set, b: Set): Set = i => a(i) || b(i)

def intersect(a: Set, b: Set): Set = i => a(i) && b(i)

def minus(a: Set, b: Set): Set = i => a(i) && !b(i)

但是 d 有什么优雅的解决方案吗? 当然,严格来说,d 的答案是“是”,因为我可以这样写:

def subset(a: Set, b: Set) = Int.MinValue to Int.MaxValue filter(a) forall(b)

但这可能不是正确的方法。

【问题讨论】:

  • 我认为正确的方式。
  • 课程与斯坦福无关
  • @Seth 它来自斯坦福的课程,而不是当前的 Coursera 课程,尽管那里的第二个作业几乎相同。请注意,它没有 -bound/bound 提示,顺便说一句,它回答了我的问题。

标签: scala functional-programming set


【解决方案1】:

我认为不遍历所有整数是不可能的。对于伪证明,请查看所需的类型:

def subset: (a: Set, b: Set): Boolean

不知何故,当我们必须使用类型为Int => Boolean 的集合(ab)和整数相等(Int, Int) => Boolean 时,我们必须生成一个Boolean。从这些原语中,获得Boolean 值的唯一方法是从Int 值开始。由于我们手中没有任何特定的Int,因此唯一的选择是遍历所有这些。

如果我们有一个神奇的神谕,isEmpty: Set => Boolean,情况就会不同。

最后一个选项是编码“false”为空集,“true”为其他任何值,从而将所需类型更改为:

def subset: (a: Set, b: Set): Set

通过这种编码,逻辑“或”对应于集合并集操作,但我不知道逻辑“与”或“非”是否可以轻松定义。

【讨论】:

    【解决方案2】:

    我们有

    Set A = 
        Returns the intersection of the two given sets,
        the set of all elements that are both in `s` and `t`.
    
    Set B = 
        Returns the subset of `s` for which `p` holds.
    

    Set A 不等于 Set B

    def filter(s: Set, p: Int => Boolean): Set = intersect(s, p)
    

    【讨论】:

      【解决方案3】:

      我同意 Kipton Barros 的观点,您必须检查 Ints 的所有值,因为您想证明 forall x, a(x) implies b(x)

      关于它的优化,我可能会写:

        def subset(a: Set, b: Set) = Int.MinValue to Int.MaxValue exists(i => !a(i) || b(i))
      

      因为!a(i) || b(i) 等价于a(i) implies b(i)

      【讨论】:

      • 你从哪里得到这个函数“存在”?它是在某个地方定义的还是未定义的?
      • 表达式Int.MinValue to Int.MaxValue创建了一个Range类型,它继承自IterableLike、TraversableLike、TraversableOnce,最后继承自GenTraversableOnce,这就是定义函数exists的地方。查看scala-lang.org/api/current/…的文档
      • 谢谢,那天我好像瞎了眼,看到是那个范围的方法调用。
      【解决方案4】:

      稍后在 Coursera 练习中介绍了有界集,然后将 forall() 和 exists() 作为边界上的普遍和存在量词。 subset() 不在练习中,但与 forall 类似。这是我的子集()版本:

      // subset(s,p) tests if p is a subset of p returning true or false
      def subset(s: Set, p: Set): Boolean = {
        def iter(a: Int): Boolean = {
          if (a > bound) { true
          } else if (contains(p, a)) {
              if (contains(s, a)) iter(a + 1) else false
          } else iter(a+1)
        }
        iter(-bound)
      }
      

      【讨论】:

        【解决方案5】:

        这是另一个使用包含函数的版本:

        def union(s: Set, t: Set): Set = x => contains(s,x) || contains(t,x)
        
        def intersect(s: Set, t: Set): Set = x => contains(s,x) && contains(t,x)
        
        def diff(s: Set, t: Set): Set = x => contains(s,x) && !contains(t,x)
        
        def filter(s: Set, p: Int => Boolean): Set = x =>  contains(s, x) && p(x)
        

        【讨论】:

          【解决方案6】:

          如果有两个集合 A 和 B,则 A 与 B 相交是 A 和 B 的子集。数学证明:A ∩ B ⊆ A and A ∩ B ⊆ B。函数可以这样写:

          def filter(s: Set, p: Int => Boolean): Set = x => s(x) && p(x)
          

          或者

          def intersect(s: Set, t: Set): Set = x => s(x) && t(x)
          def filter(s: Set, p: Int => Boolean): Set = intersect(s,p)
          

          【讨论】:

          • 虽然该陈述是正确的,但它并没有提供和回答问题。
          • @mins 答案由 Ronak 给出。我只是想说两个集合的交集是这两个集合中的任何一个的子集。我也在添加确切的答案。
          猜你喜欢
          • 2021-02-10
          • 2014-06-15
          • 2020-07-03
          • 1970-01-01
          • 1970-01-01
          • 2011-09-16
          • 2016-01-31
          • 2017-10-23
          • 1970-01-01
          相关资源
          最近更新 更多