Creating subsequences for elements in a LIst - java

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. :)

Related

Generate all possible combinations of an array of size n having exactly k subarrays

It's a combinatorics problem. We can partition the array at max n-1 times and out of it, we have to choose k-1 partitions.
Ex: arr[] = {1, 2, 3, 4, 5, 6}
k = 3, n = 6.
Total possibilities = (n-1)C(k-1) 5C2 = 10.
Expected Output : (3-dimensional array)
[
[[1], [2], [3, 4, 5, 6]],
[[1], [2, 3], [4, 5, 6]],
[[1], [2, 3, 4], [5, 6]],
[[1], [2, 3, 4, 5], [6]],
[[1, 2], [3], [4, 5, 6]],
[[1, 2], [3, 4], [5, 6]],
[[1, 2], [3, 4, 5], [6]],
[[1, 2, 3], [4, 5], [6]],
[[1, 2, 3, 4], [5], [6]],
]
Constraints:
Subarrays should have at least 1 element.
SubArrays should only consist of consecutive elements.
For ex: [[1, 3], [2, 4], [5, 6]] This is not valid.
So far, I have tried a recursive method but it yields wrong results. I can't wrap my head around how to correct it. I need an answer explaining how to approach this problem properly and the intuition behind it first and then correct my code and point out where I went wrong.
My code:
public static void main(String[] args) {
int n = 6;
int k = 3;
int[] arr = new int[]{1,2,3,4,5,6};
ArrayList<ArrayList<ArrayList<Integer>>> result = new ArrayList<ArrayList<ArrayList<Integer>>>();
ArrayList<ArrayList<Integer>> eachComb = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> eachSubArray = new ArrayList<Integer>();
int index = 0;
generateCombinations(arr, k, index, eachSubArray, eachComb, result);
for (ArrayList<ArrayList<Integer>> each : result) {
for(ArrayList<Integer> eachh: each) {
System.out.println(eachh);
}
System.out.println("-------------------------------");
}
}
private static void generateCombinations(int[] arr, int k, int index, ArrayList<Integer> eachSubArray,
ArrayList<ArrayList<Integer>> eachComb, ArrayList<ArrayList<ArrayList<Integer>>> result) {
if(k==0 || index==arr.length) {
return;
}
if(!eachSubArray.isEmpty()) {
eachComb.add(new ArrayList<>(eachSubArray));
}
if(k==1) {
ArrayList<Integer> last = new ArrayList<Integer>();
for(int i=index; i<arr.length; i++) {
last.add(arr[i]);
}
if(!last.isEmpty()) {
eachComb.add((last));
result.add(new ArrayList<ArrayList<Integer>>(eachComb));
eachComb.remove(eachComb.size()-1);
}
return;
}
eachSubArray.clear();
for(int i=index; i<arr.length; i++) {
eachSubArray.add((arr[i]));
generateCombinations(arr, k-1, i+1, eachSubArray, eachComb, result);
if(!eachComb.isEmpty()) {
eachComb.remove(eachComb.size()-1);
}
}
}

Recursive function fails in Java (ArrayList)

static List<List<Integer>> finalSubset = new ArrayList<>();
public static void main(String[] args) {
ArrayList<Integer> a = new ArrayList<>();
Integer[] array = {1, 2 ,3};
Collections.addAll(a, array);
subsets(a, 0);
System.out.println(finalSubset);
}
static void subsets (ArrayList<Integer> arr, int pos) {
if (arr.size() == 0) return;
finalSubset.add(arr); //problem
for (int i = pos; i < arr.size(); i++) {
Integer temp = arr.get(i);
arr.remove (i);
subsets(arr, i);
arr.add(i, temp);
}
}
I've tried out to make a code that prints out all possible subsets of given array using ArrayList and when I run it output is correct, but when I substitute System.out.println(arr) by funalSubset.add(arr) the output is:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
when it needs to be:
[1, 2, 3], [2, 3], [3], [2], [1, 3], [1], [1, 2], []
what's the reason of such output?
You are adding the same array list to finalSubset many times. You should create a copy every time you recurse, either when you add to finalSubset:
finalSubset.add(new ArrayList<>(arr));
OR when you do the recursive call:
subsets(new ArrayList<>(arr), i);
This way you have different lists that can have different things inside. If you only have one list, you just get the same thing repeated 8 times.
Also, you should add to finalSubset before you return, otherwise the empty list won't be added to finalSubset.
finalSubset.add(new ArrayList<>(arr));
if (arr.size() == 0) return;

Heap's Algorithm implementation in list of lists

I'm using Heap's algorithm to create a list-of-lists containing each permutation of said list. Each permutation will be its own list. It works properly when I print it within the algorithm, but it doesn't work properly when I try to add it to my list-of-lists and they are all the same array (4, 1, 2, 3). I commented out the print that I tested to make sure it was working.
My current code:
public static ArrayList<int[]> lists = new ArrayList<>();
public static void main(String[] args) {
int[] list = {1,2,3,4};
heapsAlgorithm(4,list);
for(int i = 1; i <= lists.size(); i++) {
System.out.println("List " + i + ": " + Arrays.toString(lists.get(i-1)));
}
}
public static void heapsAlgorithm(int n, int[] list) {
if (n == 1) {
lists.add(list);
//System.out.println(Arrays.toString(list));
}
else {
for(int i = 0; i < n; i++) {
heapsAlgorithm(n - 1, list);
if ( n % 2 == 0) {
int swap = list[i];
list[i] = list[n-1];
list[n-1] = swap;
}
else {
int swap = list[0];
list[0] = list[n-1];
list[n-1] = swap;
}
}
}
}
Working:
[1, 2, 3, 4]
[2, 1, 3, 4]
[3, 1, 2, 4]
[1, 3, 2, 4]
[2, 3, 1, 4]
[3, 2, 1, 4]
[4, 2, 3, 1]
[2, 4, 3, 1]
[3, 4, 2, 1]
[4, 3, 2, 1]
[2, 3, 4, 1]
[3, 2, 4, 1]
[4, 1, 3, 2]
[1, 4, 3, 2]
[3, 4, 1, 2]
[4, 3, 1, 2]
[1, 3, 4, 2]
[3, 1, 4, 2]
[4, 1, 2, 3]
[1, 4, 2, 3]
[2, 4, 1, 3]
[4, 2, 1, 3]
[1, 2, 4, 3]
[2, 1, 4, 3]
Incorrect output:
List 1: [4, 1, 2, 3]
List 2: [4, 1, 2, 3]
List 3: [4, 1, 2, 3]
List 4: [4, 1, 2, 3]
List 5: [4, 1, 2, 3]
List 6: [4, 1, 2, 3]
List 7: [4, 1, 2, 3]
List 8: [4, 1, 2, 3]
List 9: [4, 1, 2, 3]
List 10: [4, 1, 2, 3]
List 11: [4, 1, 2, 3]
List 12: [4, 1, 2, 3]
List 13: [4, 1, 2, 3]
List 14: [4, 1, 2, 3]
List 15: [4, 1, 2, 3]
List 16: [4, 1, 2, 3]
List 17: [4, 1, 2, 3]
List 18: [4, 1, 2, 3]
List 19: [4, 1, 2, 3]
List 20: [4, 1, 2, 3]
List 21: [4, 1, 2, 3]
List 22: [4, 1, 2, 3]
List 23: [4, 1, 2, 3]
List 24: [4, 1, 2, 3]
I assume I am using my ArrayList wrong, but I'm not sure where. Any suggestions?
You are need to copy your int array.
You have an mutable instance of your array and list of arrays that you assume you to keep your permutations. Basically, what's happening:
You do permutation.
You add permutation to your ArrayList.
You do another permutation on THE SAME object.
You add object to ArrayList that ALREADY in this list.
At the end you have ArrayList with 20 times added the same int array.

how to write n-level embeded loop with java

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.

bidimensional arraylists and inputting another array into them through a loop

I am trying to make an arraylist of which are essentially the rows of secondArr (which is a bidimensional arraylist). the problem is that when my cScore.size() == 7 (or equal to secondArr.size(), it does not get added to allScore, instead at the end all (in this case 21, asmyArr.size()=3, and secondArr.size()=7. values are added to one index, does anyone know why this is happening? the code seems to be so simple yet it is failing me. So in the end I would want a arraylist of 3 columns and 7 rows (but in this case just 1 column and 7 rows, and once I get this to work then I will add the rest.)
My code is as follows (this is just a small tidbit):
int rowsNum = allScores.size();
int colsNum = allScores.get(0).size();
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(colsNum);
for (int rowIdx = 0; rowIdx < colsNum; rowIdx++) {
ArrayList<Integer> rows = new ArrayList<Integer>(rowsNum);
for (int colIdx = 0; colIdx < rowsNum; colIdx++) {
rows.add(allScores.get(colIdx).get(rowIdx)); {
}
result.add(rows);
}
//using the syntax prov. by msi....
the original array allScores is:
[[2, 1, 3], [3, 1, 2], [2, 1, 3], [3, 1, 2],[ 2, 1, 3], [3, 1, 2], [1, 2, 3]]
when it is transposed with this it reeesults in
[[2, 3, 2, 3, 2, 3, 1], [2, 3, 2, 3, 2, 3, 1], [2, 3, 2, 3, 2, 3, 1], [2, 3, 2, 3, 2, 3, 1], [2, 3, 2, 3, 2, 3, 1], [2, 3, 2, 3, 2, 3, 1], [2, 3, 2, 3, 2, 3, 1]]
candScore.add(secondArr.get(j).get(k));
shouldn't that be:
cScore.add(secondArr.get(j).get(k));
Plus I have the feeling that your two nested loops should be the other way around.
for (int j=0; j< secondArr.size(); j++){
for (int k=0; k< myArr.size(); k++) {
I am not sure where your bug lies, but my guess is:
maybe the order of your two-dimensional array (i.e. it is 7 x 3 instead of 7 x 3)
do you really need that many ArrayLists to implement your algorithm
improve your code quality, e.g. by avoiding magic numbers (7 instead of size()), using extended for loops and assertions will drastically ease finding the bug.
I belive this is what you want. This code transposes 2d arraylists so column will become row, and row
will become column after transposition.
Example:
[[1 2 3], [4 5 6], [7 8 9]] -> [[1 4 7], [2 5 8], [3 6 9]]
this code assumes that all rows/columns have the same length.
// arr2d is ArrayList<ArrayList<Integer>>
int rowsNum = arr2d.size();
int colsNum = arr2d.get(0).size();
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(colsNum);
for (int rowIdx = 0; rowIdx < colsNum; rowIdx++) {
ArrayList<Integer> rows = new ArrayList<Integer>(rowsNum);
for (int colIdx = 0; colIdx < rowsNum; colIdx++) {
rows.add(arr2d.get(colIdx).get(rowIdx));
}
result.add(rows);
}
... edit (answer to 1st comment)
I don't see your point. Check:
ArrayList<ArrayList<Integer>> arr2d = new ArrayList<ArrayList<Integer>>();
arr2d.add(new ArrayList<Integer>(2));
arr2d.add(new ArrayList<Integer>(2));
arr2d.add(new ArrayList<Integer>(2));
arr2d.get(0).add(1);
arr2d.get(0).add(2);
arr2d.get(1).add(3);
arr2d.get(1).add(4);
arr2d.get(2).add(5);
arr2d.get(2).add(6);
above gives you: [[1, 2], [3, 4], [5, 6]] -> [[1, 3, 5], [2, 4, 6]] transformation. There are no copies of rows or columns you are talking about.

Categories