I'm attempting to incorporate this logic based code with the quicksort into my main program (Not shown here). The program basically generates 2d array values, and proceeds to print them out on the screen. The dim variable serves as the amount of dimensions in this code (I.e 3D) Since there are X,Y,Z coordinates. I'm having trouble understanding if this is the correct way to go about sorting this array using the [dim]. Any constructive/helpful input would be appreciated.
Example output (Not sorting it) (Taken from the last bit of the code to prove each row is not sorted :
[[3, 1, 1, 0], [3, 1, 1, 0], [2, 1, 1, 0], [3, 1, 1, 0], [3, 1, 1, 0], [3, 1, 1, 0], [3, 1, 1, 0], [2, 1, 1, 0], [3, 1, 1, 0], [3, 1, 1, 0]]
[[4, 5, 3, 0], [4, 5, 3, 0], [2, 1, 1, 0], [4, 5, 3, 0], [4, 5, 3, 0], [4, 5, 3, 0], [4, 5, 3, 0], [2, 1, 1, 0], [4, 5, 3, 0], [4, 5, 3, 0]]
[[4, 1, 2, 0], [4, 1, 2, 0], [2, 1, 1, 0], [4, 1, 2, 0], [4, 1, 2, 0], [4, 1, 2, 0], [4, 1, 2, 0], [2, 1, 1, 0], [4, 1, 2, 0], [4, 1, 2, 0]]
The actual program
//import java.util.ArrayList;
import java.util.*;
public class MyQuickSort {
private static int a[][] = new int [10][4];
private static int dim = 3;
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
//for(int j = 0; j < 4; j++) {
a[i][0] = (int)(Math.random () * 6) +1 ;
a[i][1] = (int)(Math.random () * 6) +1 ;
a[i][2] = (int)(Math.random () * 6) +1 ;
quickSort(a, 0, a.length - 1);
System.out.println(Arrays.deepToString(a));
//}
}
}
public static void quickSort(int[][] a, int p, int r)
{
if(p<r)
{
int q=partition(a,p,r);
quickSort(a,p,q);
quickSort(a,q+1,r);
}
}
private static int partition(int[][] a, int p, int r) {
int x = a[p][dim];
int i = p-1 ;
int j = r+1 ;
while (true) {
i++;
while ( i< r && a[i][dim] < x)
i++;
j--;
while (j>p && a[j][dim] > x)
j--;
if (i < j)
swap(a, i, j);
else
return j;
}
}
private static void swap(int[][] a, int i, int j) {
// TODO Auto-generated method stub
int temp = a[i][dim];
a[i] = a[j];
a[j][dim] = temp;
}
}
Since all of your individual numbers are non-negative single-digit integers, why not just convert your array elements to strings -- that is, [3, 1, 1, 0] as a string -- and quicksort them like that? The sort order will end up being the same as if you looped through each element of the above individually and compared the numerical values.
Related
I am creating unique subsequences of size 2 using below code. How can I create subsequences of different sizes. Size would be dynamic.
For example, [1 2 3 4] -> [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
For size 3, it would be , [[1, 2, 3], [1, 2, 4], [2, 3, 4]]
public static int getTheSubseq(List<Integer> AList){
List<List<Integer>> li = new ArrayList<>();
for (int i = 0; i < AList.size(); i++){
for(int j =i+1; j < AList.size(); j++){
List<Integer> temp = new ArrayList<>();
temp.add(AList.get(i));
temp.add(AList.get(j));
li.add(temp);
}
}
System.out.println(li);
return 1;
}
Using recursion you could build the subsequences as follows:
private void buildSubsequence( List<Integer> source, int targetSize,
List<List<Integer>> result, Stack<Integer> currentSubsequence, int currentIndex ) {
//We don't want to iterate beyond the point where we can't build a complete subsequence.
//Thus we'll need to subtract the number of still needed elements
//(target count - number of elements already in the subsequence - 1 for this call)
int maxIndex = source.size() - ( targetSize - currentSubsequence.size() - 1);
//iterate over each index from the current one to this call's max
for( int i = currentIndex; i < maxIndex; i++ ) {
//add the element at that index to the subsequence
currentSubsequence.push( source.get( i ) );
//if we're done make a copy
if( currentSubsequence.size() == targetSize ) {
result.add( new ArrayList<Integer>( currentSubsequence) );
} else { //if we're not done, get the next element
buildSubsequence( source, targetSize, result, currentSubsequence, i + 1 );
}
//remove the last element added by push() to have it replaced with the next one
currentSubsequence.pop();
}
}
Then you call it like this:
List<Integer> source = Arrays.asList( 1,2,3,4,5,6 );
List<List<Integer>> result = new LinkedList<>();
buildSubsequence( source, 3, result, new Stack<>(), 0 );
That creates the following subsequences:
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 2, 6]
[1, 3, 4]
[1, 3, 5]
[1, 3, 6]
[1, 4, 5]
[1, 4, 6]
[1, 5, 6]
[2, 3, 4]
[2, 3, 5]
[2, 3, 6]
[2, 4, 5]
[2, 4, 6]
[2, 5, 6]
[3, 4, 5]
[3, 4, 6]
[3, 5, 6]
[4, 5, 6]
Note that this is just one way to solve it. :)
Currently i am trying to create a method to sort an arraylist of stack of integer lexicographical for my assignment. Currently this is what i had, however, right now i am facing a problem.
Collections.sort(arrayList, new Comparator<Stack<Integer>>(){
public int compare(Stack<Integer> list1, Stack<Integer> list2){
int result = 0;
for (int i = 0; i <= list1.size() - 1 && result == 0; i++)
{
result = list2.get(i).compareTo(list1.get(i));
}
return result;
}
});
When i try to input [[1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 3], [1, 1, 1, 3, 1], [1, 1, 3, 1, 1], [1, 3, 1, 1, 1], [3, 1, 1, 1, 1], [1, 1, 3, 3], [1, 3, 1, 3], [1, 3, 3, 1], [3, 1, 1, 3], [3, 1, 3, 1], [3, 3, 1, 1], [1, 4, 4], [4, 1, 4], [4, 4, 1], [3, 3, 3]] as the arraylist of stack of integer and manage to get this as the result:
Output: [[4, 4, 1], [4, 1, 4], [3, 3, 3], [3, 3, 1, 1], [3, 1, 3, 1], [3, 1, 1, 3], [3, 1, 1, 1, 1], [1, 4, 4], [1, 3, 3, 1], [1, 3, 1, 3], [1, 3, 1, 1, 1], [1, 1, 3, 3], [1, 1, 3, 1, 1], [1, 1, 1, 3, 1], [1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 1]]
As you can see that is not lexicographic and this is what i am aiming for
Expected output: [[1, 4, 4], [3, 3, 3], [4, 1, 4], [4, 4, 1], [1, 1, 3, 3], [1, 3, 1, 3], [1, 3, 3, 1], [3, 1, 1, 3], [3, 1, 3, 1], [3, 3, 1, 1], [1, 1, 1, 1, 3], [1, 1, 1, 3, 1], [1, 1, 3, 1, 1], [1, 3, 1, 1, 1], [3, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1]]
Here is the question, Where did i get it wrong? how does .compareTo works?
Edit:
Apparently, my professor make a misunderstanding on the meaning of lexicographically. However, the expected output is the output what my professor desire
You need to first check if one of the stacks is shorter than the other. If not you need to compare the elements of list1 against list2, not the other way around.
Collections.sort(arrayList, new Comparator<Stack<Integer>>(){
public int compare(Stack<Integer> list1, Stack<Integer> list2){
int result = Integer.compare(list1.size(), list2.size());
for (int i = 0; result == 0 && i < list1.size(); i++)
{
result = Integer.compare(list1.get(i), list2.get(i));
}
return result;
}
});
As this is an assignment I will put you on what I think is the right direction, but I won't solve the programming for you:
compare() is a method defined in the interface Comparator<T> that is supposed to return -1, 0, or 1 depending if the first object passed in as a parameter is less, equal, or greater than the second object passed in as a parameter.
The expected objects are of type T which you define when you declare the class.
In the compare() method you write, you have to resolve whatever comparison method you want to implement, to a -1, a 0, or a 1.
How you get to those values depends on how you evaluate an object of T type to be less, equal or greater than other object of the same type.
On another side, Array.sort() will use the Comparator as fit to make comparisons between two elements of the array, and return as a final result the ordered Array.
If I understood your clarification, an array [1,1,1], for ordering purposes should be interpreted as a String "111";
So in terms of programming the Comparator, what will be compared (the T) would be arrays of integers.
And to compare two arrays of integers, the elements of each array should be extracted and sticked together to form a String. Once you have both Strings, you can see how they compare to each other.
If our concepts of lexicographically ordered is the same, looks like the problem is that you are using compareTo inverted (list2 compareTo list1 instead of list1 compareTo list2).
After some modifications your code will look like this:
Collections.sort(arrayList, new Comparator<Stack<Integer>>() {
public int compare(Stack<Integer> list1, Stack<Integer> list2) {
int result = 0;
for (int i = 0; i <= list1.size() - 1 && result == 0; i++) {
if (list2.size()-1 < i)
return 1;
else
result = list1.get(i).compareTo(list2.get(i));
}
return result;
}
});
This code will produce the following result: [[1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 3], [1, 1, 1, 3, 1], [1, 1, 3, 1, 1], [1, 1, 3, 3], [1, 3, 1, 1, 1], [1, 3, 1, 3], [1, 3, 3, 1], [1, 4, 4], [3, 1, 1, 1, 1], [3, 1, 1, 3], [3, 1, 3, 1], [3, 3, 1, 1], [3, 3, 3], [4, 1, 4], [4, 4, 1]], that I understand as lexicographically ordered despite of your expected result.
The if (list2.size()-1 < i) inside the for loop prevents an IndexOutOfBoundsException due to list2 being smaller than list1.
I am experimenting with creating 3d like sketches in processing without using the p3d renderer. I have managed to make a cube but for it I hardcoded all the coordinates and connections and once you want to add another dimension it begins to get a little boring. So I have created a function to create all the coordinates:
float[][] cube(int dims, float w) {
int outputSize = (int)pow(2, dims);
float[] temp = new float[dims];
float[][] res = new float[outputSize][dims];
Arrays.fill(temp, w);
res[0] = temp.clone();
for (int i = 0; i < outputSize - 1; i++) {
for (int j = dims - 1; true; j--) {
temp[j] *= -1;
if (temp[j] < 0) {
break;
}
}
res[i + 1] = temp.clone();
}
return res;
}
It simply works by using binary so the inputs (2, 1) cube would be:
[[1, 1], [1, -1], [-1, 1], [-1, -1]]
It works fine but the problem is that It only returns the corners but not witch corner to connect but I can't find an efficient way to do that. I need another function that returns what to indices to connect.
Here is an example of what the function should do given the array above:
[[0, 1], [1, 3], [3, 2], [2, 0]]
(the inner arrays may be in a different order)
Is there any known algorithm to connect the corners of a n-dimensional cube?
I am ok with changing the other function if some other point generation helps.
Here is a way to iteratively generate the coordinates and indices together:
Start with a cube of dimension n
Make two copies of the cube, and place one at each of the extremal coordinates (e.g. -1 and +1) on the n + 1-th axis
Make edges to join each pair of corresponding vertices on the cubes
You already know that the number of vertices V(n) = 2^n. Since the number of edges added to an n + 1 cube is equal to this (all corresponding vertex pairs), plus those of the copied n cube, the recurrence relation for the number of edges is:
E(n) = 2 * E(n - 1) + V(n - 1) // copies + joining edges
E(1) = 1 // base case for n = 1
--> E(n) = n * 2^(n - 1)
n | E(n)
-------------
1 | 1
2 | 4
3 | 12
4 | 32
5 | 80
This allows one to pre-allocate the number of required edges and calculate index offsets when copying the new cube / adding new edges.
Code:
// edge index
class Edge
{
public int A, B;
public Edge(int a, int b)
{
A = a; B = b;
}
public Edge shift(int n)
{
return new Edge(A + n, B + n);
}
}
// cube class
class Cube
{
// I'll leave out the get-functions etc here
private float[][] m_verts;
private Edge[] m_edges;
public Cube(float[][] v, Edge[] e)
{
m_verts = v;
m_edges = e;
}
}
Cube cube_N(int dims, float w)
{
// base case
if (dims < 1)
return null;
// calculate buffer sizes
int dpow2 = 1 << dims;
int numVerts = dpow2;
int numEdges = dims * (dpow2 / 2);
// buffers
float[] temp = new float[dims];
float[][] verts = new float[numVerts][];
Edge[] edges = new Edge[numEdges];
// base case creation
Arrays.fill(temp, w);
verts[0] = temp.clone();
edges[0] = new Edge(0, 1);
// iterative step
for (int i = 0; i < dims; i++)
{
int nV = 1 << i;
int nE = i * (nV / 2);
// copy + shift vertices
for (int j = 0; j < nV; j++)
{
float[] v = verts[j].clone();
v[i] = -w;
verts[nV + j] = v;
}
// copy + shift previous edges
for (int j = 0; j < nE; j++)
{
edges[nE + j] = edges[j].shift(nV);
}
// create new edges to join cube copies
int off = nE * 2;
for (int j = 0; j < nV; j++)
{
edges[off + j] = new Edge(j, nV + j);
}
}
return new Cube(verts, edges);
}
Results for n = 3:
verts:
[1, 1, 1], [-1, 1, 1], [1, -1, 1], [-1, -1, 1],
[1, 1, -1], [-1, 1, -1], [1, -1, -1], [-1, -1, -1]
edges:
[0, 1], [2, 3], [0, 2], [1, 3], [4, 5], [6, 7],
[4, 6], [5, 7], [0, 4], [1, 5], [2, 6], [3, 7]
Results for n = 4:
verts:
[1, 1, 1, 1], [-1, 1, 1, 1], [1, -1, 1, 1], [-1, -1, 1, 1],
[1, 1, -1, 1], [-1, 1, -1, 1], [1, -1, -1, 1], [-1, -1, -1, 1],
[1, 1, 1, -1], [-1, 1, 1, -1], [1, -1, 1, -1], [-1, -1, 1, -1],
[1, 1, -1, -1], [-1, 1, -1, -1], [1, -1, -1, -1], [-1, -1, -1, -1]
edges:
[0 , 1], [2 , 3], [0 , 2], [1 , 3], [4, 5], [6 , 7], [4 , 6], [5 , 7],
[0 , 4], [1 , 5], [2 , 6], [3 , 7], [8, 9], [10, 11], [8 , 10], [9 , 11],
[12, 13], [14, 15], [12, 14], [13, 15], [8, 12], [9 , 13], [10, 14], [11, 15],
[0 , 8], [1 , 9], [2 , 10], [3 , 11], [4, 12], [5 , 13], [6 , 14], [7 , 15]
I'm a beginner in programming and I have a method :
public int[][] toArray(List<Integer> list, int rows) {
int[][] result = new int[list.size()][rows];
int i = 0;
int j = 0;
for (Integer value : list) {
result[i][j] = value;
j++;
if(j > rows - 1){
i++;
j = 0;
}
}
return result;
}
The result of it, if rows = 2 (and if we have a list contains numbers from 1 to 7) is:
[[1, 2], [3, 4], [5, 6], [7, 0], [0, 0], [0, 0], [0, 0]]
If rows = 3 result is:
[[1, 2, 3], [4, 5, 6], [7, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
What I need:
[[1, 2], [3, 4], [5, 6], [7, 0]]
[[1, 2, 3], [4, 5, 6], [7, 0, 0]]
How to do that?
Just for fun, here's another approach using Streams and Guava:
public static int[][] toArray(List<Integer> list, int rows) {
return Lists.partition(list, rows)
.stream()
.map(Ints::toArray)
.map(a -> Arrays.copyOf(a, rows))
.toArray(int[][]::new);
}
The problem lies in this line of code:
int[][] result = new int[list.size()][rows];
As you are initializing the result to a 2D array having rows equals to list.size() you are getting always seven rows. The solution is to first compute the number of rows for result array properly and then initialize it.
int resultRows = list.size()/rows;
if(list.size()%rows!=0){
resultRows++;
}
int[][] result = new int[resultRows][rows];
You can use a counter to track the count and determine the position by counter/rows and counter%rows, e.g.:
public int[][] toArray(List<Integer> list, int rows) {
int[][] result = new int[list.size()][rows];
int counter = 0;
for (Integer value : list) {
result[counter/rows][counter%rows] = value;
counter++;
}
return result;
}
You don't need to worry about remaining places as all the MxN elements get initialised with 0 when you declare an array with size.
Given M integers (N1, N2, Nm), I want to write a N-level embedded loop like following :
for (int a = 0; a < N1; a++)
for (int b = 0; b < N2; b++)
for (int c = 0; c < N3; c++)
....
for (int m = 0; m < Nm; m++)
operation
Since M is a variable, I cannot write fixed number level for-loop. What tricks could help ?
No need for recursion. Instead, think of each iterator as a digit in a number. When you increment the number, you increment the last digit, and if it exceeds the limit (normally 10), it's set to 0, and the digit to the left of it is increased, repeating the overflow logic.
In this case, each "digit" is an independent counter, each with their own "limit", i.e. the value of the given Nx. If you store those limit values in an array, and keep the counters in a same-size array, the logic is fairly simple.
Here is an example of an optimized version, that uses a label to exit directly from a nested loop:
int[] n = { 3, 4, 5 }; // m = 3: N1 = 3, N2 = 4, N3 = 5
int[] i = new int[n.length]; // All "digits" are 0
LOOP: for (;;) {
// operation using i[] here, e.g.
System.out.println(Arrays.toString(i));
// Process "digits" from last to first
for (int j = i.length - 1; ; j--) {
if (j < 0) // Exit main loop if first "digit" overflowed
break LOOP;
if (++i[j] < n[j]) // Increment "digit", and if not overflowed:
break; // exit digit-loop, i.e. loop back to process
i[j] = 0; // Reset "digit" to 0, then process next (to left) "digit"
}
}
Output
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 0, 3]
[0, 0, 4]
[0, 1, 0]
[0, 1, 1]
[0, 1, 2]
[0, 1, 3]
[0, 1, 4]
[0, 2, 0]
[0, 2, 1]
[0, 2, 2]
[0, 2, 3]
[0, 2, 4]
[0, 3, 0]
[0, 3, 1]
[0, 3, 2]
[0, 3, 3]
[0, 3, 4]
[1, 0, 0]
[1, 0, 1]
[1, 0, 2]
[1, 0, 3]
[1, 0, 4]
[1, 1, 0]
[1, 1, 1]
[1, 1, 2]
[1, 1, 3]
[1, 1, 4]
[1, 2, 0]
[1, 2, 1]
[1, 2, 2]
[1, 2, 3]
[1, 2, 4]
[1, 3, 0]
[1, 3, 1]
[1, 3, 2]
[1, 3, 3]
[1, 3, 4]
[2, 0, 0]
[2, 0, 1]
[2, 0, 2]
[2, 0, 3]
[2, 0, 4]
[2, 1, 0]
[2, 1, 1]
[2, 1, 2]
[2, 1, 3]
[2, 1, 4]
[2, 2, 0]
[2, 2, 1]
[2, 2, 2]
[2, 2, 3]
[2, 2, 4]
[2, 3, 0]
[2, 3, 1]
[2, 3, 2]
[2, 3, 3]
[2, 3, 4]
The same solution as #Andreeas', just with more explanations (he was faster in posting the answer, I'm adding mine to give myself a reason for the time I spent with the explanations):
import java.util.Arrays;
public class Multiloop {
static public void doSomething(int... maxIndexes) {
// quick check: if any of the maxIndexes is zeo or less
// there's a snowball in a furnace chance for the most inner loop
// to get executed
for(int i=0; i<maxIndexes.length; i++) {
if(maxIndexes[i]<=0) {
return; // nothing to do
}
}
// java guarantees all of then are zero after allocation
int multiIndex[]=new int[maxIndexes.length];
int currIndexPos=maxIndexes.length-1; // start looping with the last
do {
// this happens when the current index reached its correspondent maximum
// which of course is maxIndexes[currIndexPos]-1
while(
currIndexPos>=0 &&
multiIndex[currIndexPos]>=maxIndexes[currIndexPos]-1
) {
currIndexPos--; // search for the prev one to increment
}
if(currIndexPos<0) {
// all the indexes have reached their max value, we are done
break;
}
// if it's not the last index, we need to increment the current one
// and reset to zero all the others following it
if(currIndexPos<maxIndexes.length-1) {
// if not at the max value, then it's safe to increment it
multiIndex[currIndexPos]++;
Arrays.fill(multiIndex, currIndexPos+1, maxIndexes.length, 0);
}
// and now all multicycle indexes are to their proper value
// we reset the currIndexPos to the max and the do what we need to do
currIndexPos=maxIndexes.length-1;
/// Cut along the dotted lines and place your own code
/// ✂...✂...✂...✂...✂...✂...✂...✂...✂...✂
{ // the inner-most cycle, using the multicycle indexes as necessary
// replace it with what you need here
// **** Just don't screw up the currIndexPos!!!
// **** unless you know what you are doing
// **** (e.g. breaking any of the "cycles" on the way)
char nameForIndex='a';
for(int i=0; i<maxIndexes.length; i++) {
if(i>0) {
System.out.print(',');
}
System.out.print(nameForIndex+"="+multiIndex[i]);
nameForIndex++;
}
System.out.println();
}
// ✂...✂...✂...✂...✂...✂...✂...✂...✂...
multiIndex[currIndexPos]++;
} while(true); // the exit condition is handled at the cycle start anyway
}
static public void main(String args[]) {
// a triple cycle with their respective max indexes
doSomething(2,4,3);
}
}
Output:
a=0,b=0,c=0
a=0,b=0,c=1
a=0,b=0,c=2
a=0,b=1,c=0
a=0,b=1,c=1
a=0,b=1,c=2
a=0,b=2,c=0
a=0,b=2,c=1
a=0,b=2,c=2
a=0,b=3,c=0
a=0,b=3,c=1
a=0,b=3,c=2
a=1,b=0,c=0
a=1,b=0,c=1
a=1,b=0,c=2
a=1,b=1,c=0
a=1,b=1,c=1
a=1,b=1,c=2
a=1,b=2,c=0
a=1,b=2,c=1
a=1,b=2,c=2
a=1,b=3,c=0
a=1,b=3,c=1
a=1,b=3,c=2
How about using recursive:
int recursive_loop(int var_M){
if(var_M == destination) return 0;
else{
for(int i=0;i<var_M || recursive_loop(var_M+1) ; i++){
// Do operation here
}
}
}
I tested with C , it work.