Related
I'm working on a problem that says "Write a function called splay that reorganizes a list based on the first value. The first value is called the splaymaster. This function will rearrange the list such that all of the values before the splaymaster are less than or equal to the splaymaster and all of the values after it are greater than the splaymaster. The function also returns the index where the splaymaster is located after the list is rearranged. For example, if the list is [8, 15, 4, 48, 26, 45, 18, 29, 2, 1], the function will rearrange it to become [2, 1, 4, 8, 26, 45, 18, 29, 48, 15] and return the value 3. You may not sort the list." The problem that I seem to be having is for the example above it complains that the index is out of bounds which is my first problem. The next is if I use another array such as {90, 8, 15, 4, 48, 26, 45, 18, 29, 2, 1} I get {1, 90, 8, 15, 4, 48, 26, 45, 18, 29, 2} this is my output when it's not correct. What am I doing wrong? and How do I fix it?
public static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static int splay(int[] x) {
int left = 1;
int right = x.length;
int splaymaster = x[0];
while (left < right) {
if (x[left] <= splaymaster) {
left++;
} else {
swap(x, left, right);
}
swap(x, 0, left - 1);
}
return splaymaster;
}
}
int right = x.length;
The index of the last element in an array is x.length - 1, hence the index is out of bounds. Nonetheless, your algorithm seems incorrect. Merely swapping the elements at different locations is not sufficient. If an element is less than the splaymaster then you need to move all the elements up one and insert the smaller element into the array before the splaymaster. I assume there may be other conditions regarding the way to solve the problem but if there are then they are not clear to me from your question, for example it appears that the order of the elements is not important just as long as all elements before the splaymaster are less than or equal to it. I also assume you need to change the array in place, i.e. you are not allowed to use a second array.
Consider the following code:
import java.util.Arrays;
public class SplayTst {
public static int splay(int x[]) {
int index = 0;
int splaymaster = x[0];
for (int i = 1; i < x.length; i++) {
if (x[i] <= splaymaster) {
int temp = x[i];
for (int j = i; --j >= 0;) {
x[j + 1] = x[j];
}
x[0] = temp;
index++;
}
}
return index;
}
public static void main(String[] args) {
int[] test = new int[]{8, 15, 4, 48, 26, 45, 18, 29, 2, 1};
int ndx = splay(test);
System.out.println(Arrays.toString(test));
System.out.println(ndx);
test = new int[]{90, 8, 15, 4, 48, 26, 45, 18, 29, 2, 1};
ndx = splay(test);
System.out.println(Arrays.toString(test));
System.out.println(ndx);
}
}
Running the above code produces the following output:
[1, 2, 4, 8, 15, 48, 26, 45, 18, 29]
3
[1, 2, 29, 18, 45, 26, 48, 4, 15, 8, 90]
10
Alternatively, assuming that you can use any method to solve the problem, consider the following which uses ArrayList and then converts it to an array and then all the array elements are copied to the original array. Note that the single code line for converting ArrayList<Integer> to int[] is taken from the following question:
How to convert an ArrayList containing Integers to primitive int array?
I refer to this line of the below code:
int[] arr = list.stream().mapToInt(i -> i).toArray();
I iterate through the original array. If an element is greater than the splaymaster then it is appended to the ArrayList, otherwise it is inserted as the first element in the ArrayList.
import java.util.ArrayList;
import java.util.Arrays;
public class SplayTst {
public static int splay(int[] x) {
ArrayList<Integer> list = new ArrayList<>();
list.add(x[0]);
int index = 0;
for (int i = 1; i < x.length; i++) {
if (x[i] <= x[0]) {
list.add(0, x[i]);
index++;
}
else {
list.add(x[i]);
}
}
int[] arr = list.stream().mapToInt(i -> i).toArray();
for (int i = 0; i < x.length; i++) {
x[i] = arr[i];
}
return index;
}
public static void main(String[] args) {
int[] test = new int[]{8, 15, 4, 48, 26, 45, 18, 29, 2, 1};
int ndx = splay(test);
System.out.println(Arrays.toString(test));
System.out.println(ndx);
test = new int[]{90, 8, 15, 4, 48, 26, 45, 18, 29, 2, 1};
ndx = splay(test);
System.out.println(Arrays.toString(test));
System.out.println(ndx);
}
}
How would I separate even and odd integers in an array with order preserved?
Modifications must be in place and the return is a void, and can only use built in methods.
An example would be:
{4, 5, 8, 16, 45, 12, 67, 13} -> {4, 8, 16, 12, 5, 45, 67, 13}
Explanation
You can easily solve this with one iteration, remembering the index of the current border and swapping elements.
So for your example, the process will be:
{ 4, 5, 8, 16, 45, 12, 67, 13 } // swap 4 with 4
^
{ 4, 5, 8, 16, 45, 12, 67, 13 }
^
{ 4, 8, 5, 16, 45, 12, 67, 13 } // swap 5 with 8
^
{ 4, 8, 16, 5, 45, 12, 67, 13 } // swap 5 with 16
^
{ 4, 8, 16, 12, 45, 5, 67, 13 } // swap 5 with 12
^
Where the ^ shows the current border index, which is always one ahead of the even values, pointing at the index where you want to swap the next even value to.
First draft
Here is the code for that:
int borderIndex = 0;
for (int i = 0; i < values.length; i++) {
int value = values[i];
if (value % 2 == 0) {
// swap
values[i] = values[borderIndex];
values[borderIndex] = value;
borderIndex++;
}
}
Preserving order
Now, this solution already preserves the order of the even numbers out of the box. But if you pay close attention you see that it does not preserve order of the odd values. It goes wrong as soon as you have multiple odd values after each other before an even value, like
..., 5, 45, 12, ...
because it will then swap 5 with 12 resulting in 12, 45, 5 instead of 12, 5, 45.
Even worse when there are multiple odd values:
..., 5, 7, 9, 11, 12, ...
resulting in 12, 7, 9, 11, 5.
In order to fix this, we have to not just swap 5 with the even value 12 but actually swap all the way back to 5. So:
swap 12 with 11
swap 12 with 9
swap 12 with 7
swap 12 with 5
basically shifting down 12 from right to left, until it stands right in front of 5.
We can do so easily with a simple loop that moves from 12 (at i) to 5 (at borderIndex):
int borderIndex = 0;
for (int i = 0; i < values.length; i++) {
int value = values[i];
if (value % 2 == 0) {
// swap from i to borderIndex
for (int j = i; j > borderIndex; j--) {
values[j] = values[j - 1];
values[j - 1] = value;
}
borderIndex++;
}
}
You can also do it like this. In this case your sorting them on their inherent nature as opposed to their relationship to each other.
Integer [] arr = {4, 5, 8, 16, 45, 12, 67, 13};
Arrays.sort(arr, Comparator.comparing(a->a % 2));
System.out.println(Arrays.toString(arr));
prints
[4, 8, 16, 12, 5, 45, 67, 13]
I am stuck and can't think of a way to properly shift an array by __ units. I am trying to create an array of 30 items (numbers 1-30) which can then be shifted to the right by the number the user inputs. This would mean that the first few numbers in the array would take the index's at the end of the array, and the rest of the numbers would be shifted to the left. (Ex, if shift = 3, numbers 1,2,3 would take the index of 27,28,29, and the rest of the numbers 4-30 would shift left making index 0 =4, index 1=5, index 2=6....
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
System.out.println("\nEnter the shift/rotation:");
int shiftNum = input.nextInt();
int [] numArray = new int [30];
for(int i = 0; i < 30; i++){
numArray [i] = i+1;
System.out.print(numArray[i]+" ");
}
}
}
This is the code I have so far, any suggestions to how I can do this? I have tried to make a separate for loop like
numArray [i-shiftNum] = numArray[i];
But when doing this, the index of 0-shiftNum would be negative and would not work. This is the context of the problem:
Create a program that will create an array of 30 items. Then it will rotate the array by a number selected by the user.
In order to shift the numbers in the array, the following for loop works for shifting the values within the array.
// prerequisite: array is already filled with values
for(int i = 0; i < numArray.length; i++) {
arr[i] += shiftNum;
if (numArray[i] > 30) {
numArray[i] -= 30;
} else if (numArray[i] <= 0) {
numArray[i] += 30;
}
}
According to you code, the array created will contain value from 1 - 30 including 1 and 30. If you want your code to contain values from 0 - 29 instead, change numArray[i] > 30 to numArray[i] >= 30 and change numArray[i] <= 0 to numArray[i] < 0.
Use Java's convenience methods. Most people still want to write for loops. Basically, you need to save off the elements you are overwriting with the shift. Then place those saved ones back in the array. System.arraycopy is nice in that it takes care of some nasty parts of moving elements in an array.
void shift(int shiftBy, int... array) {
int[] holdInts = Arrays.copyOf(array, shiftBy);
System.arraycopy(array, shiftBy, array, 0, array.length - shiftBy);
System.arraycopy(holdInts, 0, array, array.length - shiftBy, holdInts.length);
}
Here is quick fix for you. Please check following code.
Input :
Enter the shift/rotation: 4
Output :
Rotate given array [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
After Rotate [27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
public static void main(String[] args) {
RotationDemo rd = new RotationDemo();
int[] input = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
int k = 0;
Scanner scan = new Scanner (System.in);
try{
System.out.println("\nEnter the shift/rotation:");
int shiftNum = scan.nextInt();
if(shiftNum < 30) {
k = shiftNum;
System.out.println("Rotate given array " + Arrays.toString(input));
int[] rotatedArray = rd.rotateRight(input, input.length, k);
System.out.println("After Rotate " +
Arrays.toString(rotatedArray));
} else {
System.out.println("Shift number should be less than 30");
}
} catch(Exception ex){
} finally {
scan.close();
}
}
public int[] rotateRight(int[] input, int length, int numOfRotations) {
for (int i = 0; i < numOfRotations; i++) {
int temp = input[length - 1];
for (int j = length - 1; j > 0; j--) {
input[j] = input[j - 1];
}
input[0] = temp;
}
return input;
}
Hope this example works.
I'm still a student and I have an assignment in Java where I have to sort an array that compares the first element from the last element until the array is sorted out from highest to lowest. I already did some of the algorithm but it seems it jumps swap number 2 and proceeds to swap3. The program should run like this.
10, 3, 7, 15, 9
10, 3, 7, 15, 9
15, 3, 7, 10, 9 - swap1
15, 3, 7, 10, 9
15, 3, 7, 10, 9
15, 9, 7, 10, 3 - swap2
15, 10, 7, 9, 3
15, 10, 7, 9, 3
15, 10, 7, 9, 3
15, 10, 9, 7, 3 - swap3
15, 10, 9, 7, 3
So here is my algorithm doing this:
public static void main(String[] args) {
int array[] = {10,3,7,15,9};
int f;
int l;
int temp;
System.out.println("Sorting array first and last elements");
for (f = 0; f < array.length; f++)
{
for (l = 4; l > f; l--)
{
if (array[f] < array[l])
{
temp = array[l];
array[l] = array[f];
array[f] = temp;
}
}
System.out.println("sorting....");
for (int c = 0; c < array.length; c++)
System.out.print(array[c] + ",");
}
System.out.println("sorted");
}
The output is:
Sorting array first and last elements
sorting....
15,3,7,10,9,sorting....
15,10,7,9,3,sorting....
15,10,9,7,3,sorting....
15,10,9,7,3,sorting....
15,10,9,7,3,sorted
It does sort but it jumps the swap number 2 and proceeds to swap number 3. How can i do this correctly that the output shows and does not jump the swap number 2?
The outer loop goes from the first element until the end.
The inner loop goes from the last element until the index of the outer loop.
You print the content of the array after the inner loop runs.
That is, you print the content one time per iteration of the outer loop.
Keep in mind that during the inner loop,
multiple swaps can happen.
For example two swaps happen when f=1.
If you want to print the state after each swap,
then do just that, in the inner loop:
for (f = 0; f < array.length; f++) {
for (l = array.length - 1; l > f; l--) {
if (array[f] < array[l]) {
temp = array[l];
array[l] = array[f];
array[f] = temp;
System.out.println(Arrays.toString(array));
}
}
}
This will print:
[15, 3, 7, 10, 9]
[15, 9, 7, 10, 3]
[15, 10, 7, 9, 3]
[15, 10, 9, 7, 3]
I'm trying to get my loop to go through the array 16 times. When I use upCollisions[i], it doesn't work but when I use upCollisions[0] or any other index of the array, it works. I can't understand why it is not working using the for loop.
Here's my code:
public void handleUpArrow()
{
int upCollisions[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,};
for(int i =0; i < 16; i++)
{
if(goldenBallPosition == upCollisions[i])
{
}
else
{
jBGrid[goldenBallPosition].setIcon(imageSand);
jBGrid[goldenBallPosition -16].setIcon(imageBall);
goldenBallPosition -= 16;
jBCompass.setIcon(imageCompassNorth);
jTDirection.setText("N");
jTSquare.setText((""+goldenBallPosition));
}
}
}
There are some problems with your code. First of all it's better to make the work in the if branch, and not in the else. Then I think the problem could be in this line of code:
goldenBallPosition -=16;
If I do undestand correctly your code, it could help if you use a loop like this
for (int i = 15; i >= 0; i--)
Don't you receive an ArrayOutOfBoundException during execution?