# L-13 MCS 275 Wed 13 Feb 2008 : mergesort.py

# We merge two sorted lists by selecting each
# time the smaller element of the two lists.

from random import randint

def Merge(A,B):
   """
   Returns the merge of lists A and B,
   adding each time min(A[0],B[0]).
   """
   L = []
   while len(A) > 0 and len(B) > 0:
      if A[0] <= B[0]:
         L.append(A.pop(0))
      else:
         L.append(B.pop(0))
   if len(A) > 0:
      return L + A
   else:
      return L + B

def RMergeSort(L):
   """
   Returns a list with the data of L
   sorted in increasing order.
   This is a recursive version.
   """
   print 'L =', L
   if len(L) <= 1:
      return L
   else:
      m = len(L)/2
      left = RMergeSort(L[0:m])
      right = RMergeSort(L[m:len(L)])
      return Merge(left,right)

def IMergeSort(L):
   """
   Returns a list with the data of L
   sorted in increasing order.
   This iterative version assumes
   len(L) is a power of 2.
   """
   ind = 1; hop = 2
   while hop <= len(L):
      k = 0
      while k+hop <= len(L):
         L[k:k+hop] = Merge(L[k:k+ind],L[k+ind:k+hop])
         k = k + hop
      ind = hop; hop = 2*hop
   return L

def main():
   """
   Calls MergeSort on a list of
   randomly generated numbers.
   """
   a = input('Give lower bound : ')
   b = input('Give lower bound : ')
   N = input('How many numbers ? ')
   r = lambda i: randint(a,b)
   L = map(r,range(0,N))
   print 'L =', L
   S = RMergeSort(L)
   print 'S =', S
   T = IMergeSort(L)
   print 'T =', T

main()
