Home Finances - Python Programming Exercise

In this exercise, you will develop a Python program that can store up to 10,000 records of expenses and incomes to create a small household accounting system. For each expense (or income), the following information should be saved: Date (8 characters: YYYYMMDD format), Description of the expense or income, Category, and Amount (positive for income, negative for expenses). The program should allow the user to perform the following operations: add a new expense (the date should "seem correct": day 01 to 31, month 01 to 12, year between 1000 and 3000; the description must not be empty; no need to validate the other data), show all expenses of a certain category (e.g., "education") between two specific dates (e.g., between "20110101" and "20111231"; display the number, date (format DD/MM/YYYY), description, category in parentheses, and amount to two decimal places, all in the same line, separated by hyphens; at the end, show the total amount of the displayed data), search for expenses containing a certain text (in the description or category, case insensitive; display the number, date, and description (truncated to 50 characters if longer); notify the user if none are found), modify a record (prompt the user for the record number, display the previous value of each field, and allow the user to press Enter to leave any field unchanged; warn (but do not re-prompt) if the user enters an incorrect record number; no need to validate any data), delete records (starting from the number entered by the user; warn (but do not re-prompt) if an incorrect number is entered; display the record to be deleted and prompt for confirmation before deletion), sort data alphabetically by date and (if dates match) by description, normalize descriptions (remove trailing spaces and duplicate spaces; if a description is all uppercase, convert it to lowercase (except for the first letter, which remains uppercase)), and quit the application (as we do not store the information, the data will be lost). This exercise is perfect for practicing the use of arrays and data manipulation in Python, as well as enhancing your skills in user interaction and database management. By implementing these functionalities, you will gain hands-on experience in handling user input and output in Python. This exercise not only reinforces your understanding of arrays and data manipulation but also helps you develop efficient coding practices for managing large datasets.

 Category

Arrays, Lists, and Strings

 Exercise

Home Finances

 Objective

Develop a Python program that can store up to 10000 records of expenses and incomes to create a small household accounting system. For each expense (or income), the following information should be saved:

• Date (8 characters: YYYYMMDD format)
• Description of the expense or income
• Category
• Amount (positive for income, negative for expenses)

The program should allow the user to perform the following operations:

1 - Add a new expense (the date should "seem correct": day 01 to 31, month 01 to 12, year between 1000 and 3000). The description must not be empty. No need to validate the other data.

2 - Show all expenses of a certain category (e.g., "education") between two specific dates (e.g., between "20110101" and "20111231"). Display the number, date (format DD/MM/YYYY), description, category in parentheses, and amount to two decimal places, all in the same line, separated by hyphens. At the end, show the total amount of the displayed data.

3 - Search for expenses containing a certain text (in the description or category, case insensitive). Display the number, date, and description (truncated to 50 characters if longer). Notify the user if none are found.

4 - Modify a record (prompt the user for the record number, display the previous value of each field, and allow the user to press Enter to leave any field unchanged). Warn (but do not re-prompt) if the user enters an incorrect record number. No need to validate any data.

5 - Delete records, starting from the number entered by the user. Warn (but do not re-prompt) if an incorrect number is entered. Display the record to be deleted and prompt for confirmation before deletion.

6 - Sort data alphabetically by date and (if dates match) by description.

7 - Normalize descriptions: remove trailing spaces and duplicate spaces. If a description is all uppercase, convert it to lowercase (except for the first letter, which remains uppercase).

Q - Quit the application (as we do not store the information, the data will be lost).

 Example Python Exercise

 Copy Python Code
import re
from datetime import datetime

# List to store records
records = []

# Loop for user interaction
while True:
    # Show menu
    print("\nMenu:")
    print("1 - Add a new expense")
    print("2 - Show all expenses of a category between two dates")
    print("3 - Search for expenses containing a certain text")
    print("4 - Modify a record")
    print("5 - Delete records")
    print("6 - Sort data")
    print("7 - Normalize descriptions")
    print("Q - Quit")
    
    choice = input("Choose an option: ").strip().lower()

    if choice == '1':  # Add a new expense
        date = input("Enter date (YYYYMMDD): ")
        while True:
            try:
                datetime.strptime(date, "%Y%m%d")
                break
            except ValueError:
                print("Invalid date format. Please enter a valid date (YYYYMMDD).")
                date = input("Enter date (YYYYMMDD): ")
        
        description = input("Enter description: ").strip()
        while not description:
            print("Description cannot be empty.")
            description = input("Enter description: ").strip()
        
        category = input("Enter category: ").strip()
        amount = input("Enter amount (positive for income, negative for expense): ")
        while not amount.replace('.', '', 1).isdigit() or float(amount) == 0:
            print("Invalid amount. Enter a valid number (positive for income, negative for expense).")
            amount = input("Enter amount (positive for income, negative for expense): ")
        
        records.append({
            'date': date,
            'description': description,
            'category': category,
            'amount': float(amount)
        })

    elif choice == '2':  # Show all expenses of a category between two dates
        category = input("Enter category: ").strip()
        start_date = input("Enter start date (YYYYMMDD): ")
        end_date = input("Enter end date (YYYYMMDD): ")

        while True:
            try:
                datetime.strptime(start_date, "%Y%m%d")
                datetime.strptime(end_date, "%Y%m%d")
                break
            except ValueError:
                print("Invalid date format. Please enter valid dates (YYYYMMDD).")
                start_date = input("Enter start date (YYYYMMDD): ")
                end_date = input("Enter end date (YYYYMMDD): ")

        total_amount = 0.0
        count = 0
        for i, record in enumerate(records):
            if record['category'].lower() == category.lower() and start_date <= record['date'] <= end_date:
                print(f"{i+1} - {record['date'][6:8]}/{record['date'][4:6]}/{record['date'][:4]} - {record['description']} - ({record['category']}) - {record['amount']:.2f}")
                total_amount += record['amount']
                count += 1

        if count > 0:
            print(f"Total: {total_amount:.2f}")
        else:
            print("No records found.")

    elif choice == '3':  # Search for expenses containing a certain text
        search_text = input("Enter the text to search for: ").strip().lower()

        count = 0
        for i, record in enumerate(records):
            if search_text in record['description'].lower() or search_text in record['category'].lower():
                print(f"{i+1} - {record['date'][6:8]}/{record['date'][4:6]}/{record['date'][:4]} - {record['description'][:50]}...")
                count += 1
        
        if count == 0:
            print("No records found.")

    elif choice == '4':  # Modify a record
        record_number = input("Enter record number to modify: ")
        while not record_number.isdigit() or int(record_number) < 1 or int(record_number) > len(records):
            print("Invalid record number.")
            record_number = input("Enter record number to modify: ")
        
        record_index = int(record_number) - 1
        record = records[record_index]

        print(f"Current record: {record['date']} - {record['description']} - {record['category']} - {record['amount']:.2f}")
        
        date = input(f"Enter new date (current: {record['date']}): ").strip()
        if date:
            record['date'] = date
        
        description = input(f"Enter new description (current: {record['description']}): ").strip()
        if description:
            record['description'] = description
        
        category = input(f"Enter new category (current: {record['category']}): ").strip()
        if category:
            record['category'] = category
        
        amount = input(f"Enter new amount (current: {record['amount']:.2f}): ").strip()
        if amount:
            record['amount'] = float(amount)

    elif choice == '5':  # Delete records
        start_record = input("Enter starting record number to delete: ")
        end_record = input("Enter ending record number to delete: ")
        
        while not start_record.isdigit() or not end_record.isdigit() or int(start_record) > int(end_record) or int(start_record) < 1 or int(end_record) > len(records):
            print("Invalid record numbers.")
            start_record = input("Enter starting record number to delete: ")
            end_record = input("Enter ending record number to delete: ")

        for i in range(int(start_record) - 1, int(end_record)):
            print(f"Deleting record: {records[i]}")
            confirm = input("Are you sure? (y/n): ").strip().lower()
            if confirm == 'y':
                del records[i]
                break

    elif choice == '6':  # Sort data
        records.sort(key=lambda x: (x['date'], x['description'].lower()))
        print("Records sorted.")

    elif choice == '7':  # Normalize descriptions
        for record in records:
            record['description'] = re.sub(' +', ' ', record['description']).strip()
            if record['description'].isupper():
                record['description'] = record['description'].capitalize()
        print("Descriptions normalized.")

    elif choice == 'q':  # Quit
        break

    else:
        print("Invalid choice. Please try again.")

 Output

Case 1:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 1
Enter date (YYYYMMDD): 20231225
Enter description: Christmas gifts
Enter category: Gifts
Enter amount (positive for income, negative for expense): -200

Case 2:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 2
Enter category: Gifts
Enter start date (YYYYMMDD): 20231201
Enter end date (YYYYMM31): 20231231
1 - 25/12/2023 - Christmas gifts - (Gifts) - -200.00
Total: -200.00

Case 3:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 3
Enter the text to search for: gifts
1 - 25/12/2023 - Christmas gifts...

Case 4:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 4
Enter record number to modify: 1
Current record: 20231225 - Christmas gifts - Gifts - -200.00
Enter new date (current: 20231225): 
Enter new description (current: Christmas gifts): 
Enter new category (current: Gifts): 
Enter new amount (current: -200.00): 

Case 5:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 5
Enter starting record number to delete: 1
Enter ending record number to delete: 1
Deleting record: {'date': '20231225', 'description': 'Christmas gifts', 'category': 'Gifts', 'amount': -200.0}
Are you sure? (y/n): y

Case 6:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 6
Records sorted.

Case 7:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 7
Descriptions normalized.

Case 8:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: q

 Share this Python Exercise

 More Python Programming Exercises of Arrays, Lists, and Strings

Explore our set of Python Programming Exercises! Specifically designed for beginners, these exercises will help you develop a solid understanding of the basics of Python. From variables and data types to control structures and simple functions, each exercise is crafted to challenge you incrementally as you build confidence in coding in Python.

  •  Array Reversal

    This Python program prompts the user to input 5 numbers and stores them in an array (or list in Python). After all the numbers are entered, the program displays them ...

  •  Array Lookup

    his Python program asks the user to input a specific number of floating-point numbers and stores them in a list. The program then repeatedly prompts the user to enter...

  •  Even Number Array

    This Python program prompts the user to enter 10 integer numbers and displays only the even numbers from the list. It utilizes a for loop to iterate through th...

  •  Positive and Negative Number Array

    This Python program prompts the user to enter 10 real numbers and calculates two averages: one for the positive numbers and another for the negative numbers...

  •  Numerous Numbers and Their Sum

    This Python program prompts the user to enter several numbers, calculating their sum as they go. The program continues to prompt the user for numbers until they enter...

  •  Matrix Array

    This Python programming exercise is ideal for practicing the handling of multidimensional arrays. In this case, the goal is to prompt the user for the marks of 20 students, ...