# L-16 MCS 275 Wed 15 Feb 2017 : mergesort.py
"""
We merge two sorted lists by selecting each
time the smaller element of the two lists.
"""

from random import randint

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

def recursive_merge(data, verbose=True):
    """
    Returns a list with the data
    sorted in increasing order.
    """
    if verbose:
        print('data =', data)
    if len(data) <= 1:
        return data
    else:
        middle = len(data)//2
        left = recursive_merge(data[:middle])
        right = recursive_merge(data[middle:])
        return merge(left, right)

def iterative_merge(data):
    """
    Returns a list with the data
    sorted in increasing order.
    Assumes len(data) is a power of 2.
    """
    ind = 1
    hop = 2
    while hop <= len(data):
        k = 0
        while k+hop <= len(data):
            data[k:k+hop] = merge(data[k:k+ind], data[k+ind:k+hop])
            k = k + hop
        ind = hop
        hop = 2*hop
    return data

def main():
    """
    Calls merge sort on a list of
    randomly generated numbers.
    """
    low = int(input('Give lower bound : '))
    upp = int(input('Give lower bound : '))
    size = int(input('How many numbers ? '))
    data = [randint(low, upp) for _ in range(size)]
    print('data =', data)
    srt = recursive_merge(data)
    print('after sort :', srt)
    srt = iterative_merge(data)
    print('after sort :', srt)

if __name__ == "__main__":
    main()
