0

below code give all possible sums for given double array , how to do this same with java8 streams and producing result in `Map<Integer,Double[]> like below

(0,[15],[0.55])

code without map implementation:

public class PossibleDoubleSums {
    public static void getAllSums(double []arr, double startingValue, int pos  ) {
   
        for (int i = pos; i < arr.length; i++) {
            
            double currentValue = startingValue + arr[i];
           System.out.println(currentValue+"");
           
            getAllSums(arr, currentValue, i + 1);
        }
        
    }
     
    public static void main(String[] args) {          
        double arr[] = {15.00, 0.55,25.00, 7.00};
        getAllSums(arr, 0, 0 ); // Test array
    
    }
}
chaitu
  • 21
  • 6

2 Answers2

3

Returning the possible sums

class Solution {
    public static List<Double> solve(double[] arr) {
        return IntStream.range(0, 1 << arr.length).boxed()
            .filter(n -> (n & (n - 1)) != 0)
            .map(n -> IntStream.range(0, arr.length)
                .filter(i -> ((n >> i) & 1) == 1)
                .mapToDouble(i -> arr[i])
                .sum())
            .collect(Collectors.toList());
    }
}

Usage

final double[] arr = { 15.00, 0.55, 25.00, 7.00 };
System.out.println(solve(arr));
// Outputs [15.55, 40.0, 25.55, 40.55, 22.0, 7.55, 22.55, 32.0, 47.0, 32.55, 47.55]

Returning the possible pairs

class Solution {
    public static List<Double[]> solve(double[] arr) {
        return IntStream.range(0, 1 << arr.length).boxed()
            .filter(n -> (n & (n - 1)) != 0)
            .map(n -> IntStream.range(0, arr.length).boxed()
                .filter(i -> ((n >> i) & 1) == 1)
                .map(i -> arr[i])
                .toArray(Double[]::new))
            .collect(Collectors.toList());
    }
}

Usage

final double[] arr = { 15.00, 0.55, 25.00, 7.00 };
        
final List<Double[]> result = solve(arr);
for (Double[] resultArr : result) {
    System.out.println(Arrays.toString(resultArr));
}

Output

[15.0, 0.55]
[15.0, 25.0]
[0.55, 25.0]
[15.0, 0.55, 25.0]
[15.0, 7.0]
[0.55, 7.0]
[15.0, 0.55, 7.0]
[25.0, 7.0]
[15.0, 25.0, 7.0]
[0.55, 25.0, 7.0]
[15.0, 0.55, 25.0, 7.0]

Explanation

Let's break it down using {15.00, 0.55, 25.00, 7.00} as input array:

  1. IntStream.range(0, 1 << arr.length) creates a stream of values from 0 until 1 << arr.length. The expression 1 << n is the same as Math.pow(n, 2), so 1 << arr.length will be equal to 16.

The stream now is IntStream({0, 1, 2, 3, ..., 12, 13, 14, 15}).

  1. boxed() converts this IntStream to Stream<Integer>. This allows us to convert it to a List<Integer> in the end.

The stream now is Stream<Integer>({0, 1, 2, 3, ..., 12, 13, 14, 15}).

  1. filter(n -> (n & (n - 1)) != 0) removes all power-of-2 elements from the stream including 0 (explanation). Why is this? Let's take a look at the binary representation of the current stream:

    {0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111}
    

    Now assign every bit to its respective array element: the number 0110 correspond to the elements {0.55, 25.00}, the number 0001 correspond to the elements {7.00} and the number 1111 correspond to all elements ({15.00, 0.55, 25.00, 7.00}) since all bits are set.

    Following your test cases, we cannot include the input numbers in the output array (for example, neither 15.0, 0.55, 25 or 7 should be in the output array). Therefore, we cannot include the numbers which contain a single bit (such as 0001 or 0100). These numbers are powers of 2, therefore we must remove them.

The stream now is Stream<Integer>({3, 5, 6, 7, ..., 12, 13, 14, 15}).

  1. map(...) maps the elements of this stream to another type. For each element n (assuming n is equal to 6),

    1. IntStream.range(0, arr.length) creates a stream from 0 until 4.

    The substream now is IntStream({0, 1, 2, 3}).

    1. filter(i -> ((n >> i) & 1) == 1) keeps only the indexes of the bits which are 1.

    The substream now is IntStream({1, 2}). Note that n is equal to 6, whose binary representation is 0110. Since the mid-two bits are set, the mid-two elements in the input array will be kept.

    1. mapToDouble(i -> arr[i]) maps each bit to its respective element in the input array.

    The substream now is IntStream({0.55, 25.00}).

    1. sum() sums all elements from this stream.

    The result is 25.55.

  2. collect(Collectors.toList()) will repeat step 4 for all element in this stream, returning a List<Double>.

The result is [15.55, 40.0, 25.55, 40.55, 22.0, 7.55, 22.55, 32.0, 47.0, 32.55, 47.55].

enzo
  • 9,861
  • 3
  • 15
  • 38
0

I don't see any reason why you want to use Stream. It's not the right context where you can use the Stream. I suggest you can simply create a Map and put the values in it

public class PossibleDoubleSums {
    
    static int count = 0;
    
    public static void getAllSums(Map<Integer,Double> imaps, double []arr, double startingValue, int pos  ) {
   
        for (int i = pos; i < arr.length; i++) {
            double currentValue = startingValue + arr[i];
            imaps.put(count++, currentValue);
            getAllSums(imaps, arr, currentValue, i + 1);
        }
        
    }
     
    public static void main(String[] args) {  
        Map<Integer,Double> imaps = new HashMap<>();
        double arr[] = {15.00, 0.55,25.00, 7.00};
        getAllSums(imaps, arr, 0, 0 ); // Test array
        System.out.println(imaps);
    }
}
Nagaraj S Kharvi
  • 73
  • 1
  • 2
  • 12
  • Nagaraj : i don’t want this , current is value is sum of different index’s of double array . I think I have asked question wrongly instead of Double , I want to store Double [] – chaitu Aug 07 '21 at 17:58
  • 1
    The expected output in your first code snippet is not a Map, it's a Map. – enzo Aug 07 '21 at 18:01