# L-16 MCS 275 Wed 20 Feb 2008 : maxtrip.py

# Consider a list L of positive numbers. 
# Give an algorithm to find that triplet
# of elements # in L whose sum is maximal. 
# Given the list L # on input, the Python
# function returns the triplet (i,j,k)
# so that L[i] + L[j] + L[k] is maximal
# over all other choices of three numbers in L.

# We build the solution in three steps:
# (1) ShowTriplets : enumerates all triplets
# (2) MaxSumTriplets : returns maximal sum
# (3) MaxSelTriplets : return also selection

def ShowTriplets(L,T,k):
   """
   Enumerates all triplets in L,
   using T as accumulator,
   selecting in L from index k.
   """
   if len(T) == 3:
      print T
   else:
      for i in range(k,len(L)-2+len(T)):
         ShowTriplets(L,T+[L[i]],i+1)

def max(a,b):
   """
   Return maximum of a and b.
   """
   if a > b:
      return a
   else:
      return b

def MaxSumTriplets(L,T,k,s):
   """
   Enumerates all triplets in L,
   using T as accumulator,
   selecting in L from index k,
   returns the maximal sum.
   """
   if len(T) == 3:
      return max(sum(T),s)
   else:
      for i in range(k,len(L)-2+len(T)):
         s = MaxSumTriplets(L,T+[L[i]],i+1,s)
      return s

def MaxSelTriplets(L,T,S,k,mx,sl):
   """
   Enumerates all triplets in L,
   using T and S as accumulator,
   selecting in L from index k,
   where mx and sl hold the current
   maximum and selection from L.
   Returns a tuple (max,(i,j,k)).
   """
   if len(T) == 3:
      if sum(T) > mx:
         return (sum(T),(S[0],S[1],S[2]))
      else:
         return (mx,sl)
   else:
      for i in range(k,len(L)-2+len(T)):
        (mx,sl) = MaxSelTriplets(L,T+[L[i]],S+[i],i+1,mx,sl)
      return (mx,sl)

def main():
   """
   Prompts the user for a list
   and enumerates triplets.
   """
   L = input('Give a list : ')
   ShowTriplets(L,[],0)
   m = MaxSumTriplets(L,[],0,0)
   print 'max sum =', m
   (m,s) = MaxSelTriplets(L,[],[],0,0,())
   print 'max sum =', m, 'at', s

main()
