【问题标题】:Infinite loops? For what case do these loops occur?无限循环?在什么情况下会出现这些循环?
【发布时间】:2014-07-13 17:37:41
【问题描述】:

我已经在 coursera 上提交了我的 scala 作业,但是似乎有些测试失败了:

  Your solution achieved a testing score of 70 out of 110.
Below you can see a short feedback for every test that failed, indicating the reason
for the test failure and how many points you lost for each individual test.

[Test Description] filter: tweet with 321 retweets
[Observed Error] Test timeout: aborted after 40 seconds; Check for infinite loops!
  [exception was thrown] detailed error message in debug output section below
[Lost Points] 10

[Test Description] filter and union: tweets with 321 and 205 retweets
[Observed Error] Test timeout: aborted after 40 seconds; Check for infinite loops!
  [exception was thrown] detailed error message in debug output section below
[Lost Points] 10

[Test Description] filter and trending: tweets with 321 and 205 retweets
[Observed Error] Test timeout: aborted after 40 seconds; Check for infinite loops!
  [exception was thrown] detailed error message in debug output section below
[Lost Points] 10

[Test Description] trending: google and apple tweets
[Observed Error] Test timeout: aborted after 40 seconds; Check for infinite loops!
  [exception was thrown] detailed error message in debug output section below
[Lost Points] 10

我的问题是我无法想象我的功能会失败的任何情况。通过作业提供的标准测试运行没有问题。

这里是过滤器和联合函数:

  def union(that: TweetSet): TweetSet = (left.union(right)).union(that).incl(elem)
  val isEmpty = false

  def filter(p: Tweet => Boolean): TweetSet = filterAcc(p,new Empty)

  def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = {
    if(left.isEmpty && right.isEmpty) acc
    else if(p(elem)){ left.filterAcc(p,acc.incl(elem)).union(right.filterAcc(p,acc.incl(elem)))}
    else left.filterAcc(p,acc).union(right.filterAcc(p,acc))


  }

如果有人需要更好的调试,这里是完整的代码:

  package objsets

import common._
import TweetReader._

/**
 * A class to represent tweets.
 */
class Tweet(val user: String, val text: String, val retweets: Int) {
  override def toString: String =
    "User: " + user + "\n" +
    "Text: " + text + " [" + retweets + "]"
}

/**
 * This represents a set of objects of type `Tweet` in the form of a binary search
 * tree. Every branch in the tree has two children (two `TweetSet`s). There is an
 * invariant which always holds: for every branch `b`, all elements in the left
 * subtree are smaller than the tweet at `b`. The eleemnts in the right subtree are
 * larger.
 *
 * Note that the above structure requires us to be able to compare two tweets (we
 * need to be able to say which of two tweets is larger, or if they are equal). In
 * this implementation, the equality / order of tweets is based on the tweet's text
 * (see `def incl`). Hence, a `TweetSet` could not contain two tweets with the same
 * text from different users.
 *
 *
 * The advantage of representing sets as binary search trees is that the elements
 * of the set can be found quickly. If you want to learn more you can take a look
 * at the Wikipedia page [1], but this is not necessary in order to solve this
 * assignment.
 * 
 * [1] http://en.wikipedia.org/wiki/Binary_search_tree
 */
abstract class TweetSet {

  def greatestCurrent(soFar: Tweet):Tweet

  def iterateAndAddList(list: TweetList): TweetList

  def isEmpty: Boolean
  /**
   * This method takes a predicate and returns a subset of all the elements
   * in the original set for which the predicate is true.
   *
   * Question: Can we implment this method here, or should it remain abstract
   * and be implemented in the subclasses?
   */
  def filter(p: Tweet => Boolean): TweetSet

  /**
   * This is a helper method for `filter` that propagetes the accumulated tweets.
   */
  def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet

  /**
   * Returns a new `TweetSet` that is the union of `TweetSet`s `this` and `that`.
   *
   * Question: Should we implment this method here, or should it remain abstract
   * and be implemented in the subclasses?
   */
   def union(that: TweetSet): TweetSet;

  /**
   * Returns the tweet from this set which has the greatest retweet count.
   *
   * Calling `mostRetweeted` on an empty set should throw an exception of
   * type `java.util.NoSuchElementException`.
   *
   * Question: Should we implment this method here, or should it remain abstract
   * and be implemented in the subclasses?
   */
  def mostRetweeted: Tweet = ???

  /**
   * Returns a list containing all tweets of this set, sorted by retweet count
   * in descending order. In other words, the head of the resulting list should
   * have the highest retweet count.
   *
   * Hint: the method `remove` on TweetSet will be very useful.
   * Question: Should we implment this method here, or should it remain abstract
   * and be implemented in the subclasses?
   */
  def descendingByRetweet: TweetList


  /**
   * The following methods are already implemented
   */

  /**
   * Returns a new `TweetSet` which contains all elements of this set, and the
   * the new element `tweet` in case it does not already exist in this set.
   *
   * If `this.contains(tweet)`, the current set is returned.
   */
  def incl(tweet: Tweet): TweetSet

  /**
   * Returns a new `TweetSet` which excludes `tweet`.
   */
  def remove(tweet: Tweet): TweetSet

  /**
   * Tests if `tweet` exists in this `TweetSet`.
   */
  def contains(tweet: Tweet): Boolean

  /**
   * This method takes a function and applies it to every element in the set.
   */
  def foreach(f: Tweet => Unit): Unit
}

class Empty extends TweetSet {
  def greatestCurrent(soFar: Tweet):Tweet = new Tweet("a","b",-1)
  def iterateAndAddList(list: TweetList): TweetList = list
  def descendingByRetweet() = Nil
  def union(that: TweetSet): TweetSet = that  
  def isEmpty = true

  def filter(p: Tweet=> Boolean): TweetSet = new Empty()

  def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = new Empty()


  /**
   * The following methods are already implemented
   */

  def contains(tweet: Tweet): Boolean = false

  def incl(tweet: Tweet): TweetSet = new NonEmpty(tweet, new Empty, new Empty)

  def remove(tweet: Tweet): TweetSet = this

  def foreach(f: Tweet => Unit): Unit = ()
}

class NonEmpty(elem: Tweet, left: TweetSet, right: TweetSet) extends TweetSet {

  def descendingByRetweet = {






    iterateAndAddList(Nil)

  }

      def iterateAndAddList(list: TweetList): TweetList = {

      val current: Tweet = greatestCurrent(new Tweet("a","b",-1))
      if(current.retweets != -1){
      this.remove(current).iterateAndAddList(list.add(current))
      }else list

    }

    def greatestCurrent(soFar: Tweet):Tweet = {
      if(left.isEmpty && right.isEmpty) soFar
      else{
          if(elem.retweets < soFar.retweets) { mostPopular(left.greatestCurrent(soFar),right.greatestCurrent(soFar))     }
          else if(elem.retweets > soFar.retweets){ mostPopular(left.greatestCurrent(elem),right.greatestCurrent(elem))   }
          else { mostPopular(left.greatestCurrent(soFar),right.greatestCurrent(soFar))   }
      }
    }

    def mostPopular(left: Tweet,right: Tweet):Tweet = {
      if(left.retweets > right.retweets) left
      else if(right.retweets > left.retweets) right
      else left
    }

  def union(that: TweetSet): TweetSet = (left.union(right)).union(that).incl(elem)
  val isEmpty = false

  def filter(p: Tweet => Boolean): TweetSet = filterAcc(p,new Empty)

  def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = {
    if(left.isEmpty && right.isEmpty) acc
    else if(p(elem)){ left.filterAcc(p,acc.incl(elem)).union(right.filterAcc(p,acc.incl(elem)))}
    else left.filterAcc(p,acc).union(right.filterAcc(p,acc))


  }


  /**
   * The following methods are already implemented
   */

  def contains(x: Tweet): Boolean =
    if (x.text < elem.text) left.contains(x)
    else if (elem.text < x.text) right.contains(x)
    else true

  def incl(x: Tweet): TweetSet = {
    if (x.text < elem.text) new NonEmpty(elem, left.incl(x), right)
    else if (elem.text < x.text) new NonEmpty(elem, left, right.incl(x))
    else this
  }

  def remove(tw: Tweet): TweetSet =
    if (tw.text < elem.text) new NonEmpty(elem, left.remove(tw), right)
    else if (elem.text < tw.text) new NonEmpty(elem, left, right.remove(tw))
    else left.union(right)

  def foreach(f: Tweet => Unit): Unit = {
    f(elem)
    left.foreach(f)
    right.foreach(f)
  }
}

谁能向我解释为什么我的代码失败了?我不是在寻找烘焙代码,因为这会违反 coursera 荣誉代码。对于我的代码有什么问题的任何反馈,我将不胜感激。

注意:作业随附的标准测试运行良好。问题是提交时。也请不要给我烘焙代码

【问题讨论】:

  • 你的联合函数太慢了(不是无限的);尝试另一种方式来实现它。 p.s.尝试使用filterAcc
  • 我可以再提交 3 次。你确定这是对的吗?这只是一个持续时间不超过 0.000001 秒的通话
  • 一个一般建议:由于您的数据结构是不可变的,您可以将Empty 声明为object。这可以防止创建许多基本上具有完全相同的信息和行为的Empty-Objects。
  • 是的,我在一年多前完成了这项任务;所以有同样的问题......但是这里没有这样的问题;我做了和你一样的union函数,但是很慢;这个函数是一个非常非常...非常慢,尝试另一个变种。
  • Coursera 论坛上已经广泛讨论了这个问题。我不知道为什么你认为有必要在这里发布你的代码,尤其是——正如其他人已经指出的——这明显违反了荣誉代码?

标签: scala debugging infinite-loop


【解决方案1】:

您的联合实施效率太低。它可以很容易地被重构以提高效率。它仍然可以只使用对 union 和 incl 方法的递归调用,但不是按照您的顺序。

我怀疑这不是一个真正的无限循环,而是对于 Coursera 测试而言运行时间过长。这就是为什么您的本地较小的测试用例可以通过的原因。

【讨论】:

  • @Bula - 顺便说一句,Coursera 荣誉守则要求您不要与他人分享您的解决方案。在此处发布您的所有代码可能会被视为违反荣誉代码。我可能错了,但如果您想确保自己符合荣誉准则,为什么不在 Coursera 的课程论坛上复制并发布这个确切的问题呢?我相信您会收到有关您的问题的反馈,以及这是否违反荣誉准则的指示。 help.coursera.org/customer/portal/articles/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 2017-01-31
  • 1970-01-01
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 2013-06-17
相关资源
最近更新 更多