Search code examples
pythonrecursiondivide-and-conquer

Recursive, Divide and Conquer Max Subarray


I can't seem to figure out why I'm getting an error message on compile for the highlighted line below. the error message is "ValueError: need more than 2 values to unpack"... Thank you in advance for your help

def divConHelper(array, first, center, last):
    sumRight = float('-inf') #assign impossibly low number
    sumLeft = float('-inf') #assign impossibly low number
    leftIndexMax = 0
    rightIndexMax = 0 

    # Determine crossover max toward left
    currentLTotal = 0
    for i in range(first, center): 
    #Incrementally add values to sum
      currentLTotal += sum(array[i:center-1])
    #if the total is greater than the sumLeft, replace
      if currentLTotal > sumLeft:
        sumLeft = currentLTotal   
        leftIndexMax = i 

  # Determine crossover max toward right
    currentRTotal=0
    for i in range(center+1, last):
    #Incrementally add values to sum
      currentRTotal += sum(array[center:i+1])
    #if the rightTotal is greater than the sumRight, replace
      if currentRTotal > sumRight:
        sumRight = currentRTotal
        rightIndexMax = i+1 

    bothTotal = sumRight + sumLeft

    return(leftIndexMax, rightIndexMax, bothTotal)
    #return(bothTotal)

def divConMaxSub(self, array, first, last):

    if (last-first) == 0: 
      return array[first: last +1], array[0]


    center = (first+last)// 2
    #Recursive calls to divConMaxSub
    (minA, maxA, sumA) = self.divConMaxSub(array, first, center)
    (minB, maxB, sumB) = self.divConMaxSub(array, center+1, last)
    #call to get max cross values
    (maxL, maxR, maxCross) = divConHelper(array, first, center, last)

    #Calulate the max subarray value
    finalMax = max(sumA, sumB, maxCross)
    #Logic block for return values
    if (finalMax == sumA):
      return array[minA: maxA], sumA
      #return minA, maxA, sumA
    elif (finalMax == sumB):
      return array[minB: maxB], sumB
      #return minB, maxB, sumB
    elif (finalMax == maxCross):
      return array[maxL: maxR], maxCross
      #return maxL, maxR, maxCross 

and here is my main code

    from array import *
from utilities import utilities
from algorithms import algorithms  
def main():
   utils = utilities()
   alg = algorithms()
   results = utils.load()
   for line in results:
     max_sub_array, max_sum = alg.simpleenumeration(line)
     utils.printtofile("Simple Enumeration", max_sub_array, max_sum)
     max_sub_array, max_sum = alg.betterenumeration(line)
     utils.printtofile("Better Enumeration", max_sub_array, max_sum)
     max_sub_array, max_sum = alg.divConMaxSub(line)
     utils.printtofile("Divide and Conquer", max_sub_array, max_sum)
     max_sub_array, max_sum = alg.linear_sub_array(line)
     utils.printtofile("Linear sub array", max_sub_array, max_sum)
   #    print("--------------------")

main()

Solution

  • This statement:

    return array[minA: maxA], sumA
    

    does not return three arguments (as you seem to expect in this code):

    (minA, maxA, sumA) = self.divConMaxSub(array, first, center)
    

    it returns a chunk of your array as first argument and the sum as the second. Therefore, Python complains that it cannot use the output of divConMaxSub to initialize three values on the left, because only two values are available on the right.