BubbleSort 2D array rows by a specific column values - java

I have a two- dimensional array and i want to bubble sort it rows by array second column value.
I take Arrival time and Service time values from user and want to bubble sort it by array second column value(Arrival time).
First column is for process number.
static int[][] atst = new int[5][5];
for (int i = 0; i < atst.length; i++) {
System.out.print("Arrival time for process " + i + ": ");
atst[i][1] = in.nextInt();
}
for (int i = 0; i < atst.length; i++) {
System.out.print("Enter service Times for process " + i + ": ");
atst[i][2] = in.nextInt();
}
System.out.println("Before sorting: " + Arrays.deepToString(atst));
for (int i = 0; i < atst.length; i++) {
for (int j = 1; j < (atst.length - 1); j++) {
if (atst[j - 1][1] > atst[j][1]) { // Then swap!
int[] tempRow = atst[j - 1];
atst[j - 1] = atst[j];
atst[j] = tempRow;
}
}
}
System.out.println("After sorting :" + Arrays.deepToString(atst));
public static void swapRows(int[][] array, int rowA, int rowB) {
int[] tempRow = array[rowA];
array[rowA] = array[rowB];
array[rowB] = tempRow;
}
The swapRows method works, But it does not sort array completely.
result:
Arrival time for process 0: 5
Arrival time for process 1: 4
Arrival time for process 2: 3
Arrival time for process 3: 2
Arrival time for process 4: 1
Enter service Times for process 0: 2
Enter service Times for process 1: 3
Enter service Times for process 2: 4
Enter service Times for process 3: 5
Enter service Times for process 4: 2
Before sorting: [[0, 5, 2, 0, 0], [1, 4, 3, 0, 0], [2, 3, 4, 0, 0], [3, 2, 5, 0, 0], [4, 1, 2, 0, 0]]
After sorting :[[3, 2, 5, 0, 0], [2, 3, 4, 0, 0], [1, 4, 3, 0, 0], [0, 5, 2, 0, 0], [4, 1, 2, 0, 0]]
Whereas the result should be like this:
[[4, 1, 2, 0, 0],[3, 2, 5, 0, 0],[2, 3, 4, 0, 0],[1, 4, 3, 0, 0],[0, 5, 2, 0, 0]]

In your updated code, the bounds of your inner loop are incorrect:
for (int j = 1; j < (atst.length - 1); j++) {
You are excluding your last element by subtracting 1 here, which is why the rest of the array is sorted except for the last element. Should be:
for (int j = 1; j < atst.length; j++) {

Related

How to sort array based on multiples of 3 using Java

I have an array like this one-
{1, 2, 3, 4, 5, 6}
I want to sort it in the order of multiples of 3 with remainders 0, 1 and 2. (the first group is multiples of 3, the second one is multiples of 3 with remainder 1 and the last one is multiples of 3 with remainder 2) and I want to preserve the order in which elements appear in the array.
The result should be -
{3, 6, 1, 4, 2, 5}
I have this code-
int current = 0;
int b = 0;
for (int i = 0; i < 3; i++) { //3 groups
for (int j = current; j < numbers.length; j++) {
if (numbers[j] % 3 == i) { //reminder should be 0,1 or 2
b = numbers[j];
numbers[j] = numbers[current];
numbers[current] = b;
current++;
}
}
}
But this code does not preserve the order in which elements appear in the array. The result I got is-
{3, 6, 1, 4, 5, 2}
But I want the result to be like {3, 6, 1, 4, 2, 5}. How can I achieve this?
Using stream and comparator
int[] array = {1, 2, 3, 4, 5, 6};
List<Integer> lst = Arrays.stream(array)
.boxed()
.sorted(Comparator.comparingInt(o -> o % 3))
.collect(Collectors.toList());
System.out.println(lst);
In your solution you are swapping the elements in place, which shuffles them from the initial order. That's why you don't have the same ordering at the end. I'm not sure if there is another way apart from having a second array to keep the sorted elements, while at the same time iterating over the original one like so:
public static void main(String[] args) {
int[] numbers = new int[]{1, 2, 3, 4, 5, 6};
int[] result = new int[numbers.length];
int b = 0;
int current = 0;
for (int i = 0; i < 3; i++) { //3 groups
for (int j = 0; j < numbers.length; j++) {
if (numbers[j] % 3 == i) { //reminder should be 0,1 or 2
result[current] = numbers[j];
current++;
}
}
}
System.out.println(Arrays.toString(result));
}
Output: [3, 6, 1, 4, 2, 5]
You can use an IntStream and a Comparator to sort the stream:
int[] arr = {1, 2, 3, 4, 5, 6};
int[] arrSorted = IntStream.of(arr).boxed()
.sorted(Comparator.comparingInt(i -> i % 3))
.mapToInt(Integer::intValue)
.toArray();
System.out.println(Arrays.toString(arrSorted));
Output:
[3, 6, 1, 4, 2, 5]
Note: From IntStream.of() javadoc:
Returns a sequential ordered stream whose elements are the specified
values.
I would create a new array of the same size and then place the elements in the correct order. For example like this:
int[] array = {1, 2, 3, 4, 5, 6};
int[] sorted = new int[array.length];
int counter = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < array.length; j++) {
if (array[j] % 3 == i) {
sorted[counter] = array[j];
counter++;
}
}
}
System.out.println(Arrays.toString(sorted));
Output:
[3, 6, 1, 4, 2, 5]
Alternatively, you can use Java 8 features to reduce the amount of code like this:
int[] array = {1, 2, 3, 4, 5, 6};
int[] sorted = Arrays.stream(array).boxed().sorted(Comparator.comparingInt(a -> (a % 3))).mapToInt(i -> i).toArray();
Output:
[3, 6, 1, 4, 2, 5]

Why does this array rotation program give 0 as output?

The program is supposed to shift all values in the array to the right. Please help with what I have done wrong...
int[] array = new int[] {1, 2, 3, 4, 5};
int[] rotated = new int [array.length];
int rotationTimes = scan.nextInt();
if (rotationTimes > 4){
rotationTimes %= 5;
}
for (int i = 0; i <= rotationTimes; i++){
if (i == 4) {
rotated[0] = array[4];
break;
}
array[i] = rotated[i + 1];
}
System.out.println(Arrays.toString(rotated));
The expected output should be {5, 1, 2, 3, 4}. It outputs an array of 0s...
Thank you a lot.
You weren't populating the rotated array. You were modifying the array reference!
You were checking if index == 4 when you could do array.length - 1.
You need to determine the target index as being (index + rotationTimes) then if it exceeds array.length - 1 (the last index) you use the modulus operator to make sure it doesnt overflow. For example, if the current index is 4 (the last one) and the iterations is 1, (4 + 1) is greater than 4 so the target index is (4 + 1) % 5 = 0.
public static void main(String[] args) {
int[] array = new int[] {1, 2, 3, 4, 5};
int[] rotated = new int [array.length];
System.out.println("Enter amount of times to rotate: ");
Scanner scan = new Scanner(System.in);
int rotationTimes = scan.nextInt();
if (rotationTimes > 4){
rotationTimes %= 5;
}
for (int index = 0; index < array.length; index++) {
int targetIndex = index + rotationTimes;
if (targetIndex > array.length - 1) {
targetIndex %= array.length;
}
rotated[targetIndex] = array[index];
}
System.out.println("Input: " + Arrays.toString(array));
System.out.println("Rotations: " + rotationTimes);
System.out.println("Output: " + Arrays.toString(rotated));
}
Input: [1, 2, 3, 4, 5]
Rotations: 1
Output: [5, 1, 2, 3, 4]
Input: [1, 2, 3, 4, 5]
Rotations: 2
Output: [4, 5, 1, 2, 3]

Fibonacci Sequence printing out all values in an array EDIT

Okay my new question is how I can let the array print out all numbers of the segment. At the moment I can input a number and the code will print out the corresponding value in Fibonacci. However, I would like the array to print out all values leading up to the answer. Ex. Input = 7, array prints out 0, 1, 1, 2, 3, 5, 8 instead of just 8
package math;
public class Fibonacci {
public static long getFib(int n) {
long Fibby[] = new long[n+1];
Fibby[0] = 1;
Fibby[1] = 1;
for(int i = 2; i<=n; i++) { //initialize loop
Fibby[i] = Fibby[i-1] + Fibby[i-2];
} // end of for loop
return Fibby[n]; //end method getfib
}
}
And the runner
package math;
Scanner key = new Scanner(System.in);
Fibonacci f = new Fibonacci();
int p;
System.out.println("Fib value : ");
p = key.nextInt();
System.out.println( "Fib Value of "+ p +" :: " + f.getFib(p) );
}
How can this happen? My question has been downsized.
You can't run your main method, because System.out.println() expects a parameter it can print. However, your fib() method returns void, so there is nothing to print. Add a return type to your fib() method, and your error in main() will be resolved. Here's a demonstration of printing the 0th to 12th Fibonacci numbers:
FibonacciRunner.java
public class FibonacciRunner
{
public static void main(String[] args)
{
for(int i = 0; i <= 12; i++)
{
System.out.println(Fibonacci.fib(i));
}
for(int i = 0; i <= 12; i++)
{
System.out.println(Fibonacci.fibList(i));
}
}
}
Fibonacci.java
public class Fibonacci
{
public static long fib(int n)
{
long current = 0;
long next = 1;
for(int i = 0; i < n/2; i++)
{
current += next;
next += current;
}
return n % 2 == 0 ? current : next;
}
public static List<Long> fibList(int n)
{
List<Long> ret = new ArrayList<>(n == 0 ? List.of(0L) : List.of(0L, 1L));
long current = 0;
long next = 1;
for(int i = 0; i < n/2; i++)
{
current += next;
next += current;
if(i*2+1 <= n)
ret.add(current);
if(i*2+2 < n)
ret.add(next);
}
return ret;
}
}
Output:
0
1
1
2
3
5
8
13
21
34
55
89
144
[0]
[0, 1]
[0, 1, 1]
[0, 1, 1, 2]
[0, 1, 1, 2, 3]
[0, 1, 1, 2, 3, 5]
[0, 1, 1, 2, 3, 5, 8]
[0, 1, 1, 2, 3, 5, 8, 13]
[0, 1, 1, 2, 3, 5, 8, 13, 21]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
One problem with your code is that Fibonacci.fib doesn't return anything, so what are you expecting the FibonacciRunner to print?
Another is that arrays in Java have fixed length. Consider using a List instead:
List fibby = new ArrayList();
fibby.add(0);
fibby.add(1);
for (int i = 2; i < n; i++){
fibby.add(fibby.get(i - 1) + fibby.get(i - 2));
}

Rearranging (swapping) array values

I'm trying to solve the fix34 problem of CodingBat:
Return an array that contains exactly the same numbers as the given array, but rearranged so that every 3 is immediately followed by a 4. Do not move the 3's, but every other number may move. The array contains the same number of 3's and 4's, every 3 has a number after it that is not a 3, and a 3 appears in the array before any 4.
fix34([1, 3, 1, 4]) → [1, 3, 4, 1]
fix34([1, 3, 1, 4, 4, 3, 1]) → [1, 3, 4, 1, 1, 3, 4]
fix34([3, 2, 2, 4]) → [3, 4, 2, 2]
My code works for all cases except:
1. fix34([1, 3, 1, 4, 4, 3, 1])
→ [1, 3, 4, 1, 1, 3, 4] (Expected)
[1, 3, 4, 1, 4, 3, 1] (Actual Output)
2. fix34([5, 3, 5, 4, 5, 4, 5, 4, 3, 5, 3, 5])
→ [5, 3, 4, 5, 5, 5, 5, 5, 3, 4, 3, 4] (Expected)
[5, 3, 4, 5, 5, 4, 5, 4, 3, 5, 3, 5] (Actual Output)
Can't seem to figure out why, thanks in advance!
public int[] fix34(int[] nums) {
int [] result = new int [nums.length];
int temp = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] == 3){
result[i] = 3;
for(int j = i + 1; j < nums.length; j++){
if(nums[j] == 4){
temp = nums[i + 1];
result[i + 1] = 4;
result[j] = temp;
nums[j] = temp;
break;
}
}
}else if(result[i] == 0){
result[i] = nums[i];
}
}
return result;
}
The pseudo-code for your current implementation is:
for (each_element_in_nums) {
if (that_element_is_a_3) {
scan_the_following_elements_for_a_4;
if (we_found_a_4) {
swap_that_4_with_the_element_immediately_following_the_3;
}
}
}
The unsuccessful test cases are failing when no 4 appears after the 3 you are trying to pair up. Based on the expected output
1. fix34([1, 3, 1, 4, 4, 3, 1])
→ [1, 3, 4, 1, 1, 3, 4] (Expected)
your code will also have to be able to move a 4 that appears before the 3 you are currently working on, as shown in the second swap below:
↔↔
↕ ↕
[1, 3, 1, 4, 4, 3, 1]
↕ ↕
↔↔↔↔↔
In other words, your current code can only move a 4 to the left. You'll also need to be able to move a 4 to the right.
Here is a fairly simple implementation that seems to do the trick:
/**
* Returns an array with elements rearranged.
* <p>
* Rules:<br>
* 1. [input] The array contains the same number of 3's and 4's.<br>
* 2. [input] Every 3 has a number after it that is not a 3.<br>
* 3. [input] A 3 appears in the array before any 4.<br>
* 4. [output] Return an array that contains exactly the same numbers as the
* given array, but rearranged so that every 3 is immediately
* followed by a 4.<br>
* 5. [output] Do not move the 3's, but every other number may move.<br>
*/
public static int[] fix34(int[] nums) {
if (nums.length > 0 && nums[nums.length - 1] == 3) {
// bulletproofing: Really should not happen, per rule #2
throw new IllegalArgumentException("Input array cannot end with a 3");
}
List<Integer> positionOf3s = new ArrayList<>();
List<Integer> positionOf4s = new ArrayList<>();
int[] result = nums.clone();
for (int resultArrayIndex = 0; resultArrayIndex < result.length; resultArrayIndex++) {
if (result[resultArrayIndex] == 4) {
positionOf4s.add(resultArrayIndex); // position of swap candidate
} else if (result[resultArrayIndex] == 3) {
if (result[resultArrayIndex + 1] == 3) {
// bulletproofing: Really should not happen, per rule #2
throw new IllegalArgumentException("Input array cannot contain two successive 3's");
} else if (result[resultArrayIndex + 1] == 4) {
// 3 already paired with 4, so no need to move, just skip the 4
resultArrayIndex++;
} else {
// this 3 is lonely, so add its position to the list to be paired
positionOf3s.add(resultArrayIndex);
}
}
}
if (positionOf3s.size() > positionOf4s.size()) {
// bulletproofing: Really should not happen per rule #1
throw new IllegalArgumentException(
String.format("3's needing to be paired: %d; 4's available for swapping: %d",
positionOf3s.size(), positionOf4s.size()));
}
/*
* perform swap for each "lonely" 3 in listOf3sIndex, using the corresponding
* swap candidate from positionOf4s
*/
for (int listOf3sIndex = 0; listOf3sIndex < positionOf3s.size(); listOf3sIndex++) {
result[positionOf4s.get(listOf3sIndex)] = result[positionOf3s.get(listOf3sIndex) + 1];
result[positionOf3s.get(listOf3sIndex) + 1] = 4;
}
return result;
}

How to separate range of integers into two equal parts

I have an array of integers like this one
int [] num = {5, 8, 1, 1, 2, 3, 2}
and I want to divide it into 2 parts, so that the total of 2 sets will be as equal as possible: (output)
SET 1: 5 Piece(s)
1
1
2
2
5
Total: 11
SET 2: 2 Piece(s)
8
3
Total: 11
another example is
int [] num = {4, 6, 1, 2, 3, 3, 4}
with output like this:
SET 1: 3 Piece(s)
3
4
4
Total: 11
SET 2: 4 Piece(s)
6
1
2
3
Total: 12
any help? =) thanks
If the array is not too long, try a lazy solution: brute-force. Since all you need is to separate it into two sets, you'll need to check 2^n possibilities, because a number is either in the first set or not (i.e. in the second set).
Here's a sample code I just wrote:
public static int[][] bruteForce(int[] input) {
int n = input.length;
int[][] res = new int[2][n];
int minVal = Integer.MAX_VALUE;
int iMinVal = 0;
int limit = (int) Math.pow(2, n);
for (int i = 0; i < limit; i++) {
int v = i;
int diff = 0;
for (int j = 0; j < n; j++) {
diff = diff + ((v & 1) == 0 ? +1 : -1) * input[j];
v = v >> 1;
}
if (Math.abs(diff) < minVal) {
iMinVal = i;
minVal = Math.abs(diff);
}
}
int a = 0, b = 0;
for (int i = 0; i < n; i++) {
if ((iMinVal & 1) == 0) {
res[0][a++] = input[i];
} else {
res[1][b++] = input[i];
}
iMinVal = iMinVal >> 1;
}
return res;
}
public static void main(String[] args) {
int[] num = {5 ,8 ,1 ,1 ,2 ,3 ,2};
int[] num2 = {4, 6, 1, 2, 3, 3, 4};
int[][] r = bruteForce(num);
System.out.println("First example:");
System.out.println(Arrays.toString(r[0])+ ", sum = "+Arrays.stream(r[0]).sum());
System.out.println(Arrays.toString(r[1])+ ", sum = "+Arrays.stream(r[1]).sum());
r = bruteForce(num2);
System.out.println("Second example:");
System.out.println(Arrays.toString(r[0])+ ", sum = "+Arrays.stream(r[0]).sum());
System.out.println(Arrays.toString(r[1])+ ", sum = "+Arrays.stream(r[1]).sum());
}
output:
First example:
[5, 1, 3, 2, 0, 0, 0], sum = 11
[8, 1, 2, 0, 0, 0, 0], sum = 11
Second example:
[2, 3, 3, 4, 0, 0, 0], sum = 12
[4, 6, 1, 0, 0, 0, 0], sum = 11
If the length of the array is big, then I guess try some smart brute-force, or other methods. Like, sorting the array into non-ascending order, then starting from the biggest value, put each value into the array with less sum, which in the current case give the right answer:
public static int[][] alternative(int[] input) {
int n = input.length;
int[][] res = new int[2][n];
int[] input0 = Arrays.copyOf(input, n);
Arrays.sort(input0);
System.out.println("Input: "+Arrays.toString(input)+", ordered: "+Arrays.toString(input0));
int sum1 = 0, sum2 = 0;
int a = 0, b = 0;
for (int i = n-1; i >= 0; i--) {
if (sum1 <= sum2) {
res[0][a++] = input0[i];
sum1 = sum1 + input0[i];
System.out.println("Adding "+input0[i]+" into set 1 ==> Sum1 = "+sum1);
} else {
res[1][b++] = input0[i];
sum2 = sum2 + input0[i];
System.out.println("Adding "+input0[i]+" into set 2 ==> Sum2 = "+sum2);
}
}
return res;
}
output:
First example:
Input: [5, 8, 1, 1, 2, 3, 2], ordered: [1, 1, 2, 2, 3, 5, 8]
Adding 8 into set 1 ==> Sum1 = 8
Adding 5 into set 2 ==> Sum2 = 5
Adding 3 into set 2 ==> Sum2 = 8
Adding 2 into set 1 ==> Sum1 = 10
Adding 2 into set 2 ==> Sum2 = 10
Adding 1 into set 1 ==> Sum1 = 11
Adding 1 into set 2 ==> Sum2 = 11
[8, 2, 1, 0, 0, 0, 0], sum = 11
[5, 3, 2, 1, 0, 0, 0], sum = 11
Second example:
Input: [4, 6, 1, 2, 3, 3, 4], ordered: [1, 2, 3, 3, 4, 4, 6]
Adding 6 into set 1 ==> Sum1 = 6
Adding 4 into set 2 ==> Sum2 = 4
Adding 4 into set 2 ==> Sum2 = 8
Adding 3 into set 1 ==> Sum1 = 9
Adding 3 into set 2 ==> Sum2 = 11
Adding 2 into set 1 ==> Sum1 = 11
Adding 1 into set 1 ==> Sum1 = 12
[6, 3, 2, 1, 0, 0, 0], sum = 12
[4, 4, 3, 0, 0, 0, 0], sum = 11
For the 0s in the output, you can just write a simple function that create a new arrays without the 0s.
Have a for loop to loop like:
int sum =0:
for(int I=0; I<num.length/2; I++){
System.out.println(num[i]);
sum=sum+num[i];
}
System.out.println(sum);
(Written on ipad excuse any mistakes plz.
We should try with all combinations. For example, if the array is (1,1,100,100), then answer is (100,1) (100,1). If the array is (1,1,50,100) then answer is (1,1,50) (100). I don't think there is any short cut to this. If the array has N elements, then we shall try all combinations (Nc1, NcN01), (Nc2, NcN-2) .. and so on. Then find which of their difference is least.

Categories