Search code examples
pythonalgorithmsortinginsertion

Insertion and Bubble Sort partially working


all I'm new to Python's Data Structure & Algorithm. I implemented Insertion & Bubble Sort into my inventory program. Both my insertion and bubble sort works when I'm sorting the current dictionary. However, after adding new items or removing items from my dictionary, my insertion and bubble sort obtained a key error. I've tried changing the dictionary to [{description..}] and also changing market[len(market) + 1] to market[len(market)] before. None of these work at all. Would really appreciate if someone helped me edit my code or explain to me what's going on. Thank you in advance :")

market = {0: {'Description': 'Chocolate', 'Stock': 65, 'Price': 3.2, 'Expiry': '27 Dec', 'Discount': 'eligible'},
          1: {'Description': 'Bread', 'Stock': 20, 'Price': 2.7, 'Expiry': '15 June', 'Discount': 'eligible'},
          2: {'Description': 'Apples', 'Stock': 97, 'Price': 10.6, 'Expiry': '12 July', 'Discount': 'not eligible'},
          3: {'Description': 'Potato', 'Stock': 81, 'Price': 20.8, 'Expiry': '13 April', 'Discount': 'not eligible'},
          4: {'Description': 'Ice', 'Stock': 91, 'Price': 9.8, 'Expiry': '16 April', 'Discount': 'not eligible'}
          }


def menu():
    print('Press 1: To Add items. ')
    print('Press 2: To View items. ')
    print('Press 3: To Remove items. ')
    print('Press 4: Use Insertion Sort. ')
    print('Press 5: Use Bubble Sort. ')
    print('Press 6: Use Binary Search. ')
    print('Press 7: View Total and Average stock level. ')
    print('Press q: To Quit program. ')
    return input('What would you like to do? ')


# print(len(market) + 1) # check counter


# Insertion Sort

def insertionSort(theSeq, key):

    for i in range(1, len(theSeq)):
        temp = theSeq[i][key]
        j = i
        while j > 0 and temp < theSeq[j - 1][key]:
               theSeq[j][key] = theSeq[j - 1][key]
               j = j - 1
        theSeq[j][key] = temp
    return theSeq


# Sorting Menu
def sort_menu(second_list, sort_type):
    print('1. Sort by Description')
    print('2. Sort by Price')

    # Get user input
    user_input = input('Please enter choice: ')

    if user_input == '1':
        second_list = sort_type(second_list, 'Description')
        print('Success! Inventory list is sorted by Description!')

    elif user_input == '2':
        second_list = sort_type(second_list, 'Price')
        print('Success! Inventory list is sorted by Price!')
    else:
        print('You have entered an invalid option!')

    # Return updated list
    return second_list


# Bubble Sort
def bubble_sort(second_list, key):

    # Create temp copy of list
    temp = second_list.copy()

    # Obtain length of list
    y = len(temp)

    for i in range(y - 1, 0, -1):
        for j in range(i):
            if temp[j][key] > temp[j + 1][key]:
                temp[j], temp[j + 1] = temp[j + 1], temp[j]
    # Return updated list
    return temp

# Binary Search
def binarysearch(dictionary,item):
    global founditem
    itemlist = []
    for item2 in dictionary:
        itemlist.append(item2)
    first = 0
    last = len(itemlist) - 1
    found = False

    while first <= last and not found:
        midpoint = (first + last)//2
        if itemlist[midpoint] == item:
            # print(midpoint) test print out
            founditem = dictionary.get(midpoint)
            found = True
        else:
            if item < itemlist[midpoint]:
                last = midpoint-1
            else:
                first = midpoint+1
    return founditem


# Print total and average stock level
def average(market):
    n = len(market)
    total = 0
    for i in range(0,n):
        total += market[i]["Stock"]
    average = total/n
    return average

def total(market):
    n = len(market)
    total = 0
    for i in range(0,n):
        total += market[i]["Stock"]
    return total


while True:
    run = menu()
    if run == '1':
        # market[len(market) + 1] = {}
        # addMarket = input('Item to be added to Market? ')
        # market[len(market) + 1]['Description'] = addMarket
        name = input('Item to be added to Market? ')
        price = float(input('Price of food?'))
        amount = int(input('Qty of food to be added to stock? '))
        expiry = input('Enter expiry date: ')
        discount = input('Enter eligibility of discount: ')
        market[len(market) + 1] = {'Description': name, 'Stock': amount, 'Price': price, 'Expiry': expiry,
                                   'Discount': discount}

    elif run == '2':
        for i in market:
            item = market[i]
            print("Item No - %d Description - %s Stock - %d Price - %.2f Expiry - %s Discount - %s" % (
            i, item['Description'], item['Stock'], item['Price'], item['Expiry'], item['Discount']))


    elif run == '3':
        remove = int(input('Key in item number to remove: '))
        del market[remove]

    elif run == '4':
        market = sort_menu(market, insertionSort)

    elif run == '5':
        market = sort_menu(market, bubble_sort)
    #
    elif run == '6':
        key = int(input('Enter key you want to search: '))
        print(binarysearch(market, key))

    elif run == '7':
        print('')
        print('Total stock level is',total(market), 'and Average stock level is', average(market))
        print('')

    else:
        quit = str()
        while quit.upper() != "Q":
            quit = input("Enter Q or q to return to Main Menu. ")
            if quit.upper() == "Q":
                print('Thank you for using MamaStore!')
                menu()

Solution

  • The problem with your insertion code is that you are inserting new elements by skipping one index per insertion. Initially size of market is 5 so when you insert new element that element should go at index 5 (starting index is 0) but market[len(market)+1] is inserting at index 6. So when you run a sequential loop in sorting it throws a keyerror because you dont have 5 as a key.
    Similarly in deletion when you delete any item, sequence breaks which leads to the keyerror as it did in the case of insertion. You should probably consider running the loops over the keys of the dictionary which in your case are those item ids.
    However for your code specifically it would be convinient to convert dict to a list and then perform the sorting later before returning it convert it back to dictionary. I am attaching a working code below:

    
    market = {0: {'Description': 'Chocolate', 'Stock': 65, 'Price': 3.2, 'Expiry': '27 Dec', 'Discount': 'eligible'},
              1: {'Description': 'Bread', 'Stock': 20, 'Price': 2.7, 'Expiry': '15 June', 'Discount': 'eligible'},
              2: {'Description': 'Apples', 'Stock': 97, 'Price': 10.6, 'Expiry': '12 July', 'Discount': 'not eligible'},
              3: {'Description': 'Potato', 'Stock': 81, 'Price': 20.8, 'Expiry': '13 April', 'Discount': 'not eligible'},
              4: {'Description': 'Ice', 'Stock': 91, 'Price': 9.8, 'Expiry': '16 April', 'Discount': 'not eligible'}
              }
    
    
    def menu():
        print('Press 1: To Add items. ')
        print('Press 2: To View items. ')
        print('Press 3: To Remove items. ')
        print('Press 4: Use Insertion Sort. ')
        print('Press 5: Use Bubble Sort. ')
        print('Press 6: Use Binary Search. ')
        print('Press 7: View Total and Average stock level. ')
        print('Press q: To Quit program. ')
        return input('What would you like to do? ')
    
    
    # Insertion Sort
    
    def insertionSort(theSeq, key):
        temp1 = [i for i in theSeq.values()]
        for i in range(0, len(temp1)):
            temp = temp1[i][key]
            j = i
            while j > 0 and temp < temp1[j - 1][key]:
                temp1[j][key] = temp1[j - 1][key]
                j = j - 1
            temp1[j][key] = temp
        s = {}
        for i in range(len(temp1)):
            s[i] = temp1[i]
        return s
    
    
    # Sorting Menu
    def sort_menu(second_list, sort_type):
        print('1. Sort by Description')
        print('2. Sort by Price')
    
        # Get user input
        user_input = input('Please enter choice: ')
        if user_input == '1':
            second_list = sort_type(second_list, 'Description')
            print('Success! Inventory list is sorted by Description!')
    
        elif user_input == '2':
            second_list = sort_type(second_list, 'Price')
            print('Success! Inventory list is sorted by Price!')
        else:
            print('You have entered an invalid option!')
    
        # Return updated list
        return second_list
    
    
    # Bubble Sort
    def bubble_sort(second_list, key):
        # Create temp copy of list
        temp = [i for  i in second_list.values()]
    
        # Obtain length of list
        y = len(temp)
    
        for i in range(y - 1, 0, -1):
            for j in range(i):
                if temp[j][key] > temp[j + 1][key]:
                    temp[j], temp[j + 1] = temp[j + 1], temp[j]
        # Return updated list
        s = {}
        for i in range(len(temp)):
            s[i] = temp[i]
        return s
    
    # Binary Search
    def binarysearch(dictionary,item):
        global founditem
        itemlist = []
        for item2 in dictionary:
            itemlist.append(item2)
        first = 0
        last = len(itemlist) - 1
        found = False
    
        while first <= last and not found:
            midpoint = (first + last)//2
            if itemlist[midpoint] == item:
                # print(midpoint) test print out
                founditem = dictionary.get(midpoint)
                found = True
            else:
                if item < itemlist[midpoint]:
                    last = midpoint-1
                else:
                    first = midpoint+1
        return founditem
    
    
    # Print total and average stock level
    def average(market):
        n = len(market)
        total = 0
        for i in range(0,n):
            total += market[i]["Stock"]
        average = total/n
        return average
    
    def total(market):
        n = len(market)
        total = 0
        for i in range(0,n):
            total += market[i]["Stock"]
        return total
    
    
    while True:
        run = menu()
        if run == '1':
            name = input('Item to be added to Market? ')
            price = float(input('Price of food?'))
            amount = int(input('Qty of food to be added to stock? '))
            expiry = input('Enter expiry date: ')
            discount = input('Enter eligibility of discount: ')
            market[len(market)] = {'Description': name, 'Stock': amount, 'Price': price, 'Expiry': expiry,
                                       'Discount': discount}
    
        elif run == '2':
            for i in market:
                item = market[i]
                print("Item No - %d Description - %s Stock - %d Price - %.2f Expiry - %s Discount - %s" % (
                i, item['Description'], item['Stock'], item['Price'], item['Expiry'], item['Discount']))
    
        elif run == '3':
            remove = int(input('Key in item number to remove: '))
            del market[remove]
    
        elif run == '4':
            market = sort_menu(market, insertionSort)
    
        elif run == '5':
            market = sort_menu(market, bubble_sort)
    
        elif run == '6':
            key = int(input('Enter key you want to search: '))
            print(binarysearch(market, key))
    
        elif run == '7':
            print('')
            print('Total stock level is',total(market), 'and Average stock level is', average(market))
            print('')
    
        else:
            quit = str()
            while quit.upper() != "Q":
                quit = input("Enter Q or q to return to Main Menu. ")
                if quit.upper() == "Q":
                    print('Thank you for using MamaStore!')
                    menu()
    

    Hope it helps!