1

I'm doing a python challenge on 101computin.net and I can't figure out how to make my code shorter. I have tried placing these variables into a list, but then I can't check if the density is in the range within the list because the object can't be interpreted as an integer.

#Eureka! - Archimedes and King Hiero's Crown - www.101computing.net/eureka-and-king-hieros-crown/
mass = float(input("Input the mass of the crown in kg"))
volume = float(input("Input the volume of the crown in cubic meter"))

density = mass / volume

aluminum = range(2400, 2700)
bronze = range(8100, 8300)
silver = range(10400, 10600)
lead = range(11200, 11400)
gold = range(17100, 17500)
platinum = range(21000, 21500)

if density in Aluminum:
    print('Your crown is aluminum!')
elif density in bronze:
    print('B')
elif density in silver:
    print('S')
elif density in lead:
    print('L')
elif density in gold:
    print('G')
elif density in platinum:
    print('P')
else:
    print('Nope!')

Obviously, all the if/elif statements will work, but is there an easier way to loop through the ranges and determine which metal the output is based on the density?

solid.py
  • 2,782
  • 5
  • 23
  • 30
Devin Hight
  • 73
  • 1
  • 7

5 Answers5

3

You can make use of a dictionary:

metals = {
    'aluminum': range(2400, 2700),
    'bronze': range(8100, 8300),
    'silver': range(10400, 10600)
}

for metal, values in metals.items():
    if density in values:
        print('Your crown is ' + metal + '!')
        break
else:
    print('Nope!')
AWhiteFox
  • 96
  • 5
1

You can use dictionary to store this ranges in it. In the example below I construct dictionary where key is a name of your product and the value is a tuple where first element is a actual range and second one is a message which should be printed:

mass = float(input("Input the mass of the crown in kg"))
volume = float(input("Input the volume of the crown in cubic meter"))

density = mass / volume

values = {
    'aluminium': (range(2400, 2700), 'Your crown is aluminum',
    'bronze': (range(8100, 8300), 'B'),
    'silver': (range(10400, 10600), 'S'),
    'lead': (range(11200, 11400), 'L'),
    'gold': (range(17100, 17500), 'G'),
    'platinium': (range(21000, 21500), 'P')
}


c = 0
for k,v in values.items():
    if density in v[0]:
        c += 1
        print(v[1])

if c > 0:
    print('Nope!')
godot
  • 3,422
  • 6
  • 25
  • 42
1

You could use a dictionary to store the metals, also the else statement after the for loop covers the case in which no items are found.

mass = float(input("Input the mass of the crown in kg "))
volume = float(input("Input the volume of the crown in cubic meter "))

metals = {
    'aluminum': range(2400, 2700),
    'bronze': range(8100, 8300),
    'silver': range(10400, 10600),
    'lead': range(11200, 11400),
    'gold': range(17100, 17500),
    'platinum': range(21000, 21500)
}

for metal, density in metals.items():
    if mass / volume in density:
        print(f'Your crown is {metal}!')
        break
else:
    print('Nope!')

Output (with an input of 2400, 1):

Input the mass of the crown in kg 2400
Input the volume of the crown in cubic meter 1
Your crown is aluminum!
solid.py
  • 2,782
  • 5
  • 23
  • 30
  • 1
    One question, why exactly is metal and density separated by a comma in the for loop? ``` for metal, density in metals.items(): ``` – Devin Hight Dec 30 '20 at 02:39
  • 2
    `metals.items()` returns list of tuples of key and value. Then these tuples are unpacked into `metal` and `density`. See https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences and https://stackoverflow.com/questions/10867882/tuple-unpacking-in-for-loops – fdermishin Dec 30 '20 at 06:17
  • 1
    @DevinHight For example, in the first iteration `metal` stores `'aluminum'` and `density` stores the `range` function. – solid.py Dec 30 '20 at 09:35
  • 1
    Also I am using `f-strings` in my answer as seen in https://stackoverflow.com/questions/43123408/f-strings-vs-str-format and https://stackoverflow.com/questions/50455784/python-and-f-strings-explanation For various reasons (performance, readability) they are considered to be better than doing a simple string concatenation. – solid.py Dec 30 '20 at 09:39
  • 1
    I am also calculating the density on the fly (based on the user input) and comparing it with the density ranges, as to save more lines of code, since it's a trivial computation. – solid.py Dec 30 '20 at 09:44
1

It could probably be more optimised, but I would put the metals and their range of densities in a dictionary and iterate them.

metals = {"Aluminum":range(2400, 2700),"Bronze":range(8100, 8300),"Silver":range(10400, 10600),"Lead":range(11200, 11400),"Gold":range(17100, 17500),"Platinum":range(21000, 21500)}

for metal,density in metals.items():
    if input_density in density:
        print(metal[0])
blessthefry
  • 121
  • 7
1

You can use a list approach. I do this very often when i'm working on Unity scripts.

mass = float(input("Input the mass of the crown in kg"))
volume = float(input("Input the volume of the crown in cubic meter"))

density = mass / volume
element_list = [range(2400,2700),range(8100,8300),range(10400,10600),range(11200,11400),range(17100,17500),range(21000,21500)]
element_list2 = ["aluminum","bronze","silver","lead","gold","platinum"]
for i in range(len(element_list)):
    if density in element_list[i]:
        print(f"Your crown made of: {element_list2[i]}")