Convert List to 2D Array (Java) - java

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.

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;

How to save the contents of a powerSet into a 2d array in Java

I'm trying to save the contents of a PowerSet, obtained from a 1d Array into a 2d Array. I tried assigning the values in the array inside the "if" Statement but I'm getting the indices completely wrong
int[] set = new int[]{2,4,5,8}
int powSetLength = (int) Math.pow(2,set.length);
int[][] powSet = new int[powSetLength][];
for (int i = 0; i<powSetLength; i++){
for (int j = 0; j<set.length; j++){
if ((i & (1<<j))>0) {
powSet[i] = new int[] //here needs to be the length corresponding to the subset
powSet[i][j] = set[j]; //I know this is wrong but my idea was to assign each number of a subset into the 2d array
}
}
}
Since your inner array is of variable length, you might want to use an inner java.util.ArrayList<Integer> instead. Something like this:
int[] set = new int[]{2,4,5,8};
int powSetLength = (int) Math.pow(2,set.length);
List<Integer>[] powSet = new List[powSetLength];
for (int i = 0; i<powSetLength; i++){
for (int j = 0; j<set.length; j++){
if ((i & (1<<j))>0) {
// If the `i`'th powerSet isn't initialized yet: create an empty ArrayList:
if(powSet[i] == null)
powSet[i] = new ArrayList<>();
// And add the current set-value to the List:
powSet[i].add(set[j]);
}
}
}
System.out.println(Arrays.toString(powSet));
After which your array of Lists will contain the following powerset:
[null, [2], [4], [2, 4], [5], [2, 5], [4, 5], [2, 4, 5], [8], [2, 8], [4, 8], [2, 4, 8], [5, 8], [2, 5, 8], [4, 5, 8], [2, 4, 5, 8]]
Try it online.

Creating subsequences for elements in a LIst

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

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