Pertaining to Array Lists and the toString Method - java

I am currently in a Java AP Computer Science class and we have been required to complete an activity that can do the following:
The class TransactionHistory is used to keep track of a sequence of Transactions. Complete the following definition for this class by providing the body of the toString method, which returns a multiline String consisting of the output from the toString method of each Transaction, each on a new line. (Recall that a String may be broken into multiple lines by including "\n".)
Be careful, though, to ensure that your toString method does not return a String that ends with a newline character. To help you with this, we provide (behind the scenes) a showNewlines method for you to use when testing your toString method. Examine the code inserted by the provided test cases to see how it may be used.
So far, I have the following code:
public class TransactionHistory extends ArrayList<Transaction>
{
public String toString()
{
for (Transaction t : this) {
return t.toString();
}
return "";
}
}
And this is one of the test cases that we are required to use:
public static void main( String[] args )
{
TransactionHistory th = new TransactionHistory();
th.add( new Deposit( 100.0, "10:15", "10/23/2007" ) );
th.add( new Deposit( 2.35, "11:05", "9/21/2007" ) );
th.add( new Withdrawal( 50.0, "2:24", "11/1/2007" ) );
System.out.println( showNewlines( th.toString() ) );
}
With the code that I have currently, all it is capable of doing is printing out the first line of transactions.
Here is what is printed out:
Deposit 100.0 10:15 10/23/2007
How would I go about making the code print out all of the transactions that were added?
Thank you, all help is appreciated.

Your return statement is breaking your loop as it already returns the first Transaction:
for (Transaction t : this) {
return t.toString();
}
Use a StringBuilder to append each, then return StringBuilder#toString()
be careful, the problem indicates that your toString() DOES NOT RETURN THE STRING THAT ENDS WITH A NEWLINE CHARACTER which is a different story in itself.
substring(int beginIndex, int endIndex) and lastIndexOf(String str) should take care of that.
String a = "foo\nbar\n";
System.out.println(a.substring(0, a.lastIndexOf("\n")));
Hope this helps.

Related

how many time the characters of string are to be found in another string

my professor gave me an exercise to find how many time the characters of string called "filter" are to be found in a second string called "query".
before I begin I am java noob and English isnt my native language.
example:
String filter="kjasd";
String query="kjg4t";
Output:2
getting how many times a char has been found in another string isnt my problem but the problem that the professor gave us some rules to stick with:
class filter. The class must be the following public
Provide interfaces:
public Filter (String letters) (→ Constructor of class)
The string representing the filter should be stored in the letters string
public boolean contains (char character)
Returns true if the passed character is contained in the query string, otherwise false
-public String toString ()
Returns an appropriate string representation of the class (just to be clear I have no clue about what does he means with this one!)
To actually determine the occurrences of the filter in the query, another class QueryResolver is to be created.
The class should be able to be used as follows:
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
the filter and the query are given by the user.
(i couldnt understand this one! )The methods "where" and "matches" configure the "QueryResolver" to include a subsequent call of "count" the calculation based on the previously passed variables
"query" and "filter" performs.
The count method should use the filter's previously-created method.
The modifier static is not allowed to use!
I dunno if he means that we cant use static {} or we cant use public (static) boolean contains (char character){}
we are not allowed to use void
so the problems that encountered me
- I can not pass a char to the method contains as long as it is not static.
error "Non-static variable can not be referenced from a static context"
i did not understand what i should do with the method toStirng!
what I've done so far:
Approach Nr 1:
so I just wrote everything in the main method to check whether the principle of my code works or not and then I wanted to create that whole with constructor and other methods but unfortunately I did not succeed.
Approach Nr 2:
then I tried to write the code in small mthoden as in the exercise but I did not succeed !.
in both aprroaches i violated the exercise rules but i cant seem to be able to do it alone thats why i posted the question here.
FIRST APPROACH:
public class filter{
public filter(String letters) {
//constructor of the class
String filter;
int count;
}
public boolean contains (char character){
/*Subprogram without static!
*the problem that I can't pass any char to this method if it wasn't static
*and I will get the following error"Non-static variable cannot be referenced from a static context"
*I understand why I'm getting the error but I don't know how to get around it X( */
return true ;
}
public String toString (){
/*he told us to include it in the program but honestly, I don't know what shall I write in it -_-
*I make it to null because you have to return something and I don't know what to do yet
*so, for now, I let it null. */
return null;
}
public static void main(String[] args) {
Scanner in =new Scanner (System.in);
System.out.println("please enter the query string! ");
String query= in.next();
System.out.println("please enter the filter stirng!");
String filter= in.next();
System.out.println("the query string is : [" + query+ "]");
System.out.println("the filter string is : [" + filter+ "]");
int count=0;
// I initialized it temporarily because I wanted to print it!
//later I need to use it with the boolean contains as a public method
boolean contains=false;
//to convert each the query and the filter strings to chars
char [] tempArray=query.toCharArray();
char [] tempArray1=filter.toCharArray();
//to iterate for each char in the query string!
for (int i = 0; i < tempArray.length; i++) {
char cc = tempArray[i];
//to iterate for each char in the filter string!
for (int j = 0; j < tempArray1.length; j++) {
// if the value in the filter string matches the value in the temp array then increment the counter by one!
if(tempArray1[j] == cc){
count++;
contains=true;
}
}
}
System.out.println("the characters of the String ["+filter+"] has been found in the forworded string ["+query+"] exactly "+count+" times!" );
System.out.println("the boolean value : "+ contains);
in.close();
}
}
SECOND APPROACH
- But here too I violated the rules of the task quite brutally :(
- First, I used void and did not use the tostring method.
- Second, I did not use a constructor.
- I did not add comments because that's just the same principal as my first attempt.
public class filter2 {
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
System.out.println("enter the filter string:");
String filterStr=in.next();
System.out.println("enter the query string:");
String querystr =in.next();
Filter(filterStr, querystr);
in.close();
}
public static void Filter(String filterstr , String querystr){
char [] tempArray1 = filterstr.toCharArray();
contains(tempArray1, querystr);
}
public static void contains(char[]tempArray1, String querystr){
boolean isThere= false ;
int counter=0;
char [] tempArray = querystr.toCharArray();
for (int i = 0; i < tempArray.length; i++) {
char cc = tempArray[i];
for (int j = 0; j < tempArray1.length; j++) {
if(tempArray1[j] == cc){
counter++;
isThere=true;
}
}
}
System.out.println("the letters of the filter string has been found in the query string exactly "+counter+" times!\nthus the boolean value is "+isThere);
}
/*
* sadly enough i still have no clue what is meant with this one nor whatshall i do
* public String toString (){
* return null;
* }
*
*/
}
Few hints and advice would be very useful to me but please demonstrate your suggestions in code because sometimes it can be difficult for me to understand what you mean by the given advice. ;)
Thank you in advance.
(sorry for the gramatical and the type mistakes; english is not my native language)
As already mentioned, it is important to learn to solve those problems yourself. The homework is not for punishment, but to teach you how to learn new stuff on your own, which is an important trait of a computer scientist.
Nonetheless, because it seems like you really made some effort to solve it yourself already, here is my solution, followed by some explanation.
General concepts
The first thing that I feel like you didn't understand is the concept of classes and objects. A class is like a 'blueprint' of an object, and the object is once you instanciated it.
Compared with something like a car, the class would be the description how to build a car, and the object would be a car.
You describe what a class is with public class Car { ... }, and instanciate an object of it with Car myCar = new Car();.
A class can have methods(=functions) and member variables(=data).
I just repeat those concepts because the code that you wrote looks like you didn't fully understand that concept yet. Please ask some other student who understood it to help you with that.
The Filter class
public class Filter{
String letters;
public Filter(String letters) {
this.letters = letters;
}
public boolean contains (char character){
for(int i = 0; i < letters.length(); i++) {
if(letters.charAt(i) == character)
return true;
}
return false;
}
public String toString (){
return "Filter(" + letters + ")";
}
}
Ok, let's brake that down.
public class Filter{
...
}
I guess you already got that part. This is where you describe your class structure.
String letters;
This is a class member variable. It is unique for every object that you create of that class. Again, for details, ask other students that understood it.
public Filter(String letters) {
this.letters = letters;
}
This is the constructor. When you create your object, this is the function that gets called.
In this case, all it does is to take an argument letters and stores it in the class-variable letters. Because they have the same name, you need to explicitely tell java that the left one is the class variable. You do this by adding this..
public boolean contains (char character){
for(int i = 0; i < letters.length(); i++) {
if(letters.charAt(i) == character)
return true;
}
return false;
}
This takes a character and looks whether it is contained in this.letters or not.
Because there is no name collision here, you can ommit the this..
If I understood right, the missing static here was one of your problems. If you have static, the function is class-bound and not object-bound, meaning you can call it without having an object. Again, it is important that you understand the difference, and if you don't, ask someone. (To be precise, ask the difference between class, object, static and non-static) It would take too long to explain that in detail here.
But in a nutshell, if the function is not static, it needs to be called on an object to work. Look further down in the other class for details how that looks like.
public String toString (){
return "Filter(" + letters + ")";
}
This function is also non-static. It is used whenever the object needs to be converted to a String, like in a System.out.println() call. Again, it is important here that you understand the difference between class and object.
The QueryResolver class
public class QueryResolver {
Filter filter;
String query;
public QueryResolver where(String queryStr) {
this.query = queryStr;
return this;
}
public QueryResolver matches(String filterStr) {
this.filter = new Filter(filterStr);
return this;
}
public int count() {
int result = 0;
for(int i = 0; i < query.length(); i++) {
if(filter.contains(query.charAt(i))){
result++;
}
}
return result;
}
}
Again, let's break that down.
public class QueryResolver {
...
}
Our class body.
Note that we don't have a constructor here. It is advisable to have one, but in this case it would be an empty function with no arguments that does nothing, so we can just leave it and the compiler will auto-generate it.
public QueryResolver where(String queryStr) {
this.query = queryStr;
return this;
}
This is an interesting function. It returns a this pointer. Therefore you can use the result of the function to do another call, allowing you to 'chain' multiple function calls together, like resolver.where(query).matches(filter).count().
To understand how that works requires you to understand both the class-object difference and what exactly the this pointer does.
The short version is that the this pointer is the pointer to the object that our function currently lives in.
public QueryResolver matches(String filterStr) {
this.filter = new Filter(filterStr);
return this;
}
This is almost the same as the where function.
The interesting part is the new Filter(...). This creates the previously discussed Filter-object from the class description and puts it in the QueryResolver object's this.filter variable.
public int count() {
int result = 0;
for(int i = 0; i < query.length(); i++) {
if(filter.contains(query.charAt(i))){
result++;
}
}
return result;
}
Iterates through the object's query variable and checks for every letter if it is contained in filter. It keeps count of how many times this happens and returns the count.
This function requires that filter and query are set. Therefore it is important that before someone calls count(), they previously call where(..) and matches(..).
In our case, all of that happens in one line, resolver.where(query).matches(filter).count().
The main function
I wrote two different main functions. You want to test your code as much as possible during development, therefore the first one I wrote was a fixed one, where you don't have to enter something manually, just click run and it works:
public static void main(String[] args) {
String filter="kjasd";
String query="kjg4t";
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
System.out.println(count);
}
Once you understand the class-object difference, this should be straight forward.
But to repeat:
QueryResolver resolver = new QueryResolver();
This creates your QueryResolver object and stores it in the variable resolver.
int count = resolver.where(query).matches(filter).count();
Then, this line uses the resolver object to first call where, matches, and finally count. Again, this chaining only works because we return this in the where and matches functions.
Now finally the interactive version that you created:
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
System.out.println("please enter the query string! ");
String query= in.next();
System.out.println("please enter the filter stirng!");
String filter= in.next();
System.out.println("the query string is : [" + query+ "]");
System.out.println("the filter string is : [" + filter+ "]");
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
System.out.println("the characters of the String ["+filter+"] has been found in the forworded string ["+query+"] exactly "+count+" times!" );
in.close();
}

Removing an input from a recursive method

Good morning! I received a problem statement to write a method that returns all possible combinations of a String input passed, e.g.
if ABC is passed then it returns [A, AB, BC, ABC, AC, B, C]
if ABCD is passed then it returns [A, AB, BC, CD, ABC, AC, ACD, B, BCD, BD, ABD, AD, C, D, ABCD]
means AB and BA are always taken same, ABC, BAC and ACB are also same.
I ended up writing below code and it seems to working though (not sure).
public static Set<String> getAnyPermutations(String s,String strInput) {
Set<String> resultSet = new HashSet<>();
char[] inp = strInput.toCharArray();
for(int i=0; i<inp.length; i++) {
String temp =s+String.valueOf(inp[i]);
resultSet.add(temp);
if(i+1<=inp.length)
resultSet.addAll(getAnyPermutations(temp, String.valueOf(Arrays.copyOfRange(inp, i+1, inp.length))));
}
return resultSet;
}
My question is, I want to remove the first param(String s) from the method as using it for interal comutations only, or if that is not possible then making sure that user always pass a "" value or I can reset it to "" for the first(non-recursive) call of this method. I am going confused how to do that inside a recursive funtion.
Also please add comment if you have doubt it can fail other than this situation.
Conditions, All has to be done inside this function only, no other method can be created.
All has to be done inside this function only, no other function can be created.
Then you can't do it. The function has no (reasonable)* way of knowing whether it called itself or was called by another function.
There are lots of solutions involving creating another function. One that might fit your requirements, depending on how they're actually expressed, would be to have the function define a lambda to do the work, and have the lambda call itself. E.g., getAnyPermutations wouldn't actually be recursive, it would contain a recursive function.
But that may be out of bounds depending on the exact meaning of the quote above, since the lambda is another function, just not one that can be accessed from the outside.
* The unreasonable way is by examining a stack trace, which you can get from Thread.currentThread().getStackTrace.
You can always transform a recursive method into its iterative equivalent - e.g. see
Way to go from recursion to iteration.
In the iterative version it's easy to not expose the state parameter (you now just need to initialize it at the beginning of the iterative method).
This is not very practical in general (but I believe that the purpose of the question is more theoretical, otherwise it's always a good solution to just expose another method).
Furthermore, in this particular situation you might consider this simple iterative approach (though it is not obtained by directly translating the given code):
public static Set<String> getAnyPermutations(String strInput) {
Set<String> resultSet = new HashSet<>();
char[] inp = strInput.toCharArray();
for (int bitMask = 0; bitMask < (1 << inp.length); bitMask++) {
StringBuilder str = new StringBuilder();
for (int i = 0; i < inp.length; i++) {
if ((bitMask & (1 << i)) != 0) {
str.append(inp[i]);
}
}
if (str.length() > 0) {
resultSet.add(str.toString());
}
}
return resultSet;
}
You can change the current method to be a private one and interface it with a public method with one argument e.g.:
private static Set<String> getAnyPermutations(String s,String strInput) {
Set<String> resultSet = new HashSet<>();
char[] inp = strInput.toCharArray();
for(int i=0; i<inp.length; i++){
String temp =s+String.valueOf(inp[i]);
resultSet.add(temp);
if(i+1<=inp.length)
resultSet.addAll(getAnyPermutations(temp, String.valueOf(Arrays.copyOfRange(inp, i+1, inp.length))));
}
return resultSet;
}
Now, you can expose a one argument method to the user which in turn will call the above method, e.g.:
public static Set<String> getAnyPermutations(String strInput) {
return getAnyPermutations("", strInput);
}
Update
If you can't create any other method at all then the only alternative would be to use var-args. However, that requires change in the implementation and doesn't actually restrict the user from passing multiple values.
You can rewrite this particular algorithm so that it doesn't need to carry a state through to the recursively called invocation.
(Java-centric pseudocode):
Set<String> getAnyPermutations(String str) {
if(str.length() == 0) {
return Collections.emptySet();
}
String head = str.substring(0,1);
String tail = str.substring(1);
Set<String> permutationsOfTail = getAnyPermutations(tail);
Set<String> result = new HashSet();
// Head on its own
// For input 'ABC', adds 'A'
result.add(head);
// All permutations that do not contain head
// For input 'ABC', adds 'B', 'C', 'BC'
result.addAll(permutationsOfTail);
// All permutations that contain head along with some other elements
// For input 'ABC', adds 'AB, 'AC', 'ABC'
for(String tailPerm : permutationsOfTail) {
result.add(head + tailPerm);
}
return result;
}
This meets your aim of not creating any extra methods -- but note that it would be cleaner code if the for loop was extracted into a new method Set<String> prefixEachMember(String prefix, Set<String> strings) allowing result.addAll(prefixEachMember(head,permutationsOfTail)).
However it's not always possible to do this, and sometimes you do want to carry state. One way is the way you've asked to avoid, but I'm going to include it in my answer because it's a clean and common way of achieving the aim.
public Foo myMethod(Bar input) {
return myMethod(new HashSet<Baz>(), input);
}
private Foo myMethod(Set<Baz> state, Bar input) {
if(...) {
return ...;
} else {
...
return myMethod(..., ...);
}
}
Here, the first method is your public API, in which the collector/state parameter is not required. The second method is a private worker method, which you initially call with an empty state object.
Another option is to refer to an object field. I would recommend against this, however, because it gets confusing when recursive code refers to a global object.

Recursively reversing a sentence using void reverse() method (Java)

The tester class is:
public class SentenceWithReverseTester
{
public static void main(String[] args)
{
String[] list = new String[]{"aba",
"Madam, I'm Adam",
"nut",
"A man, a plan, a canal, Panama",
"wonderful",
"Go hang a salami, I'm a lasagna hog",
"race car",
"1",
"",
"zero",
"#!:"} ;
for (String line : list) {
SentenceWithReverse sentence = new SentenceWithReverse(line) ;
sentence.reverse() ;
System.out.println(line + " reversed becomes........") ;
System.out.println(sentence.toString()) ;
System.out.println("----------------------------") ;
}
}
}
And for the reverse method I have:
public void reverse()
{
String s = super.toString();
if(s.length() > 0)
{
String first = s.substring(0,1);
String remaining = s.substring(1, s.length());
SentenceWithReverse shorter = new SentenceWithReverse(remaining);
shorter.reverse();
System.out.println(shorter + first);
}
}
I'm not getting the result I want, and I'm not sure what I'm doing wrong here.
You should make reverse() actually return a String, rather than void, so that you can use the result of the reversal. So change void to String in the method's declaration. Then you'll need a couple of return statements inside the method - one for the base case and one for the recursive case.
In the recursive case, the return statement will be something like
return shorter.reverse() + first;
that is, you take the reverse of the shorter sentence, and put the first character back at the end.
In the base case, that is, where the input to the method is "", you can just write
return "";
I'll leave it to you to figure out where to insert these two return statements, within the logic of your method. Good luck.
You're not assigning any member fields in your reverse method. You don't show what fields you have, but I would guess you have a single String field that is returned from toString. You should assign the shorter + first to it where you have the System.out.println call.

Write a recursive method that returns the number of occurences of 'A' in the string it is passed

So I've been fiddling with this problem for the past hour. I keep getting unexpected type error. It appears to be from a confliction between charAt and s.length. Any ideas on what could fix that?
class lab7
{
public static void main(String[] args)
{
String s = ("BCA");
}
public static String recursion(String s)
{
if (s.length()>=0)
{
if(s.charAt(s.length()) = A)
{
count++;
}
s.substring(0, s.length()-1);
}
return count;
}
}
There are several issues with this code, including some significant logic errors. However, the specific error you're getting is probably here:
if(s.charAt(s.length()) = A)
First, note that you're using = instead of ==, which does an assignment rather than a comparison. Also note that A should be in single quotes to be a character literal. Right now, Java thinks A is the name of a variable, which isn't defined. Finally, note that strings are zero-indexed, so looking up the character at position s.length() will give you a bounds error.
I hope this helps you get started! As a hint, although your function is named "recursion," does it actually use recursion?
Following code uses String class. For performance critical applications you might want to use StringBuffer / StringBuilder class accordingly.
class StringCounter
{
public static void main (String[] args)
{
int count = returnCount("ABCDABCDABCD", 0);
System.out.println(count);
}
public static int returnCount(String s, int count)
{
// You may want to do some validations here.
if(s.length()==0)
{
return count;
}
if(s.charAt(0)=='A')
{
return returnCount(s.substring(1), count+1);
}
else
{
return returnCount(s.substring(1), count);
}
}
}
The code simply slices the String parameter one character at a time and checks for the required character. Further on every invoke it will update the count and String parameter.
Any ideas on what could fix that?
Your function is not recursive. Recursive functions call themselves with manipulated/updated parameters.
As a thumb rule in recursive functions, always think in terms of manipulating function parameters.
Always have a base case that will terminate recursive calls.
Consider this snippet:
static int countA(String str) {
if (str == null || str.length() == 0) { /* nothing or "" contains 0 A's */
return 0;
}
return (str.charAt(0) == 'A' ? 1 : 0 ) /* 0 or 1 A's in first character */
+ countA(str.substring(1)); /* plus no. of A's in the rest */
}
And you call the function like this:
int a = countA("ABAABA"); /* a is 4 */
I realize now that this question was school related, but at least this snippet works as an exercise in understanding recursion.

alternate method for using substring on a String

I have a string which contains an underscore as shown below:
123445_Lisick
I want to remove all the characters from the String after the underscore. I have tried the code below, it's working, but is there any other way to do this, as I need to put this logic inside a for loop to extract elements from an ArrayList.
public class Test {
public static void main(String args[]) throws Exception {
String str = "123445_Lisick";
int a = str.indexOf("_");
String modfiedstr = str.substring(0, a);
System.out.println(modfiedstr);
}
}
Another way is to use the split method.
String str = "123445_Lisick";
String[] parts = string.split("_");
String modfiedstr = parts[0];
I don't think that really buys you anything though. There's really nothing wrong with the method you're using.
Your method is fine. Though not explicitly stated in the API documentation, I feel it's safe to assume that indexOf(char) will run in O(n) time. Since your string is unordered and you don't know the location of the underscore apriori, you cannot avoid this linear search time. Once you have completed the search, extraction of the substring will be needed for future processing. It's generally safe to assume the for simple operations like this in a language which is reasonably well refined the library functions will have been optimized.
Note however, that you are making an implicit assumption that
an underscore will exist within the String
if there are more than one underscore in the string, all but the first should be included in the output
If either of these assumptions will not always hold, you will need to make adjustments to handle those situations. In either case, you should at least defensively check for a -1 returned from indexAt(char) indicating that '_' is not in the string. Assuming in this situation the entire String is desired, you could use something like this:
public static String stringAfter(String source, char delim) {
if(source == null) return null;
int index = source.indexOf(delim);
return (index >= 0)?source.substring(index):source;
}
You could also use something like that:
public class Main {
public static void main(String[] args) {
String str = "123445_Lisick";
Pattern pattern = Pattern.compile("^([^_]*).*");
Matcher matcher = pattern.matcher(str);
String modfiedstr = null;
if (matcher.find()) {
modfiedstr = matcher.group(1);
}
System.out.println(modfiedstr);
}
}
The regex groups a pattern from the start of the input string until a character that is not _ is found.
However as #Bill the lizard wrote, i don't think that there is anything wrong with the method you do it now. I would do it the same way you did it.

Categories