0

I am trying to write scala code which gives maximum sum from contiguous sub-array from the given array. For example, val arr= Array(-2, -3, 4, -1, -2, 1, 5, -3). In this array I need to get maximum contiguous sub-array sum i.e 4+(-1)+(-2)+(1)+5 = 7. I wrote following code for getting this result.

scala> arr.foldLeft(0) { (currsum,newnum) => if((currsum+newnum)<0) 0 else { if(currsum<(currsum+newnum)) (currsum+newnum) else currsum }}
res5: Int = 10

but deviated from actual result as I am unable to update the maximum_so_farvalue as the counting/summation goes on. Since I have used foldLeft to do this functionality, is there any possibility to update the maximum_so_farvariable only when sum of contiguous sub array elements is greater than previous max_sum?

reference link for better understanding of scenario

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
Mahesh
  • 178
  • 3
  • 14
  • What do you mean by "contiguous sub-array"? – jub0bs Feb 13 '16 at 10:59
  • 1
    @Jubobs ,it means the max. sum should include the continuous elements from sub-array/ array. that means sum of 4+(-1)+(-2)+(1)+5 =7 but not the sum of 4+1+5 = 10 from the given array. for better understanding of scenario please check the link provided at bottom of above question.Thanks – Mahesh Feb 13 '16 at 11:03
  • 2
    Your code doesn't have a `maximum_so_far` value so it's not clear what you mean. But in general in foldLeft you don't "update" a variable, but pass a new value in the accumulator to the next iteration. So instead of passing just `currsum` pass a pair `(currsum, maxsofar)` and extract the values as necessary. – The Archetypal Paul Feb 13 '16 at 11:10

1 Answers1

1

Well, obviously you have to propagate two values along your input data for this computation, just as you would need to do in the imperative case:

arr.foldLeft((0,0)){
  case ((maxSum, curSum), value) => {
    val newSum = Math.max(0, curSum + value)
    (Math.max(maxSum, newSum), newSum)  
  }
}._1

An other way would be to compute the intermediate results (lazily if you want) and then select the maximum:

arr.toIterator.scanLeft(0){
  case (curSum, value) =>
    Math.max(0, curSum + value)
}.max
dth
  • 2,287
  • 10
  • 17