from acsploit.options import Options


options = Options()
options.add_option('type', 'mid', 'Variant of quicksort', ['mid', 'lomuto', 'hoare'])
options.add_option('n_inputs', 10, 'Number of elements to sort')

DESCRIPTION = ('Produces a worst-case input set for quicksort'
               '\n\n  Worst-case varies based on implementation:'
               '\n  for lomuto or hoare partition scheme with high value as pivot, sorted input is worst and gives O(n^2) runtime;'
               '\n  for mid variant pessimal input places the largest values at the pivots and gives O(n^2) runtime')


def run(generator, output):
    if options['type'] in ['lomuto', 'hoare']:
        # Worst case for Lomuto and Hoare quicksort is already sorted
        output.output(ascending_list(generator, options['n_inputs']))
    elif options['type'] == 'mid':
        # worst case for quicksort with midpoint pivots radiates from the center
        output.output(radiate_list(generator, options['n_inputs']))


def ascending_list(generator, n_inputs):
    return list(reversed(descending_list(generator, n_inputs)))


def descending_list(generator, n_inputs):
    output = [generator.get_max_value()]
    for i in range(1, n_inputs):
        output.append(generator.get_less_than(output[i-1]))
    return output


def radiate_list(generator, n_inputs):
    # generates the worst case list for quicksort with midpoint pivots (rounded to the left)
    reverse_ordered_list = descending_list(generator, n_inputs)  # Start with a reverse-sorted list
    output = [None] * len(reverse_ordered_list)
    k = len(reverse_ordered_list) - 1
    for i in range(0, len(reverse_ordered_list)):
        if i % 2 == 0:
            output[int(k-(i/2))] = reverse_ordered_list[i]
        else:
            output[int((i-1)/2)] = reverse_ordered_list[i]
    return output
