Hi,
I run the tests on my Budget App implementation and the create_spend_chart function is not accepted. I am not receiving any error message on the Console, therefore I am not sure what error to look for. I have read couple of posts and corrected the space errors, but it is still not accepted.
Anyone could provide me with guidance and with an example with solution that I could verify?
def create_spend_chart(categories) :
#Deposited and withdrawn amounts for each category
percent = len(categories)*[0]
ind = 0
for obj in categories :
amount_plus = 0
amount_minus = 0
for item in obj.ledger :
if item["amount"] > 0 :
amount_plus += item["amount"]
else :
amount_minus += item["amount"]
#Calculate percentage spent
if amount_plus != 0 :
#Round down the percentage of amount spent
percent[ind] = int(((-amount_minus * 100/ amount_plus) // 10) * 10)
else :
percent[ind] = 0
ind += 1
print('Percentage:', percent)
#Generate string bar chart
str_barchart = '\nPercentage spent by category'
for p in range(100, -10, -10) :
line = '{:3d}{:1s}'.format(p, '|')
for pp in percent :
if p <= pp :
line = line + ' ' + 'o'
else :
line = line + 2*' '
str_barchart = str_barchart + '\n' + line + 2*' '
#Add the underline
str_barchart = str_barchart + '\n' + 4*' '
for iter_dash in range(len(categories)) :
str_barchart = str_barchart + 2*'-'
str_barchart = str_barchart + 2*'-'
#Add the categories, ie obj names
max_len = 0
for obj in categories :
if max_len < len(obj.name) :
max_len = len(obj.name)
for iter_maxlen in range(max_len) :
str_barchart = str_barchart + '\n' + 4*' '
for obj in categories :
if len(obj.name) < (iter_maxlen + 1) :
str_barchart = str_barchart + 2*' '
continue
str_barchart = str_barchart + ' ' + obj.name[iter_maxlen]
str_barchart = str_barchart + 2*' '
return str_barchart
Challenge Information:
Scientific Computing with Python Projects - Budget App
Can you post the full code? thanks
Thank you in advance.
class Category :
amount = 0
name = ''
ledger = tuple()
def __init__(self, name) :
self.name = name
def deposit(self, am, description = '') :
self.amount += am
self.ledger = self.ledger + ({"amount" : am, "description" : description}, )
def withdraw(self, am, description = '') :
if not self.check_funds(am) :
return False
else :
self.amount -= am
self.ledger = self.ledger + ({"amount" : -am, "description" : description}, )
return True
def get_balance(self) :
return self.amount
def transfer(self, am, categ) :
if not self.check_funds(am) :
return False
else :
self.withdraw(am, str('Transfer to ' + categ.name))
categ.deposit(am, str('Transfer from ' + self.name))
return True
def check_funds(self, am) :
if self.amount < am :
return False
else :
return True
def __str__(self) :
budget_current = 0
str_display = ''
title_line = f"{self.name:*^30}"
for item in self.ledger :
desc = item["description"][:23]
budget_current += item["amount"]
myamount = str(item["amount"])
if len(myamount) > 7 :
myamount = myamount[0:7]
str_display = str_display + '\n' + '{:23s}{:7s}'.format(desc, myamount)
else :
str_display = str_display + '\n' + '{:23s}{:7.2f}'.format(desc, float(myamount))
str_display = title_line + str_display + '\n' + str('Total: %.2f' %budget_current)
return str_display
def create_spend_chart(categories) :
#Deposited and withdrawn amounts for each category
percent = len(categories)*[0]
ind = 0
for obj in categories :
amount_plus = 0
amount_minus = 0
for item in obj.ledger :
if item["amount"] > 0 :
amount_plus += item["amount"]
else :
amount_minus += item["amount"]
#Calculate percentage spent
if amount_plus != 0 :
#Round down the percentage of amount spent
percent[ind] = int(((-amount_minus * 100/ amount_plus) // 10) * 10)
else :
percent[ind] = 0
ind += 1
print('Percentage:', percent)
#Generate string bar chart
str_barchart = '\nPercentage spent by category'
for p in range(100, -10, -10) :
line = '{:3d}{:1s}'.format(p, '|')
for pp in percent :
if p <= pp :
line = line + ' ' + 'o'
else :
line = line + 2*' '
str_barchart = str_barchart + '\n' + line + 2*' '
#Add the underline
str_barchart = str_barchart + '\n' + 4*' '
for iter_dash in range(len(categories)) :
str_barchart = str_barchart + 2*'-'
str_barchart = str_barchart + 2*'-'
#Add the categories, ie obj names
max_len = 0
for obj in categories :
if max_len < len(obj.name) :
max_len = len(obj.name)
for iter_maxlen in range(max_len) :
str_barchart = str_barchart + '\n' + 4*' '
for obj in categories :
if len(obj.name) < (iter_maxlen + 1) :
str_barchart = str_barchart + 2*' '
continue
str_barchart = str_barchart + ' ' + obj.name[iter_maxlen]
str_barchart = str_barchart + 2*' '
return str_barchart
Testing your code with the given example:
food = Category("Food")
food.deposit(1000, "deposit")
food.withdraw(10.15, "groceries")
food.withdraw(15.89, "restaurant and more food for dessert")
clothing = Category("Clothing")
food.transfer(50, clothing)
print(food)
print(create_spend_chart([food, clothing]))
That they both have
output:
>>> Percentage: [0, 0]
>>>
Percentage spent by category
100|
90|
80|
70|
60|
50|
40|
30|
20|
10|
0| o o
------
F C
o l
o o
d t
h
i
n
g
Another test:
food = Category("Food")
food.deposit(100, "deposit")
food.withdraw(10, "groceries")
food.withdraw(10, "restaurant and more food for dessert")
clothing = Category("Clothing")
food.transfer(50, clothing)
print(food)
print(create_spend_chart([food, clothing]))
>>> Percentage: [70, 0]
>>>
Percentage spent by category
100|
90|
80|
70| o
60| o
50| o
40| o
30| o
20| o
10| o
0| o o
------
F C
o l
o o
d t
h
i
n
g
So, here food withdraw is 70$ of what’s been deposited. However:
The percentage spent should be calculated only with withdrawals and not with deposits.
You need to tally all the withdrawls and calculate the percent from that number, not from the total deposit.
Thanks very much for pointing that out. I have updated the code and it appears that the percentages are now correct, but the freecodecamp.org submission platform still does not accept my create_spend_chart function.
Here is my updated code:
class Category :
amount = 0
name = ''
ledger = tuple()
def __init__(self, name) :
self.name = name
def deposit(self, am, description = '') :
self.amount += am
self.ledger = self.ledger + ({"amount" : am, "description" : description}, )
def withdraw(self, am, description = '') :
if not self.check_funds(am) :
return False
else :
self.amount -= am
self.ledger = self.ledger + ({"amount" : -am, "description" : description}, )
return True
def get_balance(self) :
return self.amount
def transfer(self, am, categ) :
if not self.check_funds(am) :
return False
else :
self.withdraw(am, str('Transfer to ' + categ.name))
categ.deposit(am, str('Transfer from ' + self.name))
return True
def check_funds(self, am) :
if self.amount < am :
return False
else :
return True
def __str__(self) :
budget_current = 0
str_display = ''
title_line = f"{self.name:*^30}"
for item in self.ledger :
desc = item["description"][:23]
budget_current += item["amount"]
myamount = str(item["amount"])
if len(myamount) > 7 :
myamount = myamount[0:7]
str_display = str_display + '\n' + '{:23s}{:7s}'.format(desc, myamount)
else :
str_display = str_display + '\n' + '{:23s}{:7.2f}'.format(desc, float(myamount))
str_display = title_line + str_display + '\n' + str('Total: %.2f' %budget_current)
return str_display
def create_spend_chart(categories) :
#Deposited and withdrawn amounts for each category
percent = len(categories)*[0]
ind = 0
amount_total = 0
amount_minus = len(categories)*[0]
for obj in categories :
for item in obj.ledger :
#Calculate the total and category withdrawals
if item["amount"] < 0 :
amount_total += item["amount"]
amount_minus[ind] += item["amount"]
ind += 1
amount_total = -amount_total
#Calculate percentage spent
for ind in range(len(categories)) :
if -amount_total != 0 :
#Round down the percentage of amount spent
percent[ind] = int(((-amount_minus[ind] * 100/ amount_total) // 10) * 10)
else :
percent[ind] = 0
ind += 1
#Generate string bar chart
str_barchart = '\nPercentage spent by category'
for p in range(100, -10, -10) :
line = '{:3d}{:1s}'.format(p, '|')
for pp in percent :
if p <= pp :
line = line + ' ' + 'o'
else :
line = line + 2*' '
str_barchart = str_barchart + '\n' + line + 2*' '
#Add the underline
str_barchart = str_barchart + '\n' + 4*' '
for iter_dash in range(len(categories)) :
str_barchart = str_barchart + 2*'-'
str_barchart = str_barchart + 2*'-'
#Add the categories, ie obj names
max_len = 0
for obj in categories :
if max_len < len(obj.name) :
max_len = len(obj.name)
for iter_maxlen in range(max_len) :
str_barchart = str_barchart + '\n' + 4*' '
for obj in categories :
if len(obj.name) < (iter_maxlen + 1) :
str_barchart = str_barchart + 2*' '
continue
str_barchart = str_barchart + ' ' + obj.name[iter_maxlen]
str_barchart = str_barchart + 2*' '
return str_barchart
Have a close look at the spacing in the example chart:
0| o o o
and yours:
0| o o o
Spacing must be exactly the same.
Also watch out, your chart starts with a \n
character which won’t pass the test
Thanks very much. It passed the tests on the freecodecamp.org submission platform.
1 Like
I used the code here as a guide when creating the bar chart as I had the same problem with the last test failing. However, the code is still not accepted. I am desperate here. Can you help me?
import math
class Category:
instances = []
def __init__(self, category_name):
self.category_name = category_name
self.ledger = []
Category.instances.append(self)
def deposit(self, amount, description=''):
self.ledger.append({'amount': amount, 'description': description})
def withdraw(self, amount, description=''):
if self.check_funds(amount):
self.ledger.append({'amount': -amount, 'description': description})
return True
else:
return False
def get_balance(self):
return sum(item['amount'] for item in self.ledger)
def transfer(self, amount, destination_category):
if self.check_funds(amount):
self.withdraw(amount, f'Transfer to {destination_category.category_name}')
destination_category.deposit(amount, f'Transfer from {self.category_name}')
return True
else:
return False
def check_funds(self, amount):
return self.get_balance() >= amount
def __str__(self):
title = f'*{self.category_name.center(28, "*")}*'
lines = [title]
for item in self.ledger:
description = item['description'][:23]
amount = '{:.2f}'.format(item['amount']).rjust(7)
lines.append(f'{description.ljust(23)}{amount}')
lines.append(f'Total: {self.get_balance():.2f}')
return '\n'.join(lines)
def create_spend_chart(categories):
def percentage_per_category(categories):
category_withdraw = {}
total_withdraw = 0.00
for category in categories:
withdraw = -round(sum(item['amount'] for item in category.ledger if item['amount'] < 0), 2)
category_withdraw[category.category_name] = withdraw
total_withdraw += withdraw
percentages = {}
for category, withdraw in category_withdraw.items():
percentages[category] = (withdraw / total_withdraw) * 100
return percentages
percentages = percentage_per_category(categories)
chart = "Percentage spent by category"
for i in range(100, -1, -10):
line = '{:3d}{:1s}'.format(i, '|')
for category, percent in percentages.items():
if percent >= i:
line += " " + "o" + " "
else:
line += 3 * " "
chart += "\n" + line + 2 * " "
chart += "\n" + 4 * " "
for iter_dash in range(len(categories)):
chart += 3 * "-"
chart += "-"
max_len = max(len(obj.category_name) for obj in categories)
for iter_maxlen in range(max_len):
chart += "\n" + 4 * " "
for obj in categories:
if len(obj.category_name) < (iter_maxlen + 1):
chart += 2 * " " + " "
continue
chart += " " + obj.category_name[iter_maxlen] + " "
chart += 2 * " "
return chart
food = Category("Food")
food.deposit(1000, "deposit")
food.withdraw(10.15, "groceries")
food.withdraw(15.89, "restaurant and more food for dessert")
clothing = Category("Clothing")
food.transfer(50, clothing)
spend_chart = create_spend_chart(Category.instances)
print(spend_chart)```
Please open a new topic for your question, thanks!