Scientific Computing with Python Projects - Budget App

Hello everybody!
I have a serious problem with this exercise, I succeeded all the tests but when I test with my own tests it does not work.
The problem is at the level of the last function, in the test everything is ok but when I try it with the code for the exercise all the lines are offset from a space except line 0.
I would be very grateful to you to enlighten me on this problem which seems to me to be like magic …
thanks in advance

link to the code “boilerplate-budget-app - Replit

My code :

import math
class Category:
    def __init__(self, name):
        self.name = name
        self.ledger = []

    def __str__(self):
        # line 1
        name = str(self.name)
        len_name = len(name)
        stars = '*' * int((30 - len_name) / 2)
        line_1 = stars + name + stars + '\n'
        # line 2
        line_2 = ''
        for operation in self.ledger:
            description_str = operation['description'][0:23]
            amount_str = "{:.2f}".format(operation['amount'])[:7]
            len_description = len(description_str)
            len_amount = len(amount_str)
            space = 30 - len_description - len_amount
            line_2 += description_str + (' ' * space) + amount_str + '\n'
        # line 3
        line_3 = 'Total: ' + str(self.get_balance())
        # result
        result = line_1 + line_2 + line_3
        return str(result)

    def deposit(self, amount, description=''):
        self.ledger.append({'amount': amount, 'description': description})

    def withdraw(self, amount, description=''):
        fund_enough = self.check_funds(amount)
        if not fund_enough:
            return False
        else:
            self.ledger.append(
                {'amount': - amount, 'description': description})
            return True

    def get_balance(self):
        total = 0
        for operation in self.ledger:
            # print(operation)
            total += operation['amount']
        return total

    def transfer(self, amount, category):
        fund_enough = self.check_funds(amount)
        if not fund_enough:
            return False
        else:
            self.withdraw(amount, 'Transfer to ' + str(category.name))
            category.deposit(amount, 'Transfer from ' + str(self.name))
            return True

    def check_funds(self, amount):
        total = self.get_balance()
        if total - amount < 0:
            return False
        else:
            return True


def create_spend_chart(categories):
    line_4 = ''
    list_name = []
    len_category = 0
    for category in categories:
        name = str(category.name)
        list_name.append(name)
        if len(name) > len_category:
            len_category = len(name)
    # calcul percentage
    arr_only_depenses = []
    for category in categories:
        arr_only_depenses.append(get_only_depenses(category))
    # print('arr_only_depenses: ', arr_only_depenses)

    total_only_depenses = 0
    for depense in arr_only_depenses:
        total_only_depenses += abs(depense)

    # print('total_only_depenses: ', total_only_depenses)

    arr_percentage = []
    for category in categories:
        depense_positif = abs(get_only_depenses(category))
        percentage = depense_positif / total_only_depenses * 100
        percentage_round = math.floor(percentage / 10) * 10
        arr_percentage.append(percentage_round)

    print('arr_percentage: ', arr_percentage)

    # line1
    line_1 = 'Percentage spent by category' + '\n'
    # line_2
    line_2 = ''
    i = 110
    max_len = (len(list_name) * 3) + 1
    print('max_len: ', max_len)
    while i > 0:
        i -= 10
        space_before_calcul = abs(int(len(str(i))) - 3)
        space_before = '*' * space_before_calcul
        space_after = '*' * max_len
        line_actuel = space_before + str(i) + '|' + space_after + '\n'
        print('line_actuel: ', line_actuel)

        for j, percentage in enumerate(arr_percentage):
            if i <= percentage:
                arr_line_actuel = line_actuel.split('*')
                print('arr_line_actuel: ', arr_line_actuel)
                calcul = 3 + (j*2)
                print('j: ', j)
                print('calcul: ', calcul, i)
                arr_line_actuel[calcul] = 'o'
                arr_line_actuel.pop(-3)
                # print('arr_line_actuel: ', arr_line_actuel)
                line_actuel = '*'.join(arr_line_actuel)
                # print('line_actuel: ', line_actuel)
        line_actuel = line_actuel.replace('*', ' ')
        line_2 += line_actuel
    # line_3
    len_categories = len(categories)
    # print('len_categories: ', len_categories)
    dash = '-' * ((len_categories * 3) + 1)
    # print('dash: ', dash)
    line_3 = '    ' + dash

    i = 0
    for character in range(len_category):
        line_5 = ''
        for name in list_name:
            space = ' ' * list_name.index(name)
            # print('space: ', space)
            if len(name) > i:
                line_5 += ' ' + name[i] + ' '
            else:
                line_5 += '   '
        line_4 += '\n' + '    ' + line_5 + ' '
        i += 1

    # result
    result = line_1 + line_2 + line_3 + line_4
    return str(result)


def get_only_depenses(category):
    only_depenses = 0
    for operation in category.ledger:
        # print(operation)
        if operation['amount'] < 0:
            only_depenses += operation['amount']
    return only_depenses

Challenge: Scientific Computing with Python Projects - Budget App

Link to the challenge:

This is pretty interesting. I see in the part composing the line there’s splitting, assigning, popping and replacing, while having at the beginning percent indication. If the o character is being written to a specific index, what is being popped off (also why the 3rd character from the end?) and why? That’s a bit complicated and introducing many moving and not moving parts.

Try to simplify it and limit number of things that can affect specific point of line composing. For example, the percent indication and new line character could be added only after the part of the line with bars is completed.

In the exercise given there is a main.py file with an example, it is this one that does not work (i.e. all the 'o’s in the lines are shifted by 1 space except line 0).

Here is the code that is in main.py:

food = budget.Category("Food")

food.deposit(1000, "initial deposit")

food.withdraw(10.15, "groceries")

food.withdraw(15.89, "restaurant and more food for dessert")

# print(food.get_balance())

clothing = budget.Category("Clothing")

food.transfer(50, clothing)

clothing.withdraw(25.55)

clothing.withdraw(100)

auto = budget.Category("Auto")

auto.deposit(1000, "initial deposit")

auto.withdraw(15)

# print(food)

# print(clothing)

print(create_spend_chart([food, clothing, auto]))

Thank you for your reply. You are right pop(-2) is enough on the other hand I cannot understand why in the exercise and in the tests the results are different.
I think I could rewrite this code differently so that there is no longer this problem but I would like to understand this “magic”.

It’s not really magic, it’s a bug lurking somewhere in the code. Or few of them, each one impacting the output in a little way. So it’s not that easy to point to a single place and say this is the reason. The less complexity, the easier is to do that.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.