fastest way to shuffle matrix row - java

I need to shuffle the rows of a matrix, creating a new randomized matrix with all the same properties of the original one. Is there any approach faster/more efficient than the one I am adopting now?
private static SparseDoubleMatrix2D shuffleMatrix(SparseDoubleMatrix2D aMatrix, int[] ordering, int size) {
SparseDoubleMatrix2D result = new SparseDoubleMatrix2D(size, size);
for (int i = 0; i < size; i++) {
int row = ordering[i];
for (int col = 0; col < size; col++) {
result.set(i, col, aMatrix.get(row, col));
}
}
return result;
}
each time the method is called, a new ordering is given according to this other method:
private static void shuffleArray(int[] ordering, MersenneTwisterFast r) {
for (int i = ordering.length - 1; i > 0; i--) {
int index = r.nextInt(i + 1);
int a = ordering[index];
ordering[index] = ordering[i];
ordering[i] = a;
}
}

It depends on the implementation of SparseDoubleMatrix2D. Presently you are shuffling the rows by re-assigning every element in the matrix, however, since only rows are being shuffled and not columns, you should be able to shuffle it by reassigning the references to each row only, which should cut down the processing time from O(size*size) to O(size).
To answer the OP's comment about deep copy, a good implementation of SparseDoubleMatrix2D would be something like this:
class Matrix2D {
private int[] ordering;
private MatrixRow[] rows;
public double getValue(int row, int col) {
return rows[ordering[row]].get(col);
}
...
}
Ordering starts off looking like {0, 1, 2, ... n-1}. When you need to randomize, just set a new ordering array. That way, the original order which
is the order of rows[] never gets changed.

Related

Return a zigzag array

I have two questions:
public static int[] everyOther(int[] arr)
Given an integer array arr, create and return a new array that contains precisely the elements in the even-numbered positions in the array arr. Make sure that your method works correctly for arrays of both odd and even lengths, and for arrays that contain zero or only one element. The length of the result array that you return must be exactly right so that there are no extra zeros at the end of the array.
public static int[][] createZigZag(int rows, int cols, int start)
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
when displayed in the traditional matrix form that is more readable for the human than the more realistic form of a one-dimensional array whose elements are one-dimensional arrays of rows.
public static int[] everyOther(int[] arr){
for (int i = 0 ; i < aList.size() ; i+=2)
{
return( aList.get(i) + " ") ;
}
}
public static int[][] createZigZag(int rows, int cols, int start){
{
int evenRow = 0;
int oddRow = 1;
while (evenRow < rows)
{
for (int i = 0; i < cols; i++)
{
return(start[evenRow][i] + " ");
}
evenRow = evenRow + 2;
if(oddRow < rows)
{
for (int i = cols - 1; i >= 0; i--)
{
return(start[oddRow][i] + " ");
}
}
oddRow = oddRow + 2;
}
}
}
does this make sense?
Try this as an attempted solution to your exercise.
Notes:
If you copy paste this whole code, make sure your class file is named TestExample as is this one.
Inside main method are just some tests so that you see the output printed and you can verify it. You can ignore Arrays.toString(), it's just to print the int[] arrays to the screen in a better format.
Wherever you see final, you can ignore it or erase it (for now, that you still learn the language). In a simple first look, it means you don't intend to change this variable. After you proceed in learning the language, visit this again but this time consider that it "locks" the variable name to a specific reference inside the enclosing scope. It doesn't guarantee immutability of the value however except if it is a primitive value (int, long, float, double etc).
Notice that the arrays have to have been initialized (their dimensions) before you assign any value to a specific position of the array.
For the everyOther method, note that Java is zero-based in its indexing and thus in the array new int[] { 8, 9, 10, 11 }; your first odd-indexed value is 9 and the second is 11.
General advice: If you are now starting with a language, use an IDE like Eclipse (it's free & open source), IntelliJ (free) or NetBeans(free & open source). It would red-underline the errors in your code and (if configured) display warning messages as well for dangerous practices.
Code:
import java.util.Arrays;
public class TestExample
{
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;
}
public static int[] everyOther(final int[] array)
{
int otherArrayLength;
if (array.length % 2 == 0)
{
otherArrayLength = array.length / 2;
}
else
{
otherArrayLength = array.length / 2 + 1;
}
final int[] otherArray = new int[otherArrayLength];
int count = 0;
for (int i = 0; i < array.length; i += 2)
{
otherArray[count] = i;
count++;
}
return otherArray;
}
public static void main(final String[] args)
{
final int[] testArray = new int[] { 0, 1, 2, 3, 4, 5, 6 };
final int[] everyOtherArray = everyOther(testArray);
System.out.println(Arrays.toString(everyOtherArray));
final int rows = 4;
final int cols = 5;
final int start = 4;
final int[][] zigzagArray = createZigZag(rows, cols, start);
for (int i = 0; i < rows; i++)
{
System.out.println(Arrays.toString(zigzagArray[i]));
}
}
}

How to efficiently sort a Multidimensional Arrray

I was given a task to sort multidimensional array into ascending order without using the pre-made functions in the Array class (such as .sort).
I've tried asking some of my friends for ideas... Many of them turns the array into a single-dimensional array, sort it the way you would sort a single-dimensional array and then turns it back into a multidimensional array.
I'm just curious to know if there'd be any other ways to do this without having to go through such trouble.
I've found a solution... Thanks all
public static void sortAscending(int array[][]) {
int temp = 0;
for(int i = 0; i < array.length; i++) {
for(int j = 0; j < array[i].length; j++) {
for(int k = 0; k < array.length; k++) {
for(int l = 0; l < array[k].length; l++) {
if(array[i][j] < array[k][l]) {
temp = array[i][j];
array[i][j] = array[k][l];
array[k][l] = temp;
}
}
}
}
}
}
here is a full exemple you can tri
import java.util.Arrays;
import java.util.Comparator;
public class PartNumberQuantityDetailer {
// initialize a two dimensional array
static Integer[][] itemIdAndQty = new Integer[5][2];
public static void main(String[] args) {
// initialize array values
itemIdAndQty[0][0] = 1234;
itemIdAndQty[0][1] = 46;
itemIdAndQty[1][0] = 5443;
itemIdAndQty[1][1] = 564;
itemIdAndQty[2][0] = 362;
itemIdAndQty[2][1] = 24;
itemIdAndQty[3][0] = 6742;
itemIdAndQty[3][1] = 825;
itemIdAndQty[4][0] = 347;
itemIdAndQty[4][1] = 549;
System.out.println("Before sorting");
// show the contents of array
displayArray();
// sort the array on item id(first column)
Arrays.sort(itemIdAndQty, new Comparator<Integer[]>() {
#Override
//arguments to this method represent the arrays to be sorted
public int compare(Integer[] o1, Integer[] o2) {
//get the item ids which are at index 0 of the array
Integer itemIdOne = o1[0];
Integer itemIdTwo = o2[0];
// sort on item id
return itemIdOne.compareTo(itemIdTwo);
}
});
// display array after sort
System.out.println("After sorting on item id in ascending order");
displayArray();
// sort array on quantity(second column)
Arrays.sort(itemIdAndQty, new Comparator<Integer[]>() {
#Override
public int compare(Integer[] o1, Integer[] o2) {
Integer quantityOne = o1[1];
Integer quantityTwo = o2[1];
// reverse sort on quantity
return quantityOne.compareTo(quantityTwo);
}
});
// display array after sort
System.out.println("After sorting on quantity in ascending order");
displayArray();
}
private static void displayArray() {
System.out.println("-------------------------------------");
System.out.println("Item id\t\tQuantity");
for (int i = 0; i < itemIdAndQty.length; i++) {
Integer[] itemRecord = itemIdAndQty[i];
System.out.println(itemRecord[0] + "\t\t" + itemRecord[1]);
}
System.out.println("-------------------------------------");
}
}]
sort multidimensional array into ascending order:
You can sort multi-d array row-wise or column -wise.
If you don't want to flatten the array that is convert it into 1-d then that mean you have to go through each row or column depending on your choice and apply quick-sort(better performance for small data set if pivot is chosen optimally) or merge-sort.
So you can do both in (considering avg. case) O(nlogn) and say there are n rown or n columns the time complexity will be O(n^2(logn)).
Now above the assumption is that you want to sort either row-wise or column-wise.
If you want to achieve the both(row and column) then it's better if you convert the array to 1-d and then apply sort and then convert it back. Otherwise following above approach the time complexity can go O(n^2(logn)) but in the other case it will be O((n+m)log(n+m)) where n amd m are no. of rows and columns in array plus the O(n+m) space complexity.
In my opinion having a bit of space complexity so that you can bring down the run-time is preferable.

OutOfBounds when working with objects in an array

When I am creating an array of Example objects, I call something like initializeArray(); I use a simple nested for loop to traverse through the array and then assign new objects with values to each index of the array using exampleArr[i][j] = new Example(false, false, false, 0); however, calling this gives me an java.lang.ArrayIndexOutofBoundsException:0 at the line above.
I am assuming that I am instantiating the new object incorrectly, as this also happens in another method which is supposed to display all of the Example objects in the array. However, I will post the nested loop I am using in case there is something that i've done wrong that I can't see.
public void initializeArray(){
for(int i = 0; i < getRows(); i++){
for(int j = 0; j < getColumns(); j++){
tileArr[i][j] = new Tile(false, false, false, 0);
}
}
}
//Declaration of rows and columns
private int rows;
private int columns;
Tile[][] tileArr = new Tile[rows][columns];
public void setRows(int r)
{
rows = r;
}
public void setColumns(int c)
{
//various setters and getters for the array
columns = c;
}
public int getRows()
{
System.out.print(rows);
return rows;
}
public int getColumns()
{
System.out.print(columns);
return columns;
}
Thanks everyone for your help! The problem has been solved.
Declare your tileArr at the top but do not initialize.
Tile[][] tileArr;
Then initialize your array before your for loop in the initializeArray() (This is assuming your rows and columns is set. You can add logic to check this as well).
tileArr = new Tile[getRows()][getColumns()];
tileArr = new Tile[rows][columns]; //Do this instead if you don't want the print statements to be called
As #gonzo said you have got to initialize your array to allocate enough memory for all the positions you are going to be using.
Tile[][] tileArr;
public void initializeArray(){
Tile[][] tileArr = new Tile[getRows()][getColumns()];
for(int i = 0; i < getRows(); i++){
for(int j = 0; j < getColumns(); j++){
tileArr[i][j] = new Tile(false, false, false, 0);
}
}
return titleArr;
}
//...wherever you want it
this.tileArray = this.initializeArray()
But there are cases when you don't know how big this array may be. For those cases you should be using List<Tile> type like LinkedList<Tile> or ArrayList<Tile> so that you don't need to allocate space for every new position to use.

How to check ensure a array does not contain the same element twice

I have a loop which assigns randomly generated integers into an array.
I need a way to ensure the same integer is not input into the array twice.
I figured creating a loop inside the overall loop would work but I am unsure on what to execute here.
int wwe[] = new int[9];
for(int i = 0; i < 9 ; i++){
int randomIndex = generator.nextInt(wwe.length);
wwe[i] = randomIndex;
System.out.println(wwe[i]);
System.out.println("########");
for(int j = 0; j < 9; j++){
System.out.println("This is the inner element " + wwe[j]);
}
}
If you want to enforce unique values, use a data structure meant for such a behavior, like a Set. TreeSet or HashSet would work perfectly.
You are actually looking for shuffling your array.
Note that what you really looking for is to find a random order of your array, this is called a permutation.
In java, it can be simply done using a list with Collections.shuffle().
If you are looking to implement it on your own - use fisher yates shuffle, it is fairly easy to implement.
Since other answers showed how to do it with Collections.shuffle() already - here is a simple implementation + example of fisher yates shuffle, that does not need to convert the original array into a list.
private static void swap (int[] arr, int i1, int i2) {
int temp = arr[i1];
arr[i1] = arr[i2];
arr[i2] = temp;
}
private static void shuffle(int[] arr, Random r) {
for (int i =0; i < arr.length; i++) {
int x = r.nextInt(arr.length - i) + i;
swap(arr,i,x);
}
}
public static void main(String... args) throws Exception {
int[] arr = new int[] {1 , 5, 6, 3, 0, 11,2,9 };
shuffle(arr, new Random());
System.out.println(Arrays.toString(arr));
}
Something similar to the following should meet your requirement.
It uses a HashSet to achieve unique elements.
Set<Integer> sint = new HashSet<>();
Random random = new Random();
while ( sint.size() < 9){
sint.add(random.nextInt());
}
For you example, you can use Collections.shuffle
public static void main(String[] args) {
List<Integer> a = new ArrayList<>(9);
for (int i = 0; i < 9; i++) {
a.add(i);
}
Collections.shuffle(a);
System.out.println(a);
}

Eliminating Recursion

I've just been looking at the following piece of code
package test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(final String[] args) {
final int sizeA = 3;
final int sizeB = 5;
final List<int[]> combos = getAllCombinations(sizeA-1, sizeB);
int counter = 1;
for(final int[] combo : combos) {
System.out.println("Combination " + counter);
System.out.println("--------------");
for(final int value : combo) {
System.out.print(value + " ");
}
System.out.println();
System.out.println();
++counter;
}
}
private static List<int[]> getAllCombinations(final int maxIndex, final int size) {
if(maxIndex >= size)
throw new IllegalArgumentException("The maximum index must be smaller than the array size.");
final List<int[]> result = new ArrayList<int[]>();
if(maxIndex == 0) {
final int[] array = new int[size];
Arrays.fill(array, maxIndex);
result.add(array);
return result;
}
//We'll create one array for every time the maxIndex can occur while allowing
//every other index to appear, then create every variation on that array
//by having every possible head generated recursively
for(int i = 1; i < size - maxIndex + 1; ++i) {
//Generating every possible head for the array
final List<int[]> heads = getAllCombinations(maxIndex - 1, size - i);
//Combining every head with the tail
for(final int[] head : heads) {
final int[] array = new int[size];
System.arraycopy(head, 0, array, 0, head.length);
//Filling the tail of the array with i maxIndex values
for(int j = 1; j <= i; ++j)
array[size - j] = maxIndex;
result.add(array);
}
}
return result;
}
}
I'm wondering, how do I eliminate recursion from this, so that it returns a single random combination, rather than a list of all possible combinations?
Thanks
If I understand your code correctly your task is as follows: give a random combination of numbers '0' .. 'sizeA-1' of length sizeB where
the combination is sorted
each number occurs at least once
i.e. in your example e.g. [0,0,1,2,2].
If you want to have a single combination only I'd suggest another algorithm (pseudo-code):
Randomly choose the step-up positions (e.g. for sequence [0,0,1,1,2] it would be steps (1->2) & (3->4)) - we need sizeA-1 steps randomly chosen at sizeB-1 positions.
Calculate your target combination out of this vector
A quick-and-dirty implementation in java looks like follows
// Generate list 0,1,2,...,sizeB-2 of possible step-positions
List<Integer> steps = new ArrayList<Integer>();
for (int h = 0; h < sizeB-1; h++) {
steps.add(h);
}
// Randomly choose sizeA-1 elements
Collections.shuffle(steps);
steps = steps.subList(0, sizeA - 1);
Collections.sort(steps);
// Build result array
int[] result = new int[sizeB];
for (int h = 0, o = 0; h < sizeB; h++) {
result[h] = o;
if (o < steps.size() && steps.get(o) == h) {
o++;
}
}
Note: this can be optimized further - the first step generates a random permutation and later strips this down to desired size. Therefore it is just for demonstration purpose that the algorithm itself works as desired.
This appears to be homework. Without giving you code, here's an idea. Call getAllCombinations, store the result in a List, and return a value from a random index in that list. As Howard pointed out in his comment to your question, eliminating recursion, and returning a random combination are separate tasks.

Categories