Sorting 2D String Array with BUBBLESORT in java - java

Similar questions have been asked but never about 2D String Arrays, therefore after trying for a long time I couldn't find what I wanted. I'm trying to sort a 2D String Array in java using BubbleSort.
As input, I receive a two-dimensional array (a table) of Strings and the index of the “column” you should sort. I should sort the rows by the values in the indicated column.
You can see the first index as a row index, and the second index as a column index. For example, the following Java array and table correspond with each other:
String[][] table = {
{"a", "b"},
{"c", "d"}
};
-
0 1
+---+---+
0 | a | b |
+---+---+
1 | c | d |
+---+---+
To continue on this example, table[0][1] will yield the value "b", since it’s the item in row 0 and column 1.
IMPORTANT: I am not allowed to use any sorting algorithm from the Java library, for example Arrays.sort.
This is what I've tried so far:
class Solution {
public static void stableSort(String[][] table, int column) {
int i;
int j;
String temp = null;
for (i = 0; i < table.length - 1; i++) {
for (j = 0; j < table.length - 1 - i; j++) {
if (table[i][j].compareTo(table[i][j + 1]) > 0) {
temp = table[i][j];
table[i][j] = table[i][j + 1];
table[i][j + 1] = temp;
}
}
}
}
}
I get an Index out of Bounds error and also it is not working as the test expects a different result in table[0][0]
Thanks for your help.

public static String[][] stableSort(String[][] table, int column) {
int i=0,j=0;
String[] temp = null;
boolean swap=true;
while(swap)
for (i = 0; i < table.length - 1; i++) {
swap=false;
if(table[i][column].compareTo(table[i+1][column]) > 0){
temp = table[i];
table[i] = table[i+1];
table[i+1]=temp;
swap=true;
}
}
return table;
}
It keeps applying the bubblesort until no more swaps are performed. At that point,the condition while(swap) is no longer satisfied and the method returns.
Tried in a main and it works (if I understand what you meant):
public static void main(String[] args) {
String[][] table = {
{"z", "b", "v"},
{"s", "w", "a"},
{"r", "c", "h"}
};
table = stableSort(table,1);
for(int i = 0; i < table.length; i++){
for(int j = 0; j < table[0].length; j++){
System.out.printf("%5s ", table[i][j]);
}
System.out.println();
}
}
this outputs:
z b v
r c h
s w a

to start, make it a 1d array
or at least 1d indexable
much easier
formula:
x = (int)index/(int)rows
y = index % rows
with that you can use 1 variable index
and index a 2d array
and this is a bubblesort
def sort(self):
for passnum in range(len(self.array)-1,0,-1):
for i in range(passnum):
if self.array[i]>self.array[i+1]:
temp = self.array[i]
self.array[i] = self.array[i+1]
self.array[i+1] = temp

EDIT: Working and no errors
If I take your exact sort but add a if statement for the switching of rows, add an exterior loop to run through the 2D array the length times the width and change the for loop control to '<=' then I get the following
for(int z = 0; z < table.length * table.length; z++) // exterior for loop to run through the loop multiple times
{
for (i = 0; i <= table.length - 1; i++) {
for (j = 0; j <= table.length - 1; j++) {
if(j == table.length -1 && i == table.length-1) // If we are at the end then we can continue either to the next iteration or to the end of program
continue;
if(j == table.length -1) // If you are ate the end of the row compare to the next row
{
if (table[i][j].compareTo(table[i+1][0]) > 0) {
temp = table[i][j];
table[i][j] = table[i+1][0];
table[i+1][0] = temp;
}
}
else if (table[i][j].compareTo(table[i][j + 1]) > 0) {
temp = table[i][j];
table[i][j] = table[i][j + 1];
table[i][j + 1] = temp;
}
}
}
}
I saw what you were trying to do by minimizing the number of checks when you put
table.length - 1 - i
That is good for efficiency but first attempt to get the sorting working. then trim it down to preform better.
Also I don't have a compiler in-front of me so code could have some errors

My working solution:
import java.util.Arrays;
public class MySolution {
public static void stableSort(String[][] table, int column) {
String[] temp = null;
int rows = table.length;
for (int i = 0; i < rows; i++) {
for (int j = 1; j < (rows - i); j++) {
if (table[j - 1][column].compareTo(table[j][column]) > 0) {
temp = table[j - 1];
table[j - 1] = table[j];
table[j] = temp;
}
}
}
}
public static void main(String[] args) {
String[][] table = { { "c", "d" }, { "a", "b" } };
printTable(table);
stableSort(table, 1);
printTable(table);
}
private static void printTable(String[][] table) {
System.out.println("table:");
for (int i = 0; i < table.length; i++) {
System.out.println(Arrays.toString(table[i]));
}
}
}
some notes for you:
use meaningful names (rows is easier to understand than table.length)
bubble sort loops were a bit off, there are plenty of examples of how to do it online
as mentioned, you should start by doing it for 1d array and then "generalize" it
one big issue you had: using j (which should be the index of the row to compare to) as the column (and ignoring column)
another big issue is only substituting the element (instead of the rows)
I hope this helps you!
EDIT: I just noticed you've also switched between row and column in your code (in your explanation the first index denotes the row, in your code it seems like the opposite is correct)

Related

java array for zigzag works, but tester keeps telling me there's an error?

I have this line of code to create a zigzag array, its fairly simple and I already have the code for it. here's the summary of the question:
This method creates and returns a new two-dimensional integer array, which in Java is really just a one-dimensional array whose elements are one-dimensional arrays of type int[]. The returned array must have the correct number of rows that each have exactly cols columns. This array must contain the numbers start, start + 1, ..., start + (rows * cols - 1) in its rows in order, except that the elements in each odd-numbered row must be listed in descending order.
For example, when called with rows = 4, cols = 5 and start = 4, this method should create and return the two-dimensional array whose contents are
4 5 6 7 8
13 12 11 10 9
14 15 16 17 18
23 22 21 20 19
I've tried talking with my colleagues but they can't spot the problem too
public class P2J1
{
public static int[][] createZigZag(final int rows, final int cols, int start)
{
final int[][] array = new int[rows][cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = start;
start++;
}
}
return array;
}
}
/// heres the tester program
#Test public void testCreateZigZag() {
Random rng = new Random(SEED);
CRC32 check = new CRC32();
for(int i = 0; i < TRIALS; i++) {
int rows = rng.nextInt(20) + 1;
int cols = rng.nextInt(20) + 1;
int start = rng.nextInt(100);
int[][] zig = P2J1.createZigZag(rows, cols, start);
assertEquals(rows, zig.length);
for(int j = 0; j < rows; j++) {
assertEquals(cols, zig[j].length);
for(int e: zig[j]) { check.update(e); }
}
}
assertEquals(3465650385L, check.getValue());
}
Your column index always goes from 0 to cols-1, in that order. You need to alternate the order every other row.
You can do this by using variables for the start, end, and increment of the inner loop and assign those variables based on the row index being odd or even.
Something like this (untested):
public static int[][] createZigZag(final int rows, final int cols, int start) {
final int[][] array = new int[rows][cols];
for (int i = 0; i < rows; i++) {
boolean backwards = ((i & 1) == 1);
final int jStart = backwards ? cols-1 : -1;
final int jEnd = backwards ? 0 : cols;
final int jStep = backwards ? -1 : 1;
for (int j = jStart; j != jEnd; j += jStep) {
array[i][j] = start;
start++;
}
}
return array;
}
You could also just write two different inner loops, selected on the same condition. One would fill starting from 0, the other would fill starting from cols-1 and going backwards.
public static int[][] createZigZag(final int rows, final int cols, int start) {
final int[][] array = new int[rows][cols];
for (int i = 0; i < rows; i++) {
if ((i & 1) == 1) {
for (int j = cols-1; j >= 0; j--) {
array[i][j] = start;
start++;
}
} else {
for (int j = 0; j < cols; j++) {
array[i][j] = start;
start++;
}
}
}
return array;
}

Java – Working with 2 dimensional array and constructor (Beginner)

This post is going to be really long, but I would be so glad if the community can help me.
This is a question from a former class test. I have to expect a similar one this time and I'm currently stuck. I'm new to Java and its concepts.
The result of the test should look like this:
The result
I'm facing multiple problems at once. I will try to be as specific as I can. First I will explain the task, which has given conditions that can't be changed.
The task
Create an array field with 2 dimensions. The field should work with various sizes. Besides the size, the array field should contain the following pattern(see picture).
1.) Create an constructor that creates a rectangle array field from the parameter passed in, with to extra conditions.
1.1) If the parameter is less than 5, the field should be forced to appear as a 5/5 field.
1.2) If the paramter is more than 5 it should always appear as an n/n array.
public class Pattern {
char[][] field;
public Pattern(int n) {
// Here goes my code for creating the field
}
2.) Write a method that fills the constructor.
public void fillArray() {
// Here goes my code.
}
My approach so far
public Pattern(int n) {
field = new char[n][n];
int i, j;
if (field.length < 5) {
for (i = 1; i <= 5; i++) {
for (j = 1; j <= 5; j++) {
// ? what to do with the array here?
}
System.out.println();
}
}
public void fillArray() {
// no fu**ing idea...
}
public static void main (String[]args){
Pattern cross = new Pattern(2);
cross.fillArray();
System.out.println(cross);
}
Questions
1.) What value should be returned in the constructor?
2.) How can I access the object in the method and set a for loop, that gets the predefined field size? Should I use this ?
I'm sorry for my bad understanding on how to pass array information and execute these correctly.
public class Pattern {
private final int size;
private final char[][] field;
public Pattern(int n) {
size = Math.max(n, 5);
field = new char[size][size];
}
public void fillArray() {
for (int row = 0, i = size - 1; row < size; row++, i--) {
for (int col = 0, j = size - 1; col < size; col++, j--) {
if (row == col || row == j)
field[row][col] = '*';
else if (col > row)
field[row][col] = col < i ? '1' : '2';
else
field[row][col] = col > i ? '3' : '4';
}
}
}
public void print() {
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++)
System.out.print(field[row][col] == '\0' ? ' ' : field[row][col]);
System.out.println();
}
}
public static void main(String... args) {
Pattern cross = new Pattern(2);
cross.fillArray();
cross.print();
}
}
You are putting what should be in fillArray in the constructor. The constructor should just be this:
public Pattern(int n) {
if (n < 5) {
field = new char[5][5];
} else {
field = new char[n][n];
}
}
And the two for loops should be in the fillArray method:
public void fillArray() {
// you should loop until field.length and field[x].length
for (int x = 0; x < field.length; x++) {
for (int y = 0; y < field[x].length; y++) {
// ...
}
}
}
Try to write your own logic of how to fill in the array.
If you are stuck, here is my solution:
for (int x = 0 ; x < field.length ; x++) {
for (int y = 0 ; y < field[x].length ; y++) {
/*
The '1' area can be represented by these inequalities:
x - y < 0
x + y < array.length - 1
The '2' area can be represented by these inequalities:
x - y < 0
x + y > array.length - 1
The '3' area can be represented by these inequalities:
x - y > 0
x + y > array.length - 1
The '4' area can be represented by these inequalities:
x - y > 0
x + y < array.length - 1
Everywhere that does not satisfy any of the inequalities are *s
*/
int xMinusY = x - y;
int xPlusY = x + y;
if (xMinusY < 0 && xPlusY < field.length - 1) {
field[x][y] = '1';
} else if (xMinusY < 0 && xPlusY > field.length - 1) {
field[x][y] = '2';
} else if (xMinusY > 0 && xPlusY > field.length - 1) {
field[x][y] = '3';
} else if (xMinusY > 0 && xPlusY < field.length - 1) {
field[x][y] = '4';
} else {
field[x][y] = '*';
}
}
}
// ...
// printing the array out:
for (int x = 0 ; x < field.length ; x++) {
for (int y = 0 ; y < field.length ; y++) {
System.out.print(field[x][y]);
}
System.out.println();
}
Answers to your questions:
Constructors does not return anything.
You don't need to use "this" since the 2-dimensional array is a field which can be accessed anywhere in the class Pattern. If you want to access the size of the array, you can use field.length.
Before you fill the array, you should first check if n is less than 5 (if it is, it should be set to 5). This is done in the constructor. Then you create the array.
After that, you have the for loops in which you have to figure out how to create the pattern. This should be done in the fillArray method.
Okay, so here is the solution. To get this kind of patterns draw it first on paper, then just write the columns and rows and search for the Pattern.
The only way you can learn this is by practice.
A constructor is like a method but does not have a return and uses the name of the Class.
The constructor will be always called when you instanciate a new Object of that class.
Example:
Pattern p = new Pattern(3);
Leave the constructor for the things you will need to do when you create an Object of that class. In your case decide the size of your Pattern.
Example:
public Pattern(int fS) { //fS = fieldSize
if (fS < 5)
fS = 5;
field = new char[fS][fS];
}
Then you have the methods, once an Object is created you can use all the methods from his Instance. In your case you will have a method called "fillArray".
Solution:
public void fillArray() {
int fS = field.length;
char c = ' ';
int len = fS - 1;
for (int row = 0; row < fS; row++)
for (int col = 0; col < fS; col++) {
if (row == col || row + col == len) c = '*';// This will make the asterisc cross
if (row < col && row < len - col) c = '1'; //This will do the 1 part
if (row < col && row > len - col) c = '2'; //This will do the 2 part
if (row > col && row > len - col) c = '3';//This will do the 3 part
if (row > col && row < len - col) c = '4';//This will do the 4 part
field[row][col] = c;
}
}
Remember:
In this case your Array will be not filled until you call the method fillArray()
Example:
Pattern p = new Pattern(7);
p.fillArray();
To print your Pattern I recommend you use the toString() method. You will need to Override it.
How to:
#Override //Important
public String toString() {
StringBuilder s = new StringBuilder();
for (char[] row : field) {
for (char col : row)
s.append("\t").append(col);
s.append("\n");
}
return s.toString();
}
Use the "#Override" tag to see if you did any typo writing the mehod toString. Now to print your pattern use:
Pattern p = new Pattern(7);
p.fillArray();
System.out.println(p); //This line
PD: Sorry if I did any grammar mistake my mother language is not english. Hope it helps.

Cant get required output from loop

I am trying to get a certain output pattern from the array but can't seem to get what I'm looking for and now sure why. Link is the desired output. Sorry if formatting is not good. Array size is inputted by the user.
public class A3_Q2 {
int [][] pattern2 = new int[arraySize][arraySize];
number = 1;
int i;
int j;
int newNumber = arraySize-1;
for (i = 0; i < arraySize; i++)
{
if (i == 0)
{
for (j = 0; j < arraySize; j++)
{
pattern2[i][j] = number;
System.out.printf("%3d", pattern2[i][j]);
number++;
}
}
else
{
for(j = 0; j < i; j++)
{
pattern2[i][j] = number + newNumber;
System.out.printf("%3d", pattern2[i][j]);
newNumber++;
}
newNumber = arraySize-1;
while(j < arraySize)
{
pattern2[i][j] = number;
System.out.printf("%3d", pattern2[i][j]);
number++;
j++;
}
}
System.out.println("");
}
Desired Output:
1 2 3 4 5
10 6 7 8 9
14 15 11 12 13
18 19 20 16 17
22 23 24 25 21
This image shows the out-of-sequence cells highlighted:
There is no need to separately handle specific rows. Value should be calculated with formula that can be applied universally using modulo operator.
This should do the trick:
for (i = 0; i < arraySize; i++) {
for (j = 0; j < arraySize; j++) {
int value = i * arraySize + (j - i + arraySize + 1) % arraySize;
if (value % arraySize == 0) {
value += arraySize;
}
pattern2[i][j] = value;
System.out.printf("%3d", pattern2[i][j]);
}
System.out.println("");
}
As I suggested in my comment, you're trying to do too many things at once, and that makes the logic (and logic errors) very hard to see.
Breaking each part into its own method can make things much easier.
All those loops and conditionals hid that there were only three tasks required:
Create grid.
Fill grid.
Print grid.
public static void main(final String[] args) {
final int arraySize = 5;
int[][] pattern = new int[arraySize][arraySize];
fillPattern(pattern);
printPattern(pattern);
return;
}
That weird non-sequential output means that "fill the grid" is actually too big a task for one method.
Filling a grid normally requires filling each row.
This grid also requires rotating each row's values one to the right...
one more than the previous row, that is.
That has nothing to do with filling a grid with rows, so it's some other method's problem.
(I could have foisted rowStartValue off onto the other method too, come to think of it.)
private static void fillPattern(int[][] pattern) {
final int rowCount = pattern.length;
for (int rowOffset = 0; rowOffset < rowCount; rowOffset++) {
final int[] row = pattern[rowOffset];
// Numbers in grid start at 1, not 0.
final int rowStartValue = rowOffset * row.length + 1;
fillRow(row, rowOffset, rowStartValue);
}
return;
}
fillRow has to produce values and stuff them into row.
Producing the values is easy;
the only tricky part is deciding where to put them.
Picking the destination required only two operators, so I did it here.
Since no one wants to figure out what row[some / weird * math % here] means, I gave the calculation a name by saving it as the rowIndex variable.
If it had been any more complex, I would have moved the work to a rowIndex(...) method instead.
private static void fillRow(int[] row, final int offset, final int value) {
for (int addend = 0; addend < row.length; addend++) {
final int rowIndex = (offset + addend) % row.length;
row[rowIndex] = value + addend;
}
return;
}
Now that the grid is full, printing it is easy:
private static void printPattern(final int[][] pattern) {
for (final int[] row : pattern) {
for (final int element : row) {
System.out.printf("%3d", element);
}
System.out.println();
}
return;
}
Replacing variables like i and j with row and offset helped a lot, too.

Inplace quick sort

Write a java program to sort a list of integers using ‘in place’ Quicksort algorithm.
Generate the list randomly every time using the java.util.Random class.
Allow the user to choose the size of the array. The program should display the result of sorting the array of that size using different pivot choices. In particular, try these 4 choices –
 First element as pivot
 Randomly choosing the pivot element
 Choosing the median of 3 randomly chosen elements as the pivot
 Median of first center and last element (book technique).
PLEASE dont give me the implementation because I would like to try on my own. I want to know what is inplace quick sort? How is it different from the regular quiksort. Is it regular quicksort. I am really confused. I would like someone to provide the pusedocode or explanation in plain english will help too.
Inplace sorting - it's when you operate on the original array, given to you from outside, as opposed to creating some new arrays and using them in any way. Inplace sorting takes O(1) space, as opposed to O(n)+ when using additional data structres
Example of inplace sort:
public static void simpleBubbleSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 1; j < arr.length; j++) {
if (arr[j - 1] > arr[j]) {
swap(arr, j - 1, j);
}
}
}
}
As opposed to Merge sort that creates arrays along the way, and by the end combines them and returns NOT the original (given to us) array, but an array containing the result.
public static int[] mergeSort(int[] arr) {
if (arr.length < 2) return arr;
int mid = arr.length / 2;
int[] left = new int[mid];
int[] right = new int[mid + arr.length % 2];
int j = 0;
for (int i = 0; i < arr.length; i++) {
if (i < mid) {
left[i] = arr[i];
} else {
right[j++] = arr[i];
}
}
// keeps going until there's 1 element in each array[]
return mergeReturn(mergeSort(left), mergeSort(right));
}
private static int[] mergeReturn(int[] leftArr, int[] rightArr) {
int leftPointer = 0, rightPointer = 0, combinedSize = leftArr.length + rightArr.length;
int[] merged = new int[combinedSize];
for (int i = 0; i < combinedSize; i++) {
if (leftPointer < leftArr.length && rightPointer < rightArr.length) {
if (leftArr[leftPointer] < rightArr[rightPointer]) {
merged[i] = leftArr[leftPointer++];
} else {
merged[i] = rightArr[rightPointer++];
}
} else if (leftPointer < leftArr.length) { // adding the last element
merged[i] = leftArr[leftPointer++];
} else {
merged[i] = rightArr[rightPointer++];
}
}
return merged;
}

insertion sort and 2 d arrays

I'm trying to use insertion sort to sort a 2 d array in Java by the first column values of each row. I've tested it on an array of size 2 but when I try the code for size 3 it doesn't even run the for loop. Thank you for any help you can give.
public int[][] sortC(int[][] temp)
{
if (temp.length == 1)
{
return temp;
}
else if (temp.length >= 2)
{
for (int i = 1; i <= temp.length - 1; i++)
{
int holdRow = temp[i][0];
int holdCol = temp[i][1];
// hold past index
int holdRowP = temp[i - 1][0];
int holdColP = temp[i - 1][1];
int j = i;
while (j > 0 && holdRow < holdRowP)
{
holdRow = temp[j][0];
holdCol = temp[j][1];
// hold past index
holdRowP = temp[j - 1][0];
holdColP = temp[j - 1][1];
// make single swap
temp[j][0] = holdRowP;
temp[j][1] = holdColP;
temp[j-1][0] = holdRow;
temp[j-1][1] = holdCol;
j--;
}
}
}
return temp;
}
You can simplify alot and make it work for arbitrary size by using the fact that a Java 2D array is really an array of arrays. The internal arrays (i.e., the rows) can be moved around as whole units rather than piecemeal as you're doing.
As your code is modifying the passed argument, there's also no need to return the array.
After the call sortC(input), the input array will be sorted.
Using both of these, your code can be reduced to
public void sortC(int[][] temp)
{
if (temp.length >= 2)
{
for (int i = 1; i <= temp.length - 1; i++)
{
int[] hold = temp[i];
int[] holdP = temp[i-1];
int j = i;
while (j > 0 && hold[0] < holdP[0])
{
hold = temp[j];
holdP = temp[j-1];
temp[j] = holdP;
temp[j-1] = hold;
j--;
}
}
}
}

Categories