Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use an IntStream to sum specific indexed numbers of an int array?

I've been studying Kotlin and Java with lambdas. I'm trying the use the most of functional programming that I can, even though I don't know much of functional programming.

I'm using HackerRank's problems to study (and Koans to study Kotlin as well). I'm currently solving the problems using both Kotlin and Java 8.

I'm trying to solve the MiniMax-Sum problem. Basically, the description is something like this:

Given five positive integers, find the minimum and maximum values that can be calculated by summing exactly four of the five integers. Then print the respective minimum and maximum values as a single line of two space-separated long integers.

I'm trying to use the most of the streams API that I can when in Java. The simple question is: how can I reduce, after sorting, the int array to its four first elements (and last, in a different scenario) and sum its values? I was trying to use IntStream, but it seems that it's very difficult without using List. I was wondering if it possible to use directly the int[] array with IntStream to sort and reduce the elements and them sum it.

Using Kotlin I solved like this:

val minSum: Long = arr.sortedArray().copyOfRange(0, 4).sum().toLong()
val maxSum: Long = arr.sortedArray().copyOfRange(1, 5).sum().toLong()
println("$minSum $maxSum")

I'm trying to use the range method, together with sorted and sum. It works. The problem is that the sum always returns an int, and sometimes the sum is a long value. Here's my code:

long min = IntStream.range(0, arr.length)
        .sorted()
        .sum();

long max = IntStream.range(1, arr.length + 1)
        .sorted()
        .sum();

Result is 10 (min) and 15 (max) for the input new long[] {256741038, 623958417, 467905213, 714532089, 938071625}


Thanks a lot to everyone that took the time to help! Guess I did not see the LongStream.of method :D I solved using 2 different ways (pointed by @Aomine, @nullpointer and @Holger):

// using Arrays and Stream
Arrays.sort(arr);
long min = Arrays.stream(arr, 0, 4).sum();
long max = Arrays.stream(arr, 1, 5).sum();

System.out.println(min + " " + max);

// and using LongSummaryStatistics (thanks @Holger)
LongSummaryStatistics ls = LongStream.of(arr).summaryStatistics();
System.out.println((ls.getSum() - ls.getMax()) + " " + (ls.getSum() - ls.getMin()));

Thanks a lot guys!

like image 383
Andre Avatar asked Dec 19 '18 21:12

Andre


2 Answers

While you can solve this task by sorting, as shown in other answers, this is unnecessary work. “Summing four out of five” values means “summing all but one”, so all you have to do, is to subtract one element from the sum of all elements. Subtract the maximum element to get the minimum sum of four, subtract the minimum element to get the maximum sum of four:

IntSummaryStatistics s = IntStream.of(1, 3, 5, 7, 9).summaryStatistics();
System.out.printf("%d %d%n", s.getSum()-s.getMax(), s.getSum()-s.getMin());
16 24

Or, if the source is an array:

IntSummaryStatistics s = Arrays.stream(array).summaryStatistics();
System.out.printf("%d %d%n", s.getSum()-s.getMax(), s.getSum()-s.getMin());
like image 116
Holger Avatar answered Sep 18 '22 02:09

Holger


You might just be looking for something like Intstream.range(int startInclusive, int endExclusive)

Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive) by an incremental step of 1.

Over these then you can perform either sum directly or use IntSummaryStatistics with summaryStatistics() to further access the count, average, max, min etc.

Edit2: If you're looking forward to get the sum as long use summaryStatistics().getSum()

Edit2: If you're specifically looking to access the statistics of the data of an array, you can use Arrays.stream​(int[] array, int startInclusive, int endExclusive) which would return back an Instream as well.

like image 21
Naman Avatar answered Sep 22 '22 02:09

Naman