Created
June 24, 2015 09:27
-
-
Save Hajto/e6e9d41f902710ca7078 to your computer and use it in GitHub Desktop.
objesets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 + "]" | |
} | |
abstract class TweetSet { | |
/** | |
* 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 = filterAcc(p, new Empty) | |
/** | |
* 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 | |
def mostRetweetedAcc(currentMost: Tweet): 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 isEmpty: Boolean | |
def descendingByRetweet: TweetList = { | |
if (isEmpty) | |
Nil | |
else { | |
val most = mostRetweeted | |
new Cons(most, remove(most).descendingByRetweet) | |
} | |
} | |
def incl(tweet: Tweet): TweetSet | |
def remove(tweet: Tweet): TweetSet | |
def contains(tweet: Tweet): Boolean | |
def foreach(f: Tweet => Unit): Unit | |
} | |
class Empty extends TweetSet { | |
def isEmpty = true | |
def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = acc | |
override def union(that: TweetSet): TweetSet = that | |
override def mostRetweeted: Tweet = throw new NoSuchElementException | |
def mostRetweetedAcc(currentMost: Tweet) = currentMost | |
/** | |
* 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 filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = { | |
if (p(elem)) | |
left.filterAcc(p, right.filterAcc(p, acc.incl(elem))) | |
else | |
left.filterAcc(p, right.filterAcc(p, acc)) | |
} | |
/** | |
* 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? | |
*/ | |
override def mostRetweeted: Tweet = mostRetweetedAcc(elem) | |
override def mostRetweetedAcc(currentMost: Tweet) = { | |
println(currentMost.retweets) | |
def test(first: Tweet, second: Tweet): Tweet = | |
if (first.retweets > second.retweets) | |
first | |
else | |
second | |
val leftMost = test(left.mostRetweetedAcc(currentMost), currentMost) | |
println(leftMost.retweets) | |
test(leftMost, right.mostRetweetedAcc(leftMost)) | |
} | |
/** | |
* 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? | |
*/ | |
override def isEmpty: Boolean = false | |
override def union(that: TweetSet): TweetSet = { | |
((left union right) union that) incl elem | |
} | |
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) | |
} | |
} | |
trait TweetList { | |
def head: Tweet | |
def tail: TweetList | |
def isEmpty: Boolean | |
def foreach(f: Tweet => Unit): Unit = | |
if (!isEmpty) { | |
f(head) | |
tail.foreach(f) | |
} | |
} | |
object Nil extends TweetList { | |
def head = throw new java.util.NoSuchElementException("head of EmptyList") | |
def tail = throw new java.util.NoSuchElementException("tail of EmptyList") | |
def isEmpty = true | |
} | |
class Cons(val head: Tweet, val tail: TweetList) extends TweetList { | |
def isEmpty = false | |
} | |
object GoogleVsApple { | |
val google = List("android", "Android", "galaxy", "Galaxy", "nexus", "Nexus") | |
val apple = List("ios", "iOS", "iphone", "iPhone", "ipad", "iPad") | |
println("Zaczynam filtrowanie") | |
lazy val googleTweets: TweetSet = TweetReader.allTweets.filter(t => google.exists(p => t.text.contains(p))) | |
println(googleTweets.mostRetweeted.user) | |
lazy val appleTweets: TweetSet = TweetReader.allTweets.filter(t => apple.exists(p => t.text.contains(p))) | |
println(appleTweets.mostRetweeted.user) | |
/** | |
* A list of all tweets mentioning a keyword from either apple or google, | |
* sorted by the number of retweets. | |
*/ | |
lazy val trending: TweetList = (googleTweets union appleTweets).descendingByRetweet | |
} | |
object Main extends App { | |
// Print the trending tweets | |
println("Poszlo") | |
GoogleVsApple.trending foreach println | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment