Python Forum
Subtracting values between two dictionaries/ floating point numbers
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Subtracting values between two dictionaries/ floating point numbers
#1
Hello everybody hope your all doing great :D,

I am new to learning python and challenged myself to make a small program for a game i like to play called Star Citizen, the purpous of the program is to take two inputs, player location and player destination. It will then take those two sets of data and calculate from a dictionary what the user can buy at their current location and sell at their destination and what would be the most profitable.

I am running into an issue when it comes calculating this. I believe im probably going about this all wrong so please don't worry about telling me to start from scratch with different ideas.

Here is the code so far:

#### taking user information
user_purchase_location = input("Were are you planning to buy your goods?").lower()
user_sale_destination = input("Where are you planning to sell your goods?").lower()

#### dicts of items available to buy and sell at locations along with UEC price.
buying_olisar = {'Medical Supply': 17.01,}
selling_olisar = {'Agricium': 25.60, 'Aluminum': 1.25, 'Beryl': 4.26, 'Chlorine': 1.57, 'Corundum': 2.53, 'Diamond': 6.90, 'Distilled Spirits': 4.95, 'Fluorine': 2.80, 'Gold': 6.07, 'Hydrogen': 1.02, 'Iodine': 0.41, 'Laranite': 28.91, 'Processed Food': 1.39, 'Quartz': 1.44, 'Scrap': 1.67, 'Stims': 3.40, 'Titanium': 8.27, 'Tungsten': 3.90,}
buying_levski = {'Agricultural Supply': 1.11, 'Aluminum': 1.20, 'Hydrogen': 0.98, 'Iodine': 0.38, 'Quartz': 1.37,}
selling_levski = {'Agricium': 25.60, 'Altruciatoxine': 11.63, 'Beryl': 4.25, 'Chlorine': 1.56, 'Corundum': 2.53, 'Diamond': 6.07, 'Distilled Spirits': 4.95, 'Fluorine': 2.80, 'Gold': 6.07, 'Laranite': 28.25, 'Medical Supply': 18.00, 'Processed Food': 1.38, 'Scrap': 1.68, 'Stims': 3.40, 'Titanium': 8.27, 'Tungsten': 3.90, 'Widdow': 24.00,}

#### Sorting the dict into ascending value instead of alphabetical
sort_buying_olisar = sorted(buying_olisar, key=lambda tup: tup[1])
sort_selling_olisar = sorted(selling_olisar, key=lambda tup:(tup[1], tup[0]))
sort_buying_levski = sorted(buying_levski, key=lambda tup: tup[1])
sort_selling_levski = sorted(selling_levski, key=lambda tup:(tup[1], tup[0]))


#### picking two dicts (buy/sell) and filtering them to print only common elements.
def common(curr, other):
    return set(curr.keys()).intersection(set(other.keys()))
tradable_items = common(buying_levski, selling_olisar)


#### calculating the prices between possible sales.
prices = {k: selling_olisar[k] - buying_levski[k] for k in tradable_items}


print(prices)
When i run this the figures are coming out as floating point numbers for example:

Quote:Were are you planning to buy your goods?levski
Where are you planning to sell your goods?olisar
{'Quartz': 0.06999999999999984, 'Hydrogen': 0.040000000000000036, 'Iodine': 0.02999999999999997, 'Aluminum': 0.050000000000000044}

What i a can't figure out is how to #1 have these floating point numbers be not so large and #2 how to then print out the item in the dictionary that holds the largest number.

Any guidance would be massively appreciated.

Thanks any questions please ask and sorry if the formatting isn't perfect i am a really new to this :).
Reply
#2
(Mar-03-2019, 06:50 PM)FloppyPoppy Wrote: how to #1 have these floating point numbers be not so large
Use string formatting,f-string Python 3.6-->.
>>> d = {'Quartz': 0.06999999999999984, 'Hydrogen': 0.040000000000000036, 'Iodine': 0.02999999999999997, 'Aluminum': 0.050000000000000044}
>>> print(f'Value of Quartz is {d["Quartz"]:.2f}')
Value of Quartz is 0.07
(Mar-03-2019, 06:50 PM)FloppyPoppy Wrote: #2 how to then print out the item in the dictionary that holds the largest number
>>> d = {'Quartz': 0.06999999999999984, 'Hydrogen': 0.040000000000000036, 'Iodine': 0.02999999999999997, 'Aluminum': 0.050000000000000044}
>>> max(d, key=d.get)
'Quartz'
Reply
#3
Hello snippsat,

Thank you very much for your help this has opened my eyes to a couple of new ways to do things in python. Here is the bottom of the code that i have got working with some manipulation and further research.

import operator
most_profitable_resourse = max(prices.items(), key=operator.itemgetter(1))[0]

profit_ammount = prices
profit_sorted = (f'{profit_ammount["Quartz"]:.2f}')


print("The most profitable item to buy at " + user_purchase_location + " is " + most_profitable_resourse + " and will make a net profit of " + profit_sorted + " per unit when sold at " + user_sale_destination + ".")

Were are you planning to buy your goods?Levski
Where are you planning to sell your goods?Olisar
The most profitable item to buy at levski is Quartz and will make a net profit of 0.07 per unit when sold at olisar.
Im going to spend some more time working on this code and adding in more locations once i am 100% happy the calculations are all complete i will post the code for anyone who wants to have a play :).
Reply
#4
You can and should use f-string everywhere,eg your line 8.
Also think of line length,line 8 is now 215 characters in length.
PEP-8 say 79 characters line length,but i would say that 90'ish is okay.
Example:
user_purchase_location = 'Mall'
most_profitable_resourse = 'Diamond' 
profit_sorted = '99'
user_sale_destination = 'Gold Shop'

print(
f"The most profitable item to buy at {user_purchase_location} is {most_profitable_resourse}\n\
and will make a net profit of {profit_sorted} per unit when sold at {user_sale_destination}"
)
Output:
The most profitable item to buy at Mall is Diamond and will make a net profit of 99 per unit when sold at Gold Shop
Reply
#5
(Mar-03-2019, 10:52 PM)snippsat Wrote: You can and should use f-string everywhere,eg your line 8.
Also think of line length,line 8 is now 215 characters in length.
PEP-8 say 79 characters line length,but i would say that 90'ish is okay.
Example:
user_purchase_location = 'Mall'
most_profitable_resourse = 'Diamond' 
profit_sorted = '99'
user_sale_destination = 'Gold Shop'

print(
f"The most profitable item to buy at {user_purchase_location} is {most_profitable_resourse}\n\
and will make a net profit of {profit_sorted} per unit when sold at {user_sale_destination}"
)
Output:
The most profitable item to buy at Mall is Diamond and will make a net profit of 99 per unit when sold at Gold Shop

Thanks for that information i will be sure to try and incorporate F strings going forward. I have changed the program to reflect your advice.

Here is how the code is looking now

#### taking user information
user_purchase_location = input(f"Where are you planning to buy your goods?").lower()
user_sale_destination = input(f"Where are you planning to sell your goods?").lower()

#### dicts of items available to buy and sell at locations along with UEC price.
buying_olisar = {'Medical Supply': 17.01,}
selling_olisar = {'Agricium': 25.60, 'Aluminum': 1.25, 'Beryl': 4.26, 'Chlorine': 1.57, 'Corundum': 2.53, 'Diamond': 6.90, 'Distilled Spirits': 4.95, 'Fluorine': 2.80, 'Gold': 6.07, 'Hydrogen': 1.02, 'Iodine': 0.41, 'Laranite': 28.91, 'Processed Food': 1.39, 'Quartz': 1.44, 'Scrap': 1.67, 'Stims': 3.40, 'Titanium': 8.27, 'Tungsten': 3.90,}
buying_levski = {'Agricultural Supply': 1.11, 'Aluminum': 1.20, 'Hydrogen': 0.98, 'Iodine': 0.38, 'Quartz': 1.37,}
selling_levski = {'Agricium': 25.60, 'Altruciatoxine': 11.63, 'Beryl': 4.25, 'Chlorine': 1.56, 'Corundum': 2.53, 'Diamond': 6.07, 'Distilled Spirits': 4.95, 'Fluorine': 2.80, 'Gold': 6.07, 'Laranite': 28.25, 'Medical Supply': 18.00, 'Processed Food': 1.38, 'Scrap': 1.68, 'Stims': 3.40, 'Titanium': 8.27, 'Tungsten': 3.90, 'Widdow': 24.00,}
buying_grim_hex = {'Chlorine': 1.44, 'Flurine': 2.63, 'Hydrogen': 0.97, 'Iodine': 0.34}
selling_grim_hex = {'Altruciatoxine': 11.80, 'distilled spirits': 4.95, 'medical suppies': 18.05, 'processed food': 1.36, 'stims': 3.40, 'Widdow': 24.0}


#### Sorting the dict into ascending value instead of alphabetical
sort_buying_olisar = sorted(buying_olisar, key=lambda tup: tup[1])
sort_selling_olisar = sorted(selling_olisar, key=lambda tup:(tup[1], tup[0]))
sort_buying_levski = sorted(buying_levski, key=lambda tup: tup[1])
sort_selling_levski = sorted(selling_levski, key=lambda tup:(tup[1], tup[0]))
sort_buying_grim_hex = sorted(buying_arc_corp_mining_area_157, key=lambda tup: tup[1])
sort_selling_grim_hex = sorted(selling_arc_corp_mining_area_157, key=lambda tup:(tup[1], tup[0]))

#### picking two dicts (buy/sell) and filtering them to print only common elements.
def common(curr, other):
    return set(curr.keys()).intersection(set(other.keys()))
tradable_items = common(buying_levski, selling_olisar)

#### calculating the prices between possible sales.
prices = {k: selling_olisar[k] - buying_levski[k] for k in tradable_items}

#### finding the most profitable material
import operator
most_profitable_resourse = max(prices.items(), key=operator.itemgetter(1))[0]

#### sorting and printing the most profitable purchase.
profit_ammount = prices
profit_sorted = (f'{profit_ammount[most_profitable_resourse]:.2f}')
print(
f"The most profitable item to buy at {user_purchase_location.title()} is {most_profitable_resourse.title()}\n\
and will make a net profit of {profit_sorted} per unit when sold at {user_sale_destination.title()}"
What i am trying to do now is alter these two lines to reflect any input from the user opposed to just focusing on the two. This is why i added in the third area "grim_hex"

tradable_items = common(buying_levski, selling_olisar)
prices = {k: selling_olisar[k] - buying_levski[k] for k in tradable_items}
i have tried to create a second variable as follows:
user_purchase_location_1 = 'buying_'+user_purchase_location+''
user_sale_destination_1 = 'selling_'+user_sale_destination+''
these produce the correct information but wont work when added into the code as below as they are interpreted as strings:

def common(curr, other):
    return set(curr.keys()).intersection(set(other.keys()))
tradable_items = common(user_purchase_location_1, user_sale_destination_1)

prices = {k: user_sale_destination_1[k] - user_purchase_location_1[k] for k in tradable_items}
When im running it like that i get this error:

Traceback (most recent call last):
File "/home/floppypoppy/PycharmProjects/Star Citizen Trading Program/Star Citizen trading NEW.py", line 33, in <module>
tradable_items = common(user_purchase_location_1, user_sale_destination_1)
File "/home/floppypoppy/PycharmProjects/Star Citizen Trading Program/Star Citizen trading NEW.py", line 32, in common
return set(curr.keys()).intersection(set(other.keys()))
AttributeError: 'str' object has no attribute 'keys'

Sorry for the wall of text just trying to offer up as much information on what i am doing as possible. Is there anything you can suggest i research to to make the above work?

Again thanks for any help and kindest regards,

Harry (FP)
Reply
#6
Dictionary do not give you a free pass on line length Wink
Here is formatted code,i use VS Code and black set to format code.
So i not done all this manually.
import operator

#### taking user information
user_purchase_location = 'Mall'
user_sale_destination = 'Gold Shop'

#### dicts of items available to buy and sell at locations along with UEC price.
buying_olisar = {"Medical Supply": 17.01}

selling_olisar = {
    "Agricium": 25.60,
    "Aluminum": 1.25,
    "Beryl": 4.26,
    "Chlorine": 1.57,
    "Corundum": 2.53,
    "Diamond": 6.90,
    "Distilled Spirits": 4.95,
    "Fluorine": 2.80,
    "Gold": 6.07,
    "Hydrogen": 1.02,
    "Iodine": 0.41,
    "Laranite": 28.91,
    "Processed Food": 1.39,
    "Quartz": 1.44,
    "Scrap": 1.67,
    "Stims": 3.40,
    "Titanium": 8.27,
    "Tungsten": 3.90,
}

buying_levski = {
    "Agricultural Supply": 1.11,
    "Aluminum": 1.20,
    "Hydrogen": 0.98,
    "Iodine": 0.38,
    "Quartz": 1.37,
}
selling_levski = {
    "Agricium": 25.60,
    "Altruciatoxine": 11.63,
    "Beryl": 4.25,
    "Chlorine": 1.56,
    "Corundum": 2.53,
    "Diamond": 6.07,
    "Distilled Spirits": 4.95,
    "Fluorine": 2.80,
    "Gold": 6.07,
    "Laranite": 28.25,
    "Medical Supply": 18.00,
    "Processed Food": 1.38,
    "Scrap": 1.68,
    "Stims": 3.40,
    "Titanium": 8.27,
    "Tungsten": 3.90,
    "Widdow": 24.00,
}
buying_grim_hex = {
    "Chlorine": 1.44,
    "Flurine": 2.63,
    "Hydrogen": 0.97,
    "Iodine": 0.34
    }

selling_grim_hex = {
    "Altruciatoxine": 11.80,
    "distilled spirits": 4.95,
    "medical suppies": 18.05,
    "processed food": 1.36,
    "stims": 3.40,
    "Widdow": 24.0,
}

#### Sorting the dict into ascending value instead of alphabetical
sort_buying_olisar = sorted(buying_olisar, key=lambda tup: tup[1])
sort_selling_olisar = sorted(selling_olisar, key=lambda tup: (tup[1], tup[0]))
sort_buying_levski = sorted(buying_levski, key=lambda tup: tup[1])
sort_selling_levski = sorted(selling_levski, key=lambda tup: (tup[1], tup[0]))
#sort_buying_grim_hex = sorted(buying_arc_corp_mining_area_157, key=lambda tup: tup[1])
#sort_selling_grim_hex = sorted(selling_arc_corp_mining_area_157, key=lambda tup: (tup[1], tup[0]))

#### picking two dicts (buy/sell) and filtering them to print only common elements.
def common(curr, other):
    return set(curr.keys()).intersection(set(other.keys()))

tradable_items = common(buying_levski, selling_olisar)

#### calculating the prices between possible sales.
prices = {k: selling_olisar[k] - buying_levski[k] for k in tradable_items}

most_profitable_resourse = max(prices.items(), key=operator.itemgetter(1))[0]

#### sorting and printing the most profitable purchase.
profit_ammount = prices
profit_sorted = f"{profit_ammount[most_profitable_resourse]:.2f}"
print(
    f"The most profitable item to buy at {user_purchase_location.title()} is {most_profitable_resourse.title()}\n\
and will make a net profit of {profit_sorted} per unit when sold at {user_sale_destination.title()}"
)
Now it work for me,i have comment out line 78,79 as eg buying_arc_corp_mining_area_157 is not set.

Next time do not post all together working and not working code it can be confusing,
make a working example with eg Dictionary and code that gives problem with Traceback.

Here my test run:
E:\div_code\xy
λ ptpython -i test1.py
# The out from running code
The most profitable item to buy at Mall is Quartz
and will make a net profit of 0.07 per unit when sold at Gold Shop

# Interactive session to test some values 
>>> tradable_items
{'Iodine', 'Aluminum', 'Hydrogen', 'Quartz'}

>>> most_profitable_resourse
'Quartz'

>>> profit_sorted
'0.07'

>>> sort_selling_olisar
['Laranite', 'Scrap', 'Beryl', 'Agricium', 'Chlorine', 'Diamond', 'Distilled Spirits', 'Titanium', 'Aluminum', 'Fluorine', 'Corundum', 'Gold', 'Iodine', 'Processed Food', 'Stims', 'Quartz', 'Tungsten', 'Hydrogen']

>>> sort_buying_levski
['Agricultural Supply', 'Aluminum', 'Iodine', 'Quartz', 'Hydrogen']

>>> prices
{'Iodine': 0.02999999999999997, 'Aluminum': 0.050000000000000044, 'Hydrogen': 0.040000000000000036, 'Quartz': 0.06999999999999984}  
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Help with subtracting values using SQLite & Python Extra 10 3,286 May-10-2022, 08:36 AM
Last Post: ibreeden
  Subtracting datetimes [index] Mark17 2 2,408 Aug-21-2021, 12:11 AM
Last Post: Larz60+
  5 variants to invert dictionaries with non-unique values Drakax1 2 2,560 Aug-31-2020, 11:40 AM
Last Post: snippsat
  Accessing values in list of dictionaries pythonnewbie138 2 2,083 Aug-02-2020, 05:02 PM
Last Post: pythonnewbie138
  Indexing problem while iterating list and subtracting lbtdne 2 2,087 May-14-2020, 10:19 PM
Last Post: deanhystad
  floating point not increasing properly rakeshpe43 4 2,346 Apr-30-2020, 05:37 AM
Last Post: rakeshpe43
  connecting the first point to the last point Matplotlib omar_mohsen 0 4,524 Jan-15-2020, 01:23 PM
Last Post: omar_mohsen
  Complex floating issue arshad 2 11,768 Nov-05-2019, 03:26 PM
Last Post: arshad
  floating point arithmetic exDeveloper 2 2,070 Sep-25-2019, 04:33 PM
Last Post: DeaD_EyE
  finding the closest floating point number in a list Skaperen 17 8,089 Sep-19-2019, 10:39 PM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020