Java: Recursive function not generating power set of a set - java

I am trying to generate a power set (all possible subsets) of integers based on a given set of integers. I am trying to use recursion based on the principle that each element in the master set can be in a subset or not in a subset. However, when I run my function on the example set {1, 5, 11, 5}, I am missing subsets, such as {1, 5, 5}. Below is my Java code:
// Function to generate power set of given set S
public static void determinePowerSet(int[] baseSet, List<Integer> currSet, int index, int sum)
{
// If the current index is at the end, we've finished generating subsets
if (index == baseSet.length) {
return;
}
// The subset in which we add the current element in the list
List<Integer> addToSet = new LinkedList<Integer>(currSet);
addToSet.add(baseSet[index]);
// Do not add the current element to the set
determinePowerSet(baseSet, currSet, index + 1, sum);
// Add the current element to the set
determinePowerSet(baseSet, addToSet, index + 1, sum + baseSet[index]);
}
public static void main(String[] args)
{
determinePowerSet(new int[] {1, 5, 11, 5}, new LinkedList<Integer>(), 0, 0);
}
Below is the output of the function call:
sum = 0, currSet = [], index = 0
sum = 0, currSet = [], index = 1
sum = 0, currSet = [], index = 2
sum = 0, currSet = [], index = 3
sum = 11, currSet = [11], index = 3
sum = 5, currSet = [5], index = 2
sum = 5, currSet = [5], index = 3
sum = 16, currSet = [5, 11], index = 3
sum = 1, currSet = [1], index = 1
sum = 1, currSet = [1], index = 2
sum = 1, currSet = [1], index = 3
sum = 12, currSet = [1, 11], index = 3
sum = 6, currSet = [1, 5], index = 2
sum = 6, currSet = [1, 5], index = 3
sum = 17, currSet = [1, 5, 11], index = 3

Everything is fine in your code. Let's take a look:
class Solution{
// Function to generate power set of given set S
public static void determinePowerSet(int[] baseSet, List<Integer> currSet, int index, int sum)
{
// If the current index is at the end, we've finished generating subsets
if (index == baseSet.length) {
for(int i : currSet)
System.out.print(i+" ");
System.out.println();
return;
}
// The subset in which we add the current element in the list
List<Integer> addToSet = new LinkedList<Integer>(currSet);
addToSet.add(baseSet[index]);
// Do not add the current element to the set
determinePowerSet(baseSet, currSet, index + 1, sum);
// Add the current element to the set
determinePowerSet(baseSet, addToSet, index + 1, sum + baseSet[index]);
}
public static void main(String[] args)
{
determinePowerSet(new int[] {1, 5, 11, 5}, new LinkedList<Integer>(), 0, 0);
}
}
OUTPUT:
5
11
11 5
5
5 5
5 11
5 11 5
1
1 5
1 11
1 11 5
1 5
1 5 5
1 5 11
1 5 11 5

Related

How to get output and get sum of columns in array / matrix?

hello to all you code geniuses on here
ill try to explain my problem as simply as i can
image1
To produce image1, lets say an array like below is required, keeping in mind that the numbers are placed left to right in the first row, then go backwards in the second row, and if you added more numbers, it would create a third row.
int[] something = {1, 2, 3, 2, 1, 2, 1, 3, 3, 1, 1, 2}
so i want to make to make a "map" of the layout, like this desired output below.
2 1 1 3 3 1
1 2 3 2 1 2
and then from there i would want to find the total for each column, so like this.
2 1 1 3 3 1
1 2 3 2 1 2
..................
3 3 4 5 4 3
(and i then want to make store this layout and sum within another array)
hopefully that all made sense, if so,
how could i go about doing this?
thanks heaps : )
Seems like you can use a two-dimensional array data structure to solve this:
int[][] something = new int[][]{
{2, 1, 1, 3, 3, 1},
{1, 2, 3, 2, 1, 2}
};
int totalForColomn1 = something[0][0] + something [1][0];
int totalForColomn2 = something[0][1] + something [1][1];
// ...
int totoalForColomn6 = something[0][5] + something [1][5];
If you could only use one-dimensional array:
int[] something = new int[] {2, 1, 1, 3, 3, 1, 4, 2, 3, 2, 1, 2};
int row_size = 6;
int totalForColomn1 = something[0] + something[0 + row_size];
int totalForColomn2 = something[1] + something[1 + row_size];
// ...
int totalForColomn6 = something[5] + something[5 + row_size];
Remember to keep a consistant row_size by putting those undecided element to 0.
In this case, you should init your array like:
int[] something = new int[] {0, 0, 0, 0, 1, 4, 1, 2, 3, 2, 1, 1};
So If I am reading this correctly if L is the length of your array you want to add the nth and L-1-nth element of the array and store the result in an array. I through this together quickly so I did not handle what happens if the input array is of odd length (your question did not specify).
import java.util.Arrays;
public class App {
public static void main(String[] args) {
int[] something = {1, 2, 3, 2, 1, 2, 1, 3, 3, 1, 1, 2};
System.out.println(Arrays.toString(addValues(something)));
}
public static int [] addValues(int [] input){
int[] output = new int[input.length / 2];
for(int i = 0; i<input.length/2; i++){
output[i] = input[i] + input[input.length -1 - i ];
}
return output;
}
}
EDIT:
I think this will work for the case where the are an arbitrary number of rows.
The main insite into how this work is in the grid below.
0 1 2 3 4 5 :row 0
11 10 9 8 7 6 :row 1
12 13 14 15 16 17:row 2
23 22 21 20 19 18:row 3
So whether the output index is going up or down is determined by the row number and every time we hit an input index that is the same size as our output array we need to stay at the same output index.
import java.util.Arrays;
public class App {
public static void main(String[] args) {
int[] something = { 1, 2, 3, 2, 1, 2, 1, 3, 3, 1, 1, 2 };
System.out.println(Arrays.toString(addValues(something, 6)));
}
public static int[] addValues(int[] input, int row_lenth) {
int[] output = new int[row_lenth];
int output_index = 0;
for (int i = 0; i < input.length; i++) {
if (i % row_lenth != 0) {
if ((i / row_lenth) % 2 == 0) {
output_index++;
} else {
output_index--;
}
}
output[output_index] += input[i];
}
return output;
}
}
import java.util.Scanner;
public class Stckoverq {
public static void main(String args[]) {
Scanner sn = new Scanner(System.in);
System.out.print("What is the size of array? ");
int size = sn.nextInt();
System.out.print("What is length of the row?");
int len = sn.nextInt();
int ind = 0, i = 0, j = 0;
//variable 'ind' is for getting the element from arr[] array at index ind
int rac[][] = new int[size/len][len];
//variable 'i' and 'j' is for storing rows and column elements respectively in array rac[]
int arr[] = new int[size];
System.out.println("Enter array elements: ");
for(int k=0;k<size;k++)
arr[k] = sn.nextInt();
while(ind!=arr.length)
{
if(j==len) {
j=0; //Reset column index
i++; //Increase row index
}
rac[i][j] = arr[ind];
ind++;
j++; //Increase column index
}
//Now print the rows and columns................
for(int r =0;r<size/len;r++) {
for(int c=0;c<len;c++)
System.out.print(rac[r][c]+"\t");
System.out.println();
}
int sum[] = new int[len];
//this array sum[] is used to store sum of all row elements.
int s = 0;
for(int c=0;c<len;c++) {
for(int r =0;r<size/len;r++)
s += rac[r][c];
sum[c] = s;
s = 0;
}
for(int x: sum)
System.out.print(x+"\t");
}
}

Insert column in desired location of 2D array

I'm looking to choose a column of my array, lets say column 2. I want this column to be inserted at a specific location in the 2D array, lets say column 4.
For example:
1 3 5 5 2
2 4 6 2 1
3 6 9 1 1
The desired output would be:
1 5 5 3 2
2 6 2 4 1
3 9 1 6 1
I know I could loop the following code until I 1 by 1 swap every column until the column is in the desired location.
for (int[] array1 : array) {
int temp = array1[col1];
array1[col1] = array1[col1];
array1[col2] = temp;
}
However, if I'm using large matrices such as 30 columns wide, this would be incredibly inefficient. Is there a way to insert the column anywhere in the 2D array without iterating through each swap until it is in the right spot?
Possibly, a performance may be improved by using parallel processing with streams.
IntStream of row indexes should be used to handle each row separately.
// basic shift method
// from, to - indexes starting from 1
public static void shiftArray(int[] arr, int from, int to) {
int tmp = arr[from - 1];
for (int i = from; i < to; i++) {
arr[i - 1] = arr[i];
}
arr[to - 1] = tmp;
}
public static void main(String[] args) {
int[][] arr2d = {
{1, 3, 5, 5, 2},
{2, 4, 6, 2, 1},
{3, 6, 9, 1, 1}
};
int fromColumn = 2;
int toColumn = 4;
IntStream.range(0, arr2d.length)
.parallel()
.forEach(i -> shiftArray(arr2d[i], fromColumn, toColumn)); // shift each row in parallel
// print the 2D array after shift
Arrays.stream(arr2d)
.map(Arrays::toString)
.forEach(System.out::println);
}
Output:
[1, 5, 5, 3, 2]
[2, 6, 2, 4, 1]
[3, 9, 1, 6, 1]
Try this.
public static void moveColumn(int[][] matrix, int from, int to) {
--from; --to; // If column number begins with zero, remove this line.
int srcPos = from < to ? from + 1 : to;
int destPos = from < to ? from : to + 1;
int length = Math.abs(from - to);
for (int[] array : matrix) {
int temp = array[from];
System.arraycopy(array, srcPos, array, destPos, length);
array[to] = temp;
}
}
and
int[][] matrix = {
{1, 3, 5, 5, 2},
{2, 4, 6, 2, 1},
{3, 6, 9, 1, 1}
};
moveColumn(matrix, 2, 4);
for (int[] row : matrix)
System.out.println(Arrays.toString(row));
output
[1, 5, 5, 3, 2]
[2, 6, 2, 4, 1]
[3, 9, 1, 6, 1]

Making a copy of the second half of an array

I want to make a function that takes as parameters an array and a boolean. The boolean tells the function if the rest of the division of the array is to be included. It then returns a new array which is the copy of the second half of the first:
secondHalf({1, 2, 3, 4, 5}, true) → {3, 4, 5}
secondHalf({1, 2, 3, 4, 5}, false) → {4, 5}
For this assignment, I'm not supposed to use any other classes.
Here's what I've attempted:
static int[] secondHalf(int[] vector, boolean include) {
int size = vector.length/2;
if(vector.length%2 == 0)
include = false;
if(include)
size ++;
int[] vector_2 = new int[size];
int i = 0;
while(i < size){
if(include)
vector_2[i] = vector[i+size-1];
vector_2[i] = vector[i+size+1];
i++;
}
return vector_2;
To find the size of vector_2, I've decided to use compound assignment operators. So the first part of this solution checks for the required condition and assigns a value to size in a single statement.
Since we know how many times to iterate over the loop, I think a for loop would be more appropriate than a while loop.
The loop retrieves all the values in vector from the middle of the array to the end of the array and places each value into vector_2.
static int[] secondHalf(int[] vector, boolean include) {
int size = vector.length/2 + (include && vector.length%2 != 0 ? 1 : 0);
int[] vector_2 = new int[size];
for(int i = 0; i < size; i++)
vector_2[i] = vector[vector.length - size + i];
return vector_2;
}
People have hinted at System#arraycopy, but with Arrays.copyOfRange there is an even simpler method, where you only have to define the proper start index and directly receive the copy.
The start index is array.length / 2 by default. Iff the include flag is true, then you have to add the remainder of dividing the array length by 2 to that.
An MCVE:
import java.util.Arrays;
public class ArrayPartCopy
{
public static void main(String[] args)
{
int array0[] = { 1, 2, 3, 4, 5 };
System.out.println("For " + Arrays.toString(array0));
System.out.println(Arrays.toString(secondHalf(array0, true)));
System.out.println(Arrays.toString(secondHalf(array0, false)));
int array1[] = { 1, 2, 3, 4 };
System.out.println("For " + Arrays.toString(array1));
System.out.println(Arrays.toString(secondHalf(array1, true)));
System.out.println(Arrays.toString(secondHalf(array1, false)));
}
static int[] secondHalf(int[] array, boolean include)
{
int start = array.length / 2;
if (include)
{
start += array.length % 2;
}
return Arrays.copyOfRange(array, start, array.length);
}
}
The output is
For [1, 2, 3, 4, 5]
[4, 5]
[3, 4, 5]
For [1, 2, 3, 4]
[3, 4]
[3, 4]

How to generate arrays with some very specific constraints

I want to print 100 int arrays according to some specific constraints.
each array can have a variable length from 2 to 10.
every item in each array must be unique
items in each array are sorted from the lowest to the highest
there are no identical arrays, meaning two arrays having same lenght and same items
At the moment I have this code
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
public class prova {
public static void main(String[] args) {
Integer[] elements = new Integer[]{1,2,3,4,5,6,7,8,9,10};
Set<List<Integer>> seenAlready = new HashSet<>();
for (int i = 0; i < 100; i++) {
final Integer[] array = generateRandomArrayFromElements(elements);
Arrays.sort(array);
if (seenAlready.add(Arrays.asList(array)))
System.out.println(Arrays.toString(array));
}
}
private static Integer[] generateRandomArrayFromElements(Integer[] elements) {
int size = ThreadLocalRandom.current().nextInt(1, elements.length) + 1;
Integer[] array = new Integer[size];
ArrayList<Integer> usedIndices = new ArrayList<>(size);
for (int i = 0; i < array.length; i++) {
int randomIndex = getUniqueRandomIndex(usedIndices, size);
usedIndices.add(randomIndex);
array[i] = elements[randomIndex];
}
return array;
}
private static int getUniqueRandomIndex(ArrayList<Integer> usedIndices, int max) {
int randomIndex = ThreadLocalRandom.current().nextInt(0, max);
final boolean contains = usedIndices.contains(randomIndex);
if (contains)
randomIndex = getUniqueRandomIndex(usedIndices, max);
return randomIndex;
}
}
The problem is that it just generates arrays too similar too each other.
They all look the same!
Have a look at one of its possible outputs:
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5, 6, 7]
[1, 2]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I'm never getting arrays like:
[3,4,8,9]
[2,3,6,7,8]
Everytime they start with [1,2,3,4] and so on!
I don't get it!
The problem is that You are generating index in range from 0 to array.length.
So if the array size is 2, then Your range is <0,2)
If the array size is 3, then Your range is <0,3)
...
If the array size is 10, then Your range is <0,10)
And in that situation there is no way to generate different results than You showed us.
Spots to fill |Elements to choose from based on range
=======================================
[_,_] |[1,2,................] range <0,2)
[_,_,_] |[1,2,3,..............] range <0,3)
[_,_,_,_] |[1,2,3,4,............] range <0,4)
...
You should invoke it like this int randomIndex = getUniqueRandomIndex(usedIndices, elements.length);
Notice that max changed to elements.length.
1 - Start to generate 100 empty arrays with a variable length from 2 to 10.
2 - Count the total size.
3 - Generate x uniques integers and add them to a Set.
Set<Integer> set = new HashSet<Integer>();
while(set.size()< xxx) {
set.add(generateRandomInteger());
}
Collections.sort(set);
(where xxx is the total array size
4 - add the integers into your arrays.

How to separate range of integers into two equal parts

I have an array of integers like this one
int [] num = {5, 8, 1, 1, 2, 3, 2}
and I want to divide it into 2 parts, so that the total of 2 sets will be as equal as possible: (output)
SET 1: 5 Piece(s)
1
1
2
2
5
Total: 11
SET 2: 2 Piece(s)
8
3
Total: 11
another example is
int [] num = {4, 6, 1, 2, 3, 3, 4}
with output like this:
SET 1: 3 Piece(s)
3
4
4
Total: 11
SET 2: 4 Piece(s)
6
1
2
3
Total: 12
any help? =) thanks
If the array is not too long, try a lazy solution: brute-force. Since all you need is to separate it into two sets, you'll need to check 2^n possibilities, because a number is either in the first set or not (i.e. in the second set).
Here's a sample code I just wrote:
public static int[][] bruteForce(int[] input) {
int n = input.length;
int[][] res = new int[2][n];
int minVal = Integer.MAX_VALUE;
int iMinVal = 0;
int limit = (int) Math.pow(2, n);
for (int i = 0; i < limit; i++) {
int v = i;
int diff = 0;
for (int j = 0; j < n; j++) {
diff = diff + ((v & 1) == 0 ? +1 : -1) * input[j];
v = v >> 1;
}
if (Math.abs(diff) < minVal) {
iMinVal = i;
minVal = Math.abs(diff);
}
}
int a = 0, b = 0;
for (int i = 0; i < n; i++) {
if ((iMinVal & 1) == 0) {
res[0][a++] = input[i];
} else {
res[1][b++] = input[i];
}
iMinVal = iMinVal >> 1;
}
return res;
}
public static void main(String[] args) {
int[] num = {5 ,8 ,1 ,1 ,2 ,3 ,2};
int[] num2 = {4, 6, 1, 2, 3, 3, 4};
int[][] r = bruteForce(num);
System.out.println("First example:");
System.out.println(Arrays.toString(r[0])+ ", sum = "+Arrays.stream(r[0]).sum());
System.out.println(Arrays.toString(r[1])+ ", sum = "+Arrays.stream(r[1]).sum());
r = bruteForce(num2);
System.out.println("Second example:");
System.out.println(Arrays.toString(r[0])+ ", sum = "+Arrays.stream(r[0]).sum());
System.out.println(Arrays.toString(r[1])+ ", sum = "+Arrays.stream(r[1]).sum());
}
output:
First example:
[5, 1, 3, 2, 0, 0, 0], sum = 11
[8, 1, 2, 0, 0, 0, 0], sum = 11
Second example:
[2, 3, 3, 4, 0, 0, 0], sum = 12
[4, 6, 1, 0, 0, 0, 0], sum = 11
If the length of the array is big, then I guess try some smart brute-force, or other methods. Like, sorting the array into non-ascending order, then starting from the biggest value, put each value into the array with less sum, which in the current case give the right answer:
public static int[][] alternative(int[] input) {
int n = input.length;
int[][] res = new int[2][n];
int[] input0 = Arrays.copyOf(input, n);
Arrays.sort(input0);
System.out.println("Input: "+Arrays.toString(input)+", ordered: "+Arrays.toString(input0));
int sum1 = 0, sum2 = 0;
int a = 0, b = 0;
for (int i = n-1; i >= 0; i--) {
if (sum1 <= sum2) {
res[0][a++] = input0[i];
sum1 = sum1 + input0[i];
System.out.println("Adding "+input0[i]+" into set 1 ==> Sum1 = "+sum1);
} else {
res[1][b++] = input0[i];
sum2 = sum2 + input0[i];
System.out.println("Adding "+input0[i]+" into set 2 ==> Sum2 = "+sum2);
}
}
return res;
}
output:
First example:
Input: [5, 8, 1, 1, 2, 3, 2], ordered: [1, 1, 2, 2, 3, 5, 8]
Adding 8 into set 1 ==> Sum1 = 8
Adding 5 into set 2 ==> Sum2 = 5
Adding 3 into set 2 ==> Sum2 = 8
Adding 2 into set 1 ==> Sum1 = 10
Adding 2 into set 2 ==> Sum2 = 10
Adding 1 into set 1 ==> Sum1 = 11
Adding 1 into set 2 ==> Sum2 = 11
[8, 2, 1, 0, 0, 0, 0], sum = 11
[5, 3, 2, 1, 0, 0, 0], sum = 11
Second example:
Input: [4, 6, 1, 2, 3, 3, 4], ordered: [1, 2, 3, 3, 4, 4, 6]
Adding 6 into set 1 ==> Sum1 = 6
Adding 4 into set 2 ==> Sum2 = 4
Adding 4 into set 2 ==> Sum2 = 8
Adding 3 into set 1 ==> Sum1 = 9
Adding 3 into set 2 ==> Sum2 = 11
Adding 2 into set 1 ==> Sum1 = 11
Adding 1 into set 1 ==> Sum1 = 12
[6, 3, 2, 1, 0, 0, 0], sum = 12
[4, 4, 3, 0, 0, 0, 0], sum = 11
For the 0s in the output, you can just write a simple function that create a new arrays without the 0s.
Have a for loop to loop like:
int sum =0:
for(int I=0; I<num.length/2; I++){
System.out.println(num[i]);
sum=sum+num[i];
}
System.out.println(sum);
(Written on ipad excuse any mistakes plz.
We should try with all combinations. For example, if the array is (1,1,100,100), then answer is (100,1) (100,1). If the array is (1,1,50,100) then answer is (1,1,50) (100). I don't think there is any short cut to this. If the array has N elements, then we shall try all combinations (Nc1, NcN01), (Nc2, NcN-2) .. and so on. Then find which of their difference is least.

Categories