Corner Grocer’s frequency tracking system is the core of the application. It reads a plain-text purchase log line by line, normalizes each item name to lowercase, and increments an internal counter for every occurrence. Once the file is loaded, users can query how many times any single item was purchased, print a full sorted list of every item and its count, or render an asterisk-based histogram directly in the terminal — all from the interactive menu.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/corner-grocer/llms.txt
Use this file to discover all available pages before exploring further.
How items are read
Theprocess_input_file method on the GroceryFrequency class reads the input file and populates the internal frequency dictionary:
defaultdict(int) — self.frequency is initialized as a defaultdict(int), which means accessing any key that does not yet exist automatically returns 0 instead of raising a KeyError. This removes the need for an explicit “does this key exist?” check before incrementing — self.frequency[item] += 1 works correctly on both new and existing keys.
Lowercase normalization — each line is passed through .strip() to remove leading/trailing whitespace and newline characters, then through .lower() to convert to lowercase. "Apples", "APPLES", and "apples" are all stored as "apples" and counted together.
FileNotFoundError — if the filename passed to the method does not exist on disk, Python raises FileNotFoundError. The except block catches it, prints a descriptive message, and calls sys.exit(1) to terminate the program cleanly rather than letting a traceback reach the user.
All item names are normalized to lowercase before they are stored in the frequency dictionary. If your input file contains
Apples, apples, and APPLES on different lines, all three are counted as a single entry: apples. Capitalization differences are merged automatically.Looking up a single item
Menu option 1 prompts the user for a name and callslookup_item_frequency:
Apples correctly matches the stored key apples. dict.get(key, default) returns 0 when the item has never been seen, so the caller always receives an integer.
Example terminal interaction:
is_valid_item_name:
True only if every character is either an alphabetic letter (ch.isalpha()) or a space (ch.isspace()). Digits, punctuation, and other symbols cause it to return False, and the menu loop prints an error and re-prompts rather than executing the lookup. This prevents unexpected keys from being introduced into the dictionary through user queries.
Printing all frequencies
Menu option 2 callsprint_all_frequencies, which iterates over every stored item in alphabetical order and prints each name alongside its count:
sorted() is called on self.frequency.keys(), which produces a new alphabetically sorted list without modifying the underlying dictionary. Each line is formatted as item: count.
Sample output:
Histogram display
Menu option 3 callsprint_histogram, which renders each item’s count as a row of asterisks:
'*' * count repeats the asterisk character exactly count times. An item purchased once produces a single *; an item purchased four times produces ****. Items are still iterated in alphabetical order so the histogram is easy to scan.
Sample output (first several items):
Input file format
Corner Grocer reads fromgrocery_frequency_input.txt by default (set as INPUT_FILE in corner_grocer.py). The expected format is one item name per line:
Bell Peppers and Green Beans are supported because the only separator is the newline character. Blank lines are skipped — the if item: guard after .strip() ensures that empty strings are never added to the dictionary.