Click here to Skip to main content
15,886,519 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Python
class Node:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.next = None

class LinkedList:
    def __init__(self):
        self.head = None

    def search(self, key):
        curr = self.head
        while curr != None:
            if curr.key == key:
                return curr
            curr = curr.next
        return None

    def insert(self, key, value):
        node = Node(key, value)
        node.next = self.head
        self.head = node

    def delete(self, key):
        prev = None
        curr = self.head
        while curr != None:
            if curr.key == key:
                if prev == None:
                    self.head = curr.next
                else:
                    prev.next = curr.next
                return True
            prev = curr
            curr = curr.next
        return False

class HashMap:
    def __init__(self, capacity=16):
        self.capacity = capacity
        self.size = 0
        self.table = [LinkedList() for _ in range(capacity)]

    def _hash(self, key):
        return hash(key) % self.capacity

    def get(self, key):
        index = self._hash(key)
        node = self.table[index].search(key)
        if node:
            return node.value
        return None

    def put(self, key, value):
        index = self._hash(key)
        node = self.table[index].search(key)
        if node:
            node.value = value
        else:
            self.table[index].insert(key, value)
            self.size += 1
            if self.size > self.capacity * 0.75:
                self._resize()

    def delete(self, key):
        index = self._hash(key)
        if self.table[index].delete(key):
            self.size -= 1

    def _resize(self):
        self.capacity *= 2
        new_table = [LinkedList() for _ in range(self.capacity)]
        for bucket in self.table:
            curr = bucket.head
            while curr != None:
                index = self._hash(curr.key)
                new_table[index].insert(curr.key, curr.value)
                curr = curr.next
        self.table = new_table</blockquote>


<pre lang="Python">import csv
from hashmap import HashMap
from math import sin, cos, sqrt, atan2


# initialize variables to store data
location_map = HashMap()
item_map = HashMap()
order_map = HashMap()


def load_location_data():
    with open('location_data.csv', 'r') as file:
        reader = csv.reader(file)
        for row in reader:
            location_name = row[0]
            inventory = row[1:]
            location_map[location_name] = inventory


def load_order_data():
    with open('order_data.csv', 'r') as file:
        reader = csv.reader(file)
        for row in reader:
            order_id = row[0]
            locations = row[1:]
            order_map[order_id] = locations


def load_serialised_data():
    with open('serialised_data.csv', 'r') as file:
        reader = csv.reader(file)
        for row in reader:
            location_name = row[0]
            item = row[1]
            quantity = int(row[2])
            if location_name not in item_map:
                item_map[location_name] = {}
            item_map[location_name][item] = quantity


def find_location_inventory():
    location_name = input("Enter location name: ")
    inventory = location_map[location_name]
    print(f"Location inventory for {location_name}:")
    for item in inventory:
        print(item)


def find_distance():
    start_location = input("Enter starting location: ")
    end_location = input("Enter ending location: ")
    start_coords = tuple(float(x) for x in location_map[start_location][:2])
    end_coords = tuple(float(x) for x in location_map[end_location][:2])
    # calculate distance using Haversine formula
    earth_radius = 6371.01  # km
    lat1, lon1 = start_coords
    lat2, lon2 = end_coords
    delta_lat = lat2 - lat1
    delta_lon = lon2 - lon1
    a = (sin(delta_lat / 2)) ** 2 + cos(lat1) * cos(lat2) * (sin(delta_lon / 2)) ** 2
    c = 2 * atan2(sqrt(a), sqrt(1 - a))
    distance = earth_radius * c
    print(f"Distance from {start_location} to {end_location}: {distance:.2f} km")


def find_order_route():
    order_id = input("Enter order ID: ")
    locations = order_map[order_id]
    print(f"Route for order {order_id}:")
    total_distance = 0
    for i in range(len(locations) - 1):
        start_location = locations[i]
        end_location = locations[i + 1]
        start_coords = tuple(float(x) for x in location_map[start_location][:2])
        end_coords = tuple(float(x) for x in location_map[end_location][:2])
        # calculate distance using Haversine formula
        earth_radius = 6371.01  # km
        lat1, lon1 = start_coords
        lat2, lon2 = end_coords
        delta_lat = lat2 - lat1
        delta_lon = lon2 - lon1
        a = (sin(delta_lat / 2)) ** 2 + cos(lat1) * cos(lat2) * (sin(delta_lon / 2)) ** 2
        c = 2 * atan2(sqrt(a), sqrt(1 - a))
        distance = earth_radius * c
        total_distance += distance
        print(f"From {start_location} to {end_location}: {distance:.2f} km")
    print(f"Total distance for order {order_id}: {total_distance:.2f} km")

def location_overview():
    print("Location overview:")
    for location, items in location_map.items():
        print(f"{location}: {len(items)} items in inventory")

def inventory_overview(inventory):
    total_items = 0
    total_value = 0

    for item, info in inventory.items():
        total_items += info['quantity']
        total_value += info['price'] * info['quantity']
        print(f"{item.capitalize()}: {info['quantity']} units, ${info['price']} each")

    print(f"\nTotal number of items: {total_items}")
    print(f"Total value of inventory: ${total_value}")

def save_data():
    with open('serialised_data.csv', 'w', newline='') as file:
        writer = csv.writer(file)
        for loc, items in item_map.items():
            for item, quantity in items.items():
                writer.writerow([loc, item, quantity])
        print("Data saved successfully")

# menu loop
while True:
    print("Welcome to the Interactive Menu:")
    print("1. Load data")
    print("2. Find and display location Inventory")
    print("3. Find and dislpay distance between two locations")
    print("4. Find and display route for collecting order")
    print("5. Location Overview")
    print("6. Inventory Overview")
    print("7. Save data")
    print("8. Exit")
   
    choice = input("Select which option you would like to choose: ")
   
    if choice == "1":
        load_location_data()
        load_order_data()
        load_serialised_data()
        print("Data successfully loaded")

    elif choice == "2":
        find_location_inventory()

    elif choice == "3":
        find_distance()

    elif choice == "4":
        find_order_route()

    elif choice == "5":
        location_overview()

    elif choice == "6":
        inventory_overview()

    elif choice == "7":
        save_data()
        print("Data saved successfully")

    elif choice == "8":
        #code for option8
        print("Exiting the interactive menu")
        break

    else:
        print("Invalid option was selected")


What I have tried:

The HashMap function wasn't originally written using linked lists, but the same errors were still present. I rewrote the code using a linked list to factor in the collisions that would be caused, but the same errors persisted. The main goal of the code is to make the interactive menu work by displaying the information that gets imported by the CSV files. Whenever I run the interactive menu and choose an option to run, I either get an attribute error or a typeerror that is associated with the HashMap file. I have tried rewriting the code in different forms but the same problem keeps coming back. 

The following is what is in the CSV files.

location_data:
"Location name", "products", "distance"
"Location A", "Item 1, Item 2, Item 3, Item 4", "40.7128, -74.2312"
"Location B", "Item 1, Item 2", "35.2321, -83.2415"
"Location C", "Item 1, Item 2, Item 3", "41.1633, -52.2352"
"Location D", "Item 1, Item 2, Item 3, Item 4, Item 5", "32.2512, -85.3425"

order_data:
"Order ID", "Order route"
"Order 1", "Location A, Location B"
"Order 2", "Location A"
"Order 3", "Location B, Location C"
"Order 4", "Location C, Location A, Location D"

serialised_data:
"Location", "Items", "Quantity"
"Location A", "Item 1", "4"
"Location A", "Item 2", "5"
"Location B", "Item 5", "2"
"Location C", "Item 2", "7"
"Location D", "Items 4", "9"
"Location D", "Item 3", "10"
Posted
Updated 22-Mar-23 3:33am

1 solution

In order to use the [] operator you need to implement 3. Data model — Python 3.11.2 documentation: __getitem__()[^]. See also 3. Data model — Emulating container types[^] for complete details.
 
Share this answer
 
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900