CSE 11 Programming Assignment 4
Due Date: Tuesday, October 26, 10:00PM Pacific Time
Learning Goals
- Practice working with interfaces
- Practice with creating objects and classes
You can come to lab hours, in-person or remote, to get a pre-grading check-off for this assignment, instructions here:
https://docs.google.com/document/d/1KbcovlvOfkrehxe7lXzKr63gVZzfP9HPbHYXh2l6RNI/edit?usp=sharing
Different assignments in this course have different collaboration policies. On this assignment, you can collaborate with anyone in the course, but you must create your own memory diagrams and descriptions for answers. In your submission, give credit to all students and course staff who helped you with this assignment by noting their name and how you used their ideas or work. Note that using someone’s work without giving credit to them is a violation of academic integrity.
You can get the starter code at
https://github.com/ucsd-cse11-f21/cse11-pa4-starter
Tweets
In a file Tweets.java, write an interface called Tweet with four
methods:
public boolean isReplyTo(Tweet other);public int totalLikes();public String allAuthors();public boolean textAppearsOnThread(String text);
Then, write three classes:
-
User, just as in PA2 TextTweet, implementsTweetand has three fields:contents, aStringlikes, an intauthor, aUser
This class should implement the methods as follows:
isReplyToshould returnfalseno matter what Tweet it receivestotalLikesshould return the number of likes on thisTextTweetobjectallAuthorsshould return the username of the author of thisTextTweettextAppearsOnThreadshould returntruewhen the given text is in the contents of thisTextTweet,falseotherwise.
ReplyTweet, which should implementTweetand has four fields:contents, aStringlikes, an intauthor, aUserreplyTo, aTweet
This class should implement the methods as follows:
isReplyToshould returntrueif thereplyToof thisReplyTweetis the givenTweet, as compared by==.totalLikesshould return the total number of likes on thisReplyTweetobject plus thetotalLikesof itsreplyToTweet. For example, a thread of tweets that is 4 replies long should sum the likes on all 4 of those tweets.allAuthorsshould return the username of the author of thisReplyTweetfollowed by a semicolon (";"), followed byallAuthorsof itsreplyToTweet.textAppearsOnThreadshould returntruewhen the given text appears in thecontentsof thisReplyTweet, or if it appears on the thread of thereplyToTweet.
Add constructors as appropriate to initialize the fields on objects of these classes.
Some tests you can start with are here; you can copy them to your program as you implement the various methods.
User joe = new User("joepolitz", "Joe Gibbs Politz", 999);
User greg = new User("gregory_miranda", "Greg Miranda", 9999);
User rachel = new User("Rachel__Lim", "Rachel Lim", 1000000);
Tweet t1 = new TextTweet(this.joe, "Java 17 has a cool feature called records", 77);
Tweet t2 = new ReplyTweet(this.greg, "Hmm I wonder if we could use it for CSE11", 12, this.t1);
Tweet t3 = new ReplyTweet(this.greg, "Thought about this more, probably not yet, too new.", 73, this.t2);
Tweet t4 = new ReplyTweet(this.joe, "Yeah, good point. Maybe in 2022.", 10, this.t3);
Tweet t5 = new ReplyTweet(this.rachel, "Yeah... I don't want to rewrite the book right this minute", 1005, this.t2);
void testIsReplyTo(Tester t) {
t.checkExpect(this.t1.isReplyTo(this.t2), false);
t.checkExpect(this.t2.isReplyTo(this.t1), true);
t.checkExpect(this.t5.isReplyTo(this.t2), true);
t.checkExpect(this.t2.isReplyTo(this.t2), false);
t.checkExpect(this.t4.isReplyTo(this.t3), true);
}
void testTotalLikes(Tester t) {
t.checkExpect(this.t5.totalLikes(), 1005 + 12 + 77);
t.checkExpect(this.t4.totalLikes(), 10 + 73 + 12 + 77);
t.checkExpect(this.t1.totalLikes(), 77);
}
void testAllAuthors(Tester t) {
t.checkExpect(this.t1.allAuthors(), "joepolitz");
t.checkExpect(this.t2.allAuthors(), "gregory_miranda;joepolitz");
t.checkExpect(this.t3.allAuthors(), "gregory_miranda;gregory_miranda;joepolitz");
t.checkExpect(this.t5.allAuthors(), "Rachel__Lim;gregory_miranda;joepolitz");
}
void testTextAppearsOnThread(Tester t) {
t.checkExpect(this.t1.textAppearsOnThread("joepolitz"), false);
t.checkExpect(this.t1.textAppearsOnThread("2022"), false);
t.checkExpect(this.t1.textAppearsOnThread("cool"), true);
t.checkExpect(this.t4.textAppearsOnThread("wonder"), true);
t.checkExpect(this.t4.textAppearsOnThread("Java"), true);
t.checkExpect(this.t4.textAppearsOnThread("rewrite"), false);
t.checkExpect(this.t4.textAppearsOnThread("2022"), true);
}
Additional Testing and Exploration
You must also add your own tests. Construct your own (made-up or real) Tweet thread with at least 3 different authors and at least 5 different Tweets, and write at least 2 additional tests for each method – try to think of cases we may have not thoroughly tested in what’s provided.
Put these in an easily-found area of the ExamplesTweets to help us review your
code; don’t add them to the existing methods we provided.
Numbers
This code will go in the file Numbers.java, any tests in a class called
ExamplesNumbers that you add to that file.
We saw in our reading that representing fractional numbers like 0.6 with
doubles can be fraught. Some languages and libraries do support exact
fractions, and we can implement classes that act like them in Java. We won’t
be able to use the built-in + and * operators, because these are only
defined for numbers and strings, but we can define methods for the operations
we care about. We can represent numbers with an interface:
interface Number {
int numerator();
int denominator();
Number add(Number other);
Number multiply(Number other);
String toText();
double toDouble();
}
Your task is to create two classes that implement the interface above. One
should be called WholeNumber and represent whole integers (including
negative integers). The other should be called Fraction and represent mixed
numbers (including negative mixed numbers).
WholeNumber should have:
- A field
int nand a constructor that takes a singleint - An implementation of all the methods above.
numeratorshould return the value ofndenominatorshould return1addshould return a newNumberthat represents adding this whole number to the one provided as an argument. Note that the argument could be either aFractionor aWholeNumbermultiplyshould return a newNumberthat represents multiplying this whole number to the one provided as an argument. Note that the argument could be either aFractionor aWholeNumbertoTextshould return the value ofnas aString, so ifnis500, it should return"500"toDoubleshould return the value ofnas adouble
Fraction should have:
- A field
int nrepresenting the numerator - A field
int drepresenting the denominator - An implementation of all the methods above:
numeratorshould return the value ofndenominatorshould return the value ofdaddshould return a newNumberthat represents adding this fraction to the one provided as an argument. Note that the argument could be either aFractionor aWholeNumbermultiplyshould return a newNumberthat represents multiplying this fraction by the one provided as an argument. Note that the argument could be either aFractionor aWholeNumbertoTextshould return aStringin the format"n/d"wherenanddare the corresponding fields. So ifnanddwere1and2, this should be"1/2"toDoubleshould return the value ofn/das adouble. So ifnis 1 anddis 2, this should return0.5
A reminder about arithmetic and fractions:
\[n = \frac{n}{1}\] \[\frac{n}{d_1} + \frac{m}{d_2} = \frac{d_1m + d_2n}{d_1d_2}\] \[\frac{n}{d_1} \cdot \frac{m}{d_2} = \frac{nm}{d_1d_2}\]Some example tests that you can use are below. You can copy-paste these into your solution as you implement the various methods. All of these tests must pass on your implementation.
Number n1 = new WholeNumber(5);
Number n2 = new WholeNumber(7);
Number n3 = new Fraction(7, 2);
Number n4 = new Fraction(1, 2);
void testAdd(Tester t) {
t.checkExpect(this.n1.add(this.n2).toDouble(), 12.0);
t.checkExpect(this.n1.add(this.n3).toDouble(), 5 + 7.0/2.0);
t.checkExpect(this.n3.add(this.n3).toDouble(), 7.0);
}
void testMultiply(Tester t) {
t.checkExpect(this.n1.multiply(this.n4).toDouble(), 2.5);
t.checkExpect(this.n3.multiply(this.n4).toDouble(), 7.0/4.0);
}
void testNumDem(Tester t) {
t.checkExpect(this.n3.numerator(), 7);
t.checkExpect(this.n1.numerator(), 5);
t.checkExpect(this.n4.denominator(), 2);
t.checkExpect(this.n2.denominator(), 1);
}
void testToString(Tester t) {
t.checkExpect(this.n4.toText(), "1/2");
t.checkExpect(this.n3.toText(), "7/2");
t.checkExpect(this.n2.toText(), "7");
}
Exploration
At the end of the ExamplesNumbers class in a place marked clearly with a
comment that says // Exploration, write code to perform four calculations:
- The result of
0.1 + 0.2 + 0.3using built-indoublearithmetic in Java - The result of
0.1 + (0.2 + 0.3)using built-indoublearithmetic in Java - The result of (1) using your exact fractions, showing the result via
toText() - The result of (2) using your exact fractions, showing the result via
toText()
Submission
Then you will submit all of your files to the pa4 assignment on Gradescope:
Numbers.javanumber-transcript.txtTweets.javatweet-transcript.txt
Tests and exploration sections will be graded manually. In addition, we may give you feedback on any part of the code, including automatically graded parts, that we want you to respond to after grading.
Extra Challenges (not for credit)
Challenge: Many fractions, like \(2/4\) or
\(27/6\), are not in their simplest form. Make it so that the constructor for
Fraction always creates a fraction object with numerator and denominator in
their most reduced form.
Challenge: Create a ReplyTweet that is a reply
to itself. Do you think this is possible on Twitter?
Challenge: Add a method Tweet mostPopularInThread()
for Tweet that returns the Tweet in the thread with the most likes.
Challenge: The implementation of numbers above is
limited by having ints as the underlying representation; we can’t represent
certain large whole numbers. Using long makes things a bit better, but has its
own limits. Change the classes so that the size of number you can represent is
limited only by the memory in your computer.
Challenge: On Twitter, we can think of the thread “before” a Tweet by following what it replied to, which is what we’ve modeled. We can also think about the thread(s) “after” a Tweet, where we go from the first Tweet to its replies. How could we model this latter case?
Schedule
Calendar
Syllabus
Questions
Material
Assignments
Help Hours