Advertisement
Guest User

Untitled

a guest
Jul 4th, 2019
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 7.09 KB | None | 0 0
  1. package objsets
  2.  
  3. import TweetReader._
  4.  
  5. /**
  6.   * A class to represent tweets.
  7.   */
  8. class Tweet(val user: String, val text: String, val retweets: Int) {
  9.   override def toString: String =
  10.     "User: " + user + "\n" +
  11.       "Text: " + text + " [" + retweets + "]"
  12. }
  13.  
  14. /**
  15.   * This represents a set of objects of type `Tweet` in the form of a binary search
  16.   * tree. Every branch in the tree has two children (two `TweetSet`s). There is an
  17.   * invariant which always holds: for every branch `b`, all elements in the left
  18.   * subtree are smaller than the tweet at `b`. The elements in the right subtree are
  19.   * larger.
  20.   *
  21.   * Note that the above structure requires us to be able to compare two tweets (we
  22.   * need to be able to say which of two tweets is larger, or if they are equal). In
  23.   * this implementation, the equality / order of tweets is based on the tweet's text
  24.   * (see `def incl`). Hence, a `TweetSet` could not contain two tweets with the same
  25.   * text from different users.
  26.   *
  27.   *
  28.   * The advantage of representing sets as binary search trees is that the elements
  29.   * of the set can be found quickly. If you want to learn more you can take a look
  30.   * at the Wikipedia page [1], but this is not necessary in order to solve this
  31.   * assignment.
  32.   *
  33.   * [1] http://en.wikipedia.org/wiki/Binary_search_tree
  34.   */
  35. abstract class TweetSet {
  36.  
  37.   /**
  38.     * This method takes a predicate and returns a subset of all the elements
  39.     * in the original set for which the predicate is true.
  40.     *
  41.     * Question: Can we implment this method here, or should it remain abstract
  42.     * and be implemented in the subclasses?
  43.     */
  44.   def filter(p: Tweet => Boolean): TweetSet = filterAcc(p, new Empty)
  45.  
  46.   /**
  47.     * This is a helper method for `filter` that propagetes the accumulated tweets.
  48.     */
  49.   def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet
  50.  
  51.   /**
  52.     * Returns a new `TweetSet` that is the union of `TweetSet`s `this` and `that`.
  53.     *
  54.     * Question: Should we implment this method here, or should it remain abstract
  55.     * and be implemented in the subclasses?
  56.     */
  57.   def union(that: TweetSet): TweetSet
  58.  
  59.   /**
  60.     * Returns the tweet from this set which has the greatest retweet count.
  61.     *
  62.     * Calling `mostRetweeted` on an empty set should throw an exception of
  63.     * type `java.util.NoSuchElementException`.
  64.     *
  65.     * Question: Should we implment this method here, or should it remain abstract
  66.     * and be implemented in the subclasses?
  67.     */
  68.   def mostRetweeted: Tweet
  69.  
  70.   /**
  71.     * Returns a list containing all tweets of this set, sorted by retweet count
  72.     * in descending order. In other words, the head of the resulting list should
  73.     * have the highest retweet count.
  74.     *
  75.     * Hint: the method `remove` on TweetSet will be very useful.
  76.     * Question: Should we implment this method here, or should it remain abstract
  77.     * and be implemented in the subclasses?
  78.     */
  79.   def descendingByRetweet: TweetList
  80.  
  81.   /**
  82.     * The following methods are already implemented
  83.     */
  84.  
  85.   /**
  86.     * Returns a new `TweetSet` which contains all elements of this set, and the
  87.     * the new element `tweet` in case it does not already exist in this set.
  88.     *
  89.     * If `this.contains(tweet)`, the current set is returned.
  90.     */
  91.   def incl(tweet: Tweet): TweetSet
  92.  
  93.   /**
  94.     * Returns a new `TweetSet` which excludes `tweet`.
  95.     */
  96.   def remove(tweet: Tweet): TweetSet
  97.  
  98.   /**
  99.     * Tests if `tweet` exists in this `TweetSet`.
  100.     */
  101.   def contains(tweet: Tweet): Boolean
  102.  
  103.   /**
  104.     * This method takes a function and applies it to every element in the set.
  105.     */
  106.   def foreach(f: Tweet => Unit): Unit
  107.  
  108.   def isEmpty: Boolean
  109. }
  110.  
  111. class Empty extends TweetSet {
  112.   def isEmpty = true
  113.  
  114.   def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = acc
  115.  
  116.   def union(that: TweetSet): TweetSet = that
  117.  
  118.   def mostRetweeted: Tweet = throw new java.util.NoSuchElementException
  119.  
  120.   def descendingByRetweet: TweetList = Nil
  121.  
  122.  
  123.   /**
  124.     * The following methods are already implemented
  125.     */
  126.  
  127.   def contains(tweet: Tweet): Boolean = false
  128.  
  129.   def incl(tweet: Tweet): TweetSet = new NonEmpty(tweet, new Empty, new Empty)
  130.  
  131.   def remove(tweet: Tweet): TweetSet = this
  132.  
  133.   def foreach(f: Tweet => Unit): Unit = ()
  134. }
  135.  
  136. class NonEmpty(elem: Tweet, left: TweetSet, right: TweetSet) extends TweetSet {
  137.  
  138.   def isEmpty = false
  139.  
  140.   def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet =
  141.     if (p(elem))
  142.       (left.filter(p) union right.filter(p)) incl elem
  143.     else
  144.       left.filter(p) union right.filter(p)
  145.  
  146.   // def union(that: TweetSet): TweetSet = left union right union that incl elem
  147.   // def union(that: TweetSet): TweetSet = left union right union (that incl elem)
  148.   def union(that: TweetSet): TweetSet = left union (right union (that incl elem))
  149.  
  150.   def mostRetweeted: Tweet = {
  151.     def max(a: Tweet, b: Tweet): Tweet = if (a.retweets > b.retweets) a else b
  152.  
  153.     var res = elem
  154.     if (!left.isEmpty) res = max(res, left.mostRetweeted)
  155.     if (!right.isEmpty) res = max(res, right.mostRetweeted)
  156.     res
  157.   }
  158.  
  159.   def descendingByRetweet: TweetList = new Cons(mostRetweeted, remove(mostRetweeted).descendingByRetweet)
  160.  
  161.   /**
  162.     * The following methods are already implemented
  163.     */
  164.  
  165.   def contains(x: Tweet): Boolean =
  166.     if (x.text < elem.text) left.contains(x)
  167.     else if (elem.text < x.text) right.contains(x)
  168.     else true
  169.  
  170.   def incl(x: Tweet): TweetSet = {
  171.     if (x.text < elem.text) new NonEmpty(elem, left.incl(x), right)
  172.     else if (elem.text < x.text) new NonEmpty(elem, left, right.incl(x))
  173.     else this
  174.   }
  175.  
  176.   def remove(tw: Tweet): TweetSet =
  177.     if (tw.text < elem.text) new NonEmpty(elem, left.remove(tw), right)
  178.     else if (elem.text < tw.text) new NonEmpty(elem, left, right.remove(tw))
  179.     else left.union(right)
  180.  
  181.   def foreach(f: Tweet => Unit): Unit = {
  182.     f(elem)
  183.     left.foreach(f)
  184.     right.foreach(f)
  185.   }
  186. }
  187.  
  188. trait TweetList {
  189.   def head: Tweet
  190.  
  191.   def tail: TweetList
  192.  
  193.   def isEmpty: Boolean
  194.  
  195.   def foreach(f: Tweet => Unit): Unit =
  196.     if (!isEmpty) {
  197.       f(head)
  198.       tail.foreach(f)
  199.     }
  200. }
  201.  
  202. object Nil extends TweetList {
  203.   def head = throw new java.util.NoSuchElementException("head of EmptyList")
  204.  
  205.   def tail = throw new java.util.NoSuchElementException("tail of EmptyList")
  206.  
  207.   def isEmpty = true
  208. }
  209.  
  210. class Cons(val head: Tweet, val tail: TweetList) extends TweetList {
  211.   def isEmpty = false
  212. }
  213.  
  214.  
  215. object GoogleVsApple {
  216.   val google = List("android", "Android", "galaxy", "Galaxy", "nexus", "Nexus")
  217.   val apple = List("ios", "iOS", "iphone", "iPhone", "ipad", "iPad")
  218.  
  219.   lazy val googleTweets: TweetSet = allTweets.filter(p => google.exists(x => p.text.contains(x)))
  220.   lazy val appleTweets: TweetSet = allTweets.filter(p => apple.exists(x => p.text.contains(x)))
  221.  
  222.   /**
  223.     * A list of all tweets mentioning a keyword from either apple or google,
  224.     * sorted by the number of retweets.
  225.     */
  226.   lazy val trending: TweetList = (googleTweets union appleTweets).descendingByRetweet
  227. }
  228.  
  229. object Main extends App {
  230.   // Print the trending tweets
  231.   GoogleVsApple.trending foreach println
  232. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement