Advertisement
jules0707

Tweet

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