Merging two arrays using method call - java

I am a beginner in Java looking for some help to finish my assignment. Here you have the assignment text :
A Stack of integers is an abstract data type that allows the following operations:
1) memorize integers (input function)
2) print the memorized numbers in the insertion order (print method)
3) reverse the insertion order of the numbers (reverse method)
4) concatenate two stacks (concatenate method)
5) copy the content of the stack to an array (toarray)
Write a java class to implement the abstract data type of integers. The program should work with the main file.
The first thing i did was create a class that contains the methods such as: print, input, reverse, concatenate, copy, etc to store the integers in an array, print them using the print method, reverse the insertion order. No problems here.
My problem comes when i want to concatenate two arrays of integers (input from the main) using a method in the class. Instead, the program outputs some numbers + the "java.lang.NullPointerException" error which i think i understand reason for.
Here you can see the stack class:
import java.util.Arrays;
public class Repo {
private static int SIZE;
private int [] Repo ;
private int [] Repo2;
private int top;
Repo () {
Repo = new int [SIZE];
}
Repo (int l) {
Repo = new int [l];
}
public void input (int in) {
Repo[top] = in;
top++;
}
public void stampa () { //print
for(top = 0; top < Repo.length; top++ ) {
if(Repo[top]!=0) {
System.out.print(Repo[top] + " ");
}
}
System.out.println();
}
public void gira() { //Invert
for(top=0; top < Repo.length/2; top++) {
int reverse = Repo[top];
Repo[top] = Repo[Repo.length -top -1];
Repo[Repo.length -top -1] = reverse;
}
}
public void appendi(Repo s) { //Append
int aLen = Repo.length;
int bLen = Repo2.length;
int[] result = new int[aLen + bLen];
System.arraycopy(Repo, 0, result, 0, aLen);
System.arraycopy(Repo2, 0, result, aLen, bLen);
}
public void toarray () {
int [] Repo2 = Repo.clone();
}
}
Here you have the main:
public class TestRepo {
// gioca con i repositori di interi
public static void main(String[] args) {
// il risultato deve essere:
//
// 42 43 44 45
// 1 2 3 45 44 43 42
Repo r = new Repo(10);
// r potra' contenere un massimo di 10 elementi
Repo s = new Repo(20);
r.input(42);
r.input(43);
r.input(44);
r.input(45);
r.stampa();
s.input (1);
s.input (2);
s.input (3);
s.gira();
r.appendi(s);
r.gira();
r.stampa();
}
}
As you can see in the main, the numbers were entered using two different references r.input() & s.input().
In order to get the desired output i used the clone method to create a copy of the first array, merge it with a second one and then print it.
The output should be:
42 43 44 45
1 2 3 45 44 43 42
The output i get is:
42 43 44 45
Exception in thread "main" java.lang.NullPointerException
at Repo.appendi(Repo.java:46)
at TestRepo.main(TestRepo.java:32)
I think the cause of the error is that i am not indicating the right reference in the "append" method, but i am not sure. There might be other errors i may not be aware of in my code.
Any help will be appreciated
Thank you very much

As #WJS pointed out, you never initialised Repo2 and there for it's value is null.
therefore: int bLen = Repo2.length; throws an NullPointerException.
I think what you want to do is bLen = s.length as you probably want to size of this Repo plus the size of the repo you want to append, which is s, not Repo2.
This is only regarding your error.
I think your whole implementation is somewhat off.
I would advice you to do some reading on what exactly stacks are, just google it.
Now you work with arrays of integers, but I think you should use Stack instead.
Why would you otherwise have a function called toArray, when your stack implemenation is already an array? Doesn't make sense. I could be wrong tough...
And for your print function I do not see why 0 should not be printed.
Nice job on the inverse though

When performing your changes, you should work only with your stack implementation and nothing else. Here are some pointers.
Repo should only have one array which acts as a stack.
Repo should have a method that prints itself and nothing else.
Repo should be able to reverse itself. That can be done in place, but if you use another array it shouldn't be visible outside of your class. If I were going to do this I would return a reversed version of the stack, rather than mutate one.
The append method should take to stacks. It should create an instance of the stack, populate that instance from the two passed stacks, and return it as a new instance of stack.
A toArray method simply returns a copy of the array backing your stack. Don't just return the array object because mutating that array would also mutate the stack.
The above is how I might approach this. If I said anything that was in conflict with what your instructor wanted or expected, then your instructor's word certainly takes precedence.
Here is an example of how I would handle the append operation. It works as follows:
returns a new stack with the supplied stack appended to the calling stack.
updates the index of the returned stack to point to the next slot.
For an existing Stack one and Stack two to append two to one would be called like this.
Stack appended = one.append(two);
Here is how it might be implemented (has not been thoroughly tested).
data is the internal array that backs the stack
index is the internal pointer that keeps track of elements.
// append stack to this stack
public Stack append(Stack stack) {
// create a new stack to return
Stack retStack = new Stack();
// copy the data from the current stack to the new, ensuring
// space for both
retStack.data = Arrays.copyOf(data, index + stack.index);
System.arraycopy(stack.data, 0, retStack.data, index,
stack.index);
// update the returned stack's index.
retStack.index = index + stack.index;
// return the stack.
return retStack;
}
This is only one possibility. The overall idea is to return a new stack to house any modifications to an existing stack without changing the existing stack. It all depends on how much flexibility you are permitted with your solution and the requirements of your instructor.

Related

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.

NullPointerException, can't find reason even after research

I'm having bad times with creating typical card/deck class in java. I've read some similar questions & answers but either they're not relatable/helpful or I can't simply comprehend it yet.
Here's the code
public class Cards {
boolean isAvailable;
int card_id;
static final int AC = 32;
public Cards [] deck = new Cards[AC];
public void set () {
int a = 0;
for (int i = 0; i < AC; i++) {
if(a == 4) a = 0;
deck[i].isAvailable = true; // <---------
deck[i].card_id = i + (a * 101); // <---------
a++;
}
}
public void read () {
for (int i = 0; i < AC; i++)
System.out.println(deck[i].isAvailable + " " + deck[i].card_id);
}
public static void main (String[] args) {
Cards c = new Cards();
c.set();
c.read();
}
}
Exception in thread "main" java.lang.NullPointerException
at Cards.set(Cards.java:13)
at Cards.main(Cards.java:24)
1.
I've read about similar issues and found that problem can be in initialization of an array and I've tried to do the same with my prog but it went bad anyway.
I marked 13th and 14th lines because they are being pointed (when i comment 13th line just for check, pointer sets to the next line).
2.
Next part of help I would like to get from you is:
Even though there is main (for training purposes), I see other class using this class (which just creates deck) so I guess I won't be needing main... Is everything well set besides probs in first point?
Very simple:
public Cards [] deck = new Cards[AC];
creates an empty array with AC number of slots for Cards objects.
Now you have to put a non-null Cards object into each slot!
But thing is: actually your abstraction is broken.
You wrote code that seems to take one card to be the same as a card set - by adding that array of Cards into your Cards class! And that makes it actually hard to fix your current code. As the "normal" way to fix this would be to add a constructor like
public Cards() {
deck = new Cards[AC];
for (int i=0; i<deck.length;i++) {
deck[i] = new Cards();
}
If you try that ... you immediately run into an endless recursion (creating one new Cards would result in creating AC new Cards (to fill the array); causing a stackoverflow very soon.
Thus the real answer goes somewhere along these lines:
public class Card {
... a class that represents a SINGLE card in your game
and then
public card GameOfCards {
... a class that (for example!) uses an array to hold n objects of class Card!
Finally, as Peter is indicating in his comment: you should learn to use debugging means to work on such problems yourself. One good way: before using any data structure, iterate it and print out its content. Or even better, learn how to use a debugger, and walk through your code step by step! As you should please understand: this is very basic stuff; that you normally should not bring forward here.

Java - how to call an add() method in a different class

This is for homework, and I am becoming a little frustrated with how I can't figure out something so simple.
To simplify my code, I have 3 files right now: one class with an add() method I created among other things, one file that tests it (made by the prof), and one that creates the object (which I won't post, b/c its working). Here's the add() function.
EDIT 2: I'm going to add the method that prints the array, maybe that's the problem?
public class Population {
private Person[] pop = new Person[15];
private int numPop = 0;
public void add(Person c){ // this object is created in another class, it works fine
for(int i = 0; i < pop.length; i++){
if(pop[i] == null) {
pop[i] = c;
numPop++;
} else {}
}
public String listPeople(){
System.out.println("Population with "+numPeople+" people as follows:");
int i = 0;
while (i<numPeople){
System.out.println("A "+pop[i].getAge()+"year old person named "+pop[i].getName());
i++;
//FYI the get methods are working fine and are in another file.
}
return("");
}
Then, I run the program in a test file to ensure it works, which was provided to us. Here's the part that isn't working
public class PopTestProgram{ // FYI the prof created this, I can't change this
public static void main(String[] args){
Population pop = new Population(15);
pop.add(new Person(4, "Bob"));
pop.add(new Person(25, "Kim"));
// then adds 8 more people with different ages and names
// then prints the people
It compiles, but when I run it, it just puts 10 of the last person into the array, then crashes saying there is a problem with the "pop[i] = c;" line. I simply cannot figure out what I need to change here.
I haven't received an email from the prof directly, so I thought I'd ask here.
Edit: Here's what it shows after printing out the last person 10 times. It is showing problems with other methods that I haven't completed yet though...
java.lang.ArrayIndexOutOfBoundsException: -1
at Population.removePerson(Population.java:49)
at PopTestProgram.main(PopTestProgram.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
In add(Person), you are not stopping when you add an item, so the first item you added is put in all cells in the array, then the rest won't go in at all, since there are no more null cells in array. Break the loop when you find an empty location.
public void add(Person c) {
for(int i = 0; i < pop.length; i++){
if(pop[i] == null) {
pop[i] = c;
numPop++;
break;
}
else {
//.....
}
}
}
Could also just use numPop as the next location in the list, like:
public void add(Person c) {
if (numPop < pop.length) {
pop[numPop++] = c;
}
}
The exception is coming in at Population.removePerson(Population.java:49), which is not related to add method. So I assume removePerson is the method to print the person.
While removing you are calling one extra For loop, make sure your iteration is 10 times only.
The java.lang.ArrayIndexOutOfBoundsException: -1clearly tells the removePerson method is calling the index -1 also (which doesnt exist causing ArrayIndexOufofBoundsException). The removePerson method should start from index 9 to index 0 (or viceversa) [10 iteration in total] and then stop out.
Hope this helps

Why doesn't add method accept my inputs?

So far this is my problematic code, assume everything else is made and done:
public GameRecord[] updateHighScoreRecords(GameRecord[] highScoreRecords, String name, int level, int score) {
// write your code after this line
int i = 0;
for (GameRecord gr : highScoreRecords){
if (gr.getScore() >= gr.getScore()){
highScoreRecords.add(i+(gr.getLevel()-level),(Object) new GameRecord(name, level, score)); /*
*adds the new GameRecord in at the (i+gr's level - level)th iteration.
*note it does this because of the assumtion that highScoreRecords is ordered becuase of only using this function
*/
break; //no more need to continue the loop
}
i += 1;
}
return highScoreRecords;
}
as you may have noticed, my code is part of a course, so that is why I'm assuming all other implementations are perfect.
You are passing in a GameRecord[] highScoreRecords array,
but calling a List method add - this does not exist on an Array. You should be getting a compile error.
If you are sure that the array has capacity for insertion then you could do
highScoreRecords[i+(gr.getLevel()-level)] = new GameRecord(name, level, score);
but I guess you would be better off using a List like ArrayList, and keeping your existing code. For this you will to pass a List to the method not an Array.
Java arrays are not dynamic data structures,
highScoreRecords.add(i+(gr.getLevel()-level),
(Object) new GameRecord(name, level, score));
I think you wanted
// Using a List.
GameRecord[] updateHighScoreRecords(List<GameRecord> highScoreRecords,
String name, int level, int score) {
Also, don't cast to Object. That's raw-typeing.

Lexicographic quicksort algorithm

My professor gave me a code for the methods to be used in sorting an array of names lexicographically, but I have no idea how what to write inside the main class to show that the program works. I am very new to java, so please if you know how to do this could you write it as simple as possible for me to understand it. Thanks in advance.
This is are the classes
public class quicksort_class {
int[] array1 = new int[11];
public quicksort_class(int[] w)
{
array1 = w;
}
private static void sort(String[] string, int leftlimit, int rightlimit) {
if (rightlimit > leftlimit)
{
int midpoint = partitionstep(string, leftlimit, rightlimit);
sort(string, leftlimit, midpoint - 1);
sort(string, midpoint, rightlimit);
}
}
public static int partitionstep(String[] string, int leftlimit, int rightlimit)
{
String midpoint = string[rightlimit];
int lpointer = leftlimit;
int rpointer = rightlimit;
String temp = "";
while(string[lpointer].compareTo(midpoint) <= 0)
{
lpointer = lpointer ++;
}
while(string[rpointer].compareTo(midpoint) > 0)
{
rpointer = rpointer --;
}
if(lpointer > rpointer)
{
temp = string[lpointer];
string[lpointer] = string[rightlimit];
string[rpointer] = temp;
System.out.println(string);
}
while(lpointer < rpointer)
{
temp = string[lpointer];
string[lpointer] = string[rightlimit];
string[rightlimit] = temp;
}
return lpointer;
}
}
This is the main class (as you can see I have no idea what to write)
package quicksort;
public class Quicksort {
public static void main(String[] args) {
}
}
Write something that sets up an array of strings and calls sort against it, then prints out the results or checks them against a known good result.
Ideally, write something which does this repeatedly, with particular emphasis on checking unusual combinations (already sorted or sorted in reverse, null in the array, same value appearing several times or all values being identical...)
If you want to go beyond that, you need to dig into the code to understand its edge cases and specifically test those, and/or do a "code coverage" analysis (there are tools to help with that) to make sure all parts of the code have been exercised.
Assume the algorithm of sort method is correct:
1. If the main method is within the body of quicksort_class, you can directly call the sort method as sort(arrayToBeSorted, 0 , arrayToBeSorted.length-1). And the arrayToBeSorted should ordered lexicographically after your call. You can check that to confirm.
2. If the main method is in other class, as your main method currently, you need to at least change the private prefix of sort method to public, and call quicksort_class.sort(arrayToBeSorted, 0 , arrayToBeSorted.length-1).
Some tips:
1. Private prefix of method definition means this method can only be called inside current class body.
2. Static prefix of method definition means you should call this method via class name directly, instead of via a instance of class.
By the way, can you provide what the array1 attribute stands for? I don't get why it's there.

Categories