Program hangs and won't finish - java

I'm writing a program that is supposed to take as input, several arrays of objects, and process them with the output being all the elements that the lists have in common. In other words, find the intersection of three arrays.
When I attempt to run the program, it all goes fine until the program starts executing the while loop within findCommonElements(). It hangs there and doesn't step forward, and I can't figure out why. Any help would be greatly appreciated.
edit When the arrays are passed to this method, they are already sorted
public static Comparable[] findCommonElements(Comparable[][] collections)
{
team[] intersection = new team[50];
int index = 0;
int i = 0; //counter for collections[0]
int j = 0; //counter for collections[1]
int k = 0; //counter for collections[2]
System.out.print("test");
while (i < collections[0].length && j < collections[1].length && k < collections[2].length)
{
//if query value > collections[2] value, increment collections[2]
if (collections[0][i].compareTo(collections[1][j]) > 0)
{
j++;
incComparisons();
}
//if query value > collections[2] value, increment collections[2]
else if (collections[0][i].compareTo(collections[2][k]) > 0)
{
k++;
incComparisons();
}
else if (collections[0][i] == collections[1][j] && collections[0][i] == collections[2][k])
{
// add entry to intersection array
intersection[index] = (team) collections[0][i];
index++;
incComparisons();
// if the next item in each collection also matches, then add an extra instance of that item to the list
if (collections[1][j + 1] == collections[0][i] || collections[2][k + 1] == collections[0][i])
{
intersection[index] = (team) collections[0][i];
index++;
incComparisons();
}
i++;
j++;
k++;
}
}
return intersection;
}

Related

Recursive in Merge Sort

public static void main(String[] args) {
int[] numbers = {20,4,7,6,1,3,9,5};
mergeSort(numbers);
}
private static void mergeSort(int[] inputArray) {
int inputLength = inputArray.length;
System.out.println(inputLength);
if (inputLength < 2)
return;
int midIndex = inputLength / 2;
int[] leftHalf = new int[midIndex];
int[] rightHalf = new int[inputLength - midIndex];
for (int i = 0; i < midIndex; i++) {
leftHalf[i] = inputArray[i];
}
for (int i = midIndex; i < inputLength; i++) {
rightHalf[i - midIndex] = inputArray[i];
}
mergeSort(leftHalf);
mergeSort(rightHalf);
merge(inputArray, leftHalf, rightHalf);
}
private static void merge(int[] inputArray, int[] leftHalf, int[] rightHalf) {
int leftSize = leftHalf.length;
int rightSize = rightHalf.length;
int i = 0, j = 0, k = 0;
while (i < leftSize && j < rightSize) {
if (leftHalf[i] <= rightHalf[i]) {
inputArray[k] = leftHalf[i];
i++;
} else {
inputArray[k] = rightHalf[j];
j++;
}
k++;
}
while (i < leftSize) { //eğer karşılaştırılmayan bir tane kalırsa diye yapılıyor yani
inputArray[k] = leftHalf[i];
i++;
k++;
}
while (j < rightSize) {
inputArray[k] = rightHalf[j];
j++;
k++;
}
}
In the mergeSort part if inputLength < 2 part of the code, we return when the length is less than 2. And last time the inputLength was 1, it becomes 2 and returns to the array [20,4].
This did not make sense to me logically. How does it get back to [20,4] when last we had [20] left?
first of all the code you have shared is flawed in the merge function part, you can find the proper code for Merge sort online, you can refer to
https://www.geeksforgeeks.org/java-program-for-merge-sort/
Now for understanding merge sort you have to understand the concept of stack (Last in First out) & recursion. In recursion the lines after the recursive call wait till the recursive call to the function has not executed completely. So in case of the
1st call Merge sort the length of the array is n and waiting for the complete execution of mergeSort(leftHalf) and mergeSort(rightHalf) both of size (n/2).
now for both the mergeSort(leftHalf) and mergeSort(rightHalf)
there will be sub left part and sub right part and this will continue till the size of the array becomes <2 and the remaining part will wait.
and after the successful execution of the smallest part it will return to the previous part from where this part was called. By this eventually this will return to the place where the function was called first.
And in case of your code both the smaller arrays are merged into the larger array so the data of the left and right sub array aren't lost.

How to return value when there's no input in array method?

So, I have to write a program that counts the most repeated number in an array (e.g. 1, 2, 2, 3, 3, 3) and then tells the user what number is it (3). Finally, an online compiler tests my code and sees if my output is correct.
Here are the inputs from the program.
My issue is the last input, which is nothing. I tried to return a value but I couldn't.
Here's my code excluding the main method (Java):
Edit: Thank you everyone. I'm an idiot.
public int lengthOfLongestRun(int[] values) {
if (values == null){
return 0;
}
int lastVal = values[0];
int currentLength = 1;
int longestLength = 1;
for (int i = 1; i < values.length; i++) {
if (values[i] == lastVal)
currentLength++;
else
currentLength = 1;
lastVal = values[i];
if (currentLength > longestLength)
longestLength = currentLength;
}
return longestLength;
}
Since the array is empty you need to check the length and return zero if the length of the array is zero.
Right now you have added a condition already for null check. Just extend that and add another condition for empty array aswell.
public int lengthOfLongestRun(int[] values)
{
if(values == null || values.length == 0){ // code added here
return 0;
}
int...
...
That should solve your problem.
I can see another potential bug here. Your loop starting at position 1
for (int i = 1; i < values.length; i++)
{
What if the biggest number lies at position 1 ? You are not seeing the bug because all your input arrays starting with value 1.
You should check array size
if(values == null || array.length == 0){
return 0;
}
if(values == null || values.length == 0){
return 0;
}
If the input array is [], its length is zero. So just check for that:
if (values.length == 0) {
return 0;
}
Note that it's maybe better not to return 0 in the null case: it's an invalid input, so don't give a valid output. Throw a NullPointerException or IllegalArgumentException, for instance.
You can also write the loop so as not to need to handle the zero case separately:
int longestLength = 0;
int i = 0;
while (i < values.length) {
int start = i++;
while (i < values.length && values[i] == values[start]) {
++i;
}
longestLength = Math.max(longestLength, i - start);
}
return longestLength;

CodingBat commonTwo method, help examine the output?

Question Summary:
Given two String arrays, return an integer representing how many matches are between them (ignore duplicates).
Real Answer:
http://www.javaproblems.com/2013/11/java-ap-1-commontwo-codingbat-solution.html
My Code
public int commonTwo(String[] a, String[] b) {
int count = 0;
boolean done = false;
for (int i = 0; i<a.length-1; i++){
if(a[i].equals(a[i+1])){
i++;
for (String j:b)
if (a[i].equals(j) && !done){
done = true;
count++;
}
}
else{
for (String j:b)
if(a[i].equals(j) && !done){
done = true;
count++;
}
}
done = false;
if(i == a.length-2)
for (String j:b)
if (a[i+1].equals(j) && !done){
done = true;
count++;
}
}
return count;
}
Image of output: [1]: http://i.stack.imgur.com/0esjC.png
So what it was intended to do was to go through all of the array a,if it equals the next one then go to that index, then add to count if there's a match between the arrays. The done boolean was used to make it so it doesn't add to count if there're duplicates of b that matches a and to end it once a match is found.
Lastly,
if(i == a.length-2)
was intended to make it so if it's the second before the last index number (as the last index number won't be checked in some cases), and not the same as the last index number, then it would check for matches for the last index number after checking the one before the last essentially. I understand why both errors occur and was wondering what could be done to fix it, particularly for the second one/comments on the code. Also, a third issue I notice would be (["a"], ["a"]) → 1 but the code will result in 0.
This question can be done is linear time O(N) that is a single traversal of both arrays a and b.
You should increment i as long as same string appears.So
if(a[i].equals(a[i+1]))
i++;
should be replaced by
while(i+1<a.length&&a[i].equals(a[i+1])){
i++;}
Also you do not need to go through entire array b for a single string of array a since both are in alphabetical order.You should only compare the string from the array b as long there is no match.Once a match is found then you should remember that index and next time matching should continue from that index onwards for the array b
Also you don't need the boolean variable done.
Keeping these things in mind the correct code is:
public static int commonTwo(String[] a, String[] b) {
int count = 0;
int j=0,i;
for (i = 0; i<a.length-1&&j<b.length-1;){
//SKIP DUPLICATES FOR ARRAY a
while(i+1<a.length&&a[i].equals(a[i+1])){
i++;}
//SKIP DUPLICATES FOR ARRAY b
while(j+1<b.length&&b[j].equals(b[j+1])){
j++;}
//MATCH THE STRINGS FROM ARRAY a AND ARRAY b
while(i<a.length&&j<b.length&&a[i].compareTo(b[j])!=0)
{
//INCREMENT I IF STRING IN ARRAY a IS LESS THAN STRING IN ARRAY b
if(a[i].compareTo(b[j])<0)
++i;
//INCREMENT J IF STRING IN ARRAY b IS LESS THAN STRING IN ARRAY a
else ++j;
}
//IF ABOVE LOOP BREAKS BECAUSE OF MATCH
if(i<a.length&&j<b.length)
{count++; ++j; ++i;}
}
//IF THE LAST ELEMENT OF ARRAY a IS LEFT FOR COMPARISON
if(i==a.length-1)
{
while(j<b.length)
{
//SKIP DUPLICATES OF ARRAY b
while(j+1<b.length&&b[j].equals(b[j+1]))
++j;
if(a[i].equals(b[j]))
{++count;}
++j;
}
}
//IF THE LAST ELEMENT OF ARRAY b IS LEFT FOR COMPARISON
if(j==b.length-1)
{
while(i<a.length)
{
//SKIP DUPLICATES OF ARRAY a
while(i+1<a.length&&a[i].equals(a[i+1]))
++j;
if(a[i].equals(b[j]))
++count;
++i;
}
}
return count;
}
This is the simplest solution i could come up with that uses only one loop.
public int commonTwo(String[] a, String[] b) {
int count = 0;
int i = 0;
int j = 0;
String s = "";
while (i < a.length && j < b.length) {
if (a[i].compareTo(b[j]) < 0)
i++;
else if (a[i].equals(b[j]) && a[i] != s) {
s = a[i];
count++;
i++;
j++;
}
else j++;
}
return count;
}
public int commonTwo(String[] a, String[] b) {
int ctr = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < b.length; j++) {
if (i > 0 && a[i] == b[j] && a[i] != a[i - 1]) {
ctr++;
break;
} else if (i == 0 && a[i] == b[j]) {
ctr++;
break;
}
}
}
return ctr;
}

Using quicksort on a string array

I'm a programming student and rather than post the whole assignment I'll just ask for help solving what I've tried for hours now to understand. I'm tasked with sorting an array of strings using the quicksort method. Everything else I've been tasked with as part of this problem is fine but when I tested the sorting method by printing out the String Array, it's completely jumbled up without any seeming rhyme or reason. Please help me pinpoint the error in my code, or the several glaring errors I've overlooked. The array of strings provided is this list of 65 names: http://pastebin.com/jRrgeV1E and the method's code is below:
private static void quickSort(String[] a, int start, int end)
{
// index for the "left-to-right scan"
int i = start;
// index for the "right-to-left scan"
int j = end;
// only examine arrays of 2 or more elements.
if (j - i >= 1)
{
// The pivot point of the sort method is arbitrarily set to the first element int the array.
String pivot = a[i];
// only scan between the two indexes, until they meet.
while (j > i)
{
// from the left, if the current element is lexicographically less than the (original)
// first element in the String array, move on. Stop advancing the counter when we reach
// the right or an element that is lexicographically greater than the pivot String.
while (a[i].compareTo(pivot) < 0 && i <= end && j > i){
i++;
}
// from the right, if the current element is lexicographically greater than the (original)
// first element in the String array, move on. Stop advancing the counter when we reach
// the left or an element that is lexicographically less than the pivot String.
while (a[j].compareTo(pivot) > 0 && j >= start && j >= i){
j--;
}
// check the two elements in the center, the last comparison before the scans cross.
if (j > i)
swap(a, i, j);
}
// At this point, the two scans have crossed each other in the center of the array and stop.
// The left partition and right partition contain the right groups of numbers but are not
// sorted themselves. The following recursive code sorts the left and right partitions.
// Swap the pivot point with the last element of the left partition.
swap(a, start, j);
// sort left partition
quickSort(a, start, j - 1);
// sort right partition
quickSort(a, j + 1, end);
}
}
/**
* This method facilitates the quickSort method's need to swap two elements, Towers of Hanoi style.
*/
private static void swap(String[] a, int i, int j)
{
String temp = a[i];
a[i] = a[j];
a[j] = temp;
}
Ok, i was mistaken that it would work and found your tiny mistake.
Take a look at wikipedias pseudo code
You will notice that your conditions in the while loop are causing the error
if you change (a[i].compareTo(pivot) < 0 && i <= end && j > i) and (a[j].compareTo(pivot) > 0 && j >= start && j >= i) to
(a[i].compareTo(pivot) <= 0 && i < end && j > i) and (a[j].compareTo(pivot) >= 0 && j > start && j >= i).
Thought this would help for those who seek for a string sorting algorithm based on quick sorting method.
public class StringQuickSort {
String names[];
int length;
public static void main(String[] args) {
StringQuickSort sorter = new StringQuickSort();
String words[] = {"zz", "aa", "cc", "hh", "bb", "ee", "ll"}; // the strings need to be sorted are put inside this array
sorter.sort(words);
for (String i : words) {
System.out.print(i);
System.out.print(" ");
}
}
void sort(String array[]) {
if (array == null || array.length == 0) {
return;
}
this.names = array;
this.length = array.length;
quickSort(0, length - 1);
}
void quickSort(int lowerIndex, int higherIndex) {
int i = lowerIndex;
int j = higherIndex;
String pivot = this.names[lowerIndex + (higherIndex - lowerIndex) / 2];
while (i <= j) {
while (this.names[i].compareToIgnoreCase(pivot) < 0) {
i++;
}
while (this.names[j].compareToIgnoreCase(pivot) > 0) {
j--;
}
if (i <= j) {
exchangeNames(i, j);
i++;
j--;
}
}
//call quickSort recursively
if (lowerIndex < j) {
quickSort(lowerIndex, j);
}
if (i < higherIndex) {
quickSort(i, higherIndex);
}
}
void exchangeNames(int i, int j) {
String temp = this.names[i];
this.names[i] = this.names[j];
this.names[j] = temp;
}
}

2d array game that moves to adjacent spaces picking up coins

So I've been working on this problem for the better part of today. Can someone help me figure out where I went wrong?
It’s greedy because it moves to the location with the highest number of coins; and it’s lazy because it will stop moving if no adjacent location increases its coin treasure. If several adjacent locations had the same highest number of coins, the gatherer will choose to move to the highest in a clockwise fashion. The gatherer empties the coins from any location it visits.
public static int receiveCoins(int[][]map,int r,int c){
int[] coins = {0,0,0,0};
boolean moreCoins = true;
int numOfCoins = 0;
if(map[r][c] > 0){
numOfCoins += map[r][c];
map[r][c] = 0;
}
while(moreCoins == true){
if(c < (map.length-1)){
if(map[r][c+1] > 0){
coins[1] = map[r][c+1];
}
}
if(r < map[0].length-1){
if(map[r+1][c] > 0){
coins[2] = map[r+1][c];
}
}
if(row > 0){
if(map[r-1][c] > 0){
coins[0] = map[r-1][c];
}
}
if(c > 0){
if(map[r][c-1] > 0){
coins[3] = map[r][c-1];
}
}
int maxCoin = 0;
int nRow = 0;
int nCol = 0;
for(int i = 0; i < coins.length; i++){
if(coins[i] > maxCoin){
maxCoin = coins[i];
if(i == 0){
nCol = c;
nRow = r - 1;
}else if(i == 1){
nRow = r;
nCol = c + 1;
}else if(i == 2){
nCol = c;
nRow = r + 1;
}else{
nRow = r;
nCol = c - 1;
}
}
coins[i] = 0;
}
}
}
if (maxCoin == 0){
moreCoins = false;
}else{
r = nRow;
c = nCol;
numOfCoins += map[r][c];
map[r][c] = 0;
}
}
return numOfCoins;
}
A few corrections to your algorithm:
Suggestion from user1509803
You should reset coins[] back to zero after checking them for the highest, so that in the next iteration you are not reusing the values from the previous iteration. For example, if a value is non-zero in one iteration and then zero in the next.
Why the break near the end? This will cause your program to always break after the first iteration in the while loop.
map[row][col] = 0;
if(map[row][col] == 0){
break; // why?
}
When checking for the highest-valued next position, be sure to set both the row and column in case a previous position had been identified as the highest.
if(coins[i] > highestCoin){
highestCoin = coins[i];
if(i == 0){
newCol = col; // this is important! do this for all cases!
newRow = row - 1;
}
...
}
Switch the two bounds comparisons. row should compare to map.length, whereas col should compare to map[0].length. This is because rows can be thought of as vertical stacks (and so represent the first index in a 2d-array), whereas columns can be thought of as the horizontal units that make up the stacks (and so appear in the second index). Think of selecting first the stack, and then the unit in the stack.
Well I think col must be less than (map.length-1) instead of (map.length-2)
For {1},{1}, map.length == 2 so map.length-2 = 0, then col must be less than 0 to execute the if block.
Btw, you have map.length comparison to both col and row, so you map will be a square in any case?

Categories

Resources