Is there a neater way to show the cheapest option in Sal's Shipping exercise?

At the end of the code I’ve quoted, I tried to also show the user which option would be the cheapest. However, this ended up being very messy. Also, I’m wondering what would happen if two options end up having the same price (or if all three options have the same price)? Haven’t found a value for weight which lets that happen yet, but in theory what would happen? Also how would I correct any problems which arise from that happening?

All best, and thanks for any replies

Exercise: https://www.codecademy.com/courses/learn-python-3/projects/python-sals-shipping

Code:

weight = 17

# Ground Shipping

if weight <= 2.0:

  cost_ground = weight * 1.50 + 20

  print("The cost of Ground Shipping is:", cost_ground)

elif weight <= 6.0:

  cost_ground = weight * 3.0 + 20

  print("The cost of Ground Shipping is:", cost_ground)

elif weight <= 10.0:

  cost_ground = weight * 4.0 + 20

  print("The cost of Ground Shipping is:", cost_ground)

else:

  cost_ground = weight * 4.75 + 20

  print("The cost of Ground Shipping is:", cost_ground)

# Ground Premium Shipping

cost_ground_premium = 125

print("The cost of Ground Premium Shipping is:", cost_ground_premium)

# Drone Shipping

if weight <= 2.0:

  cost_drone = weight * 4.50

  print("The cost of Drone Shipping is:", cost_drone)

elif weight <= 6.0:

  cost_drone = weight * 9.0

  print("The cost of Drone Shipping is:", cost_drone)

elif weight <=10:

  cost_drone = weight * 12.0

  print("The cost of Drone Shipping is:", cost_drone)

else:

  cost_drone = weight * 14.25

  print("The cost of Drone Shipping is:", cost_drone)

# Cheapest choice

if cost_drone < cost_ground_premium and cost_drone < cost_ground:

  print("Drone Shipping is the cheapest at:", cost_drone)

elif cost_ground_premium < cost_drone and cost_ground_premium < cost_ground:

  print("Ground Premium Shipping is the cheapest at:", cost_ground_premium)

elif cost_ground < cost_drone and cost_ground < cost_ground_premium:

  print("Ground Shipping is the cheapest at:", cost_ground)

I think it’s setup as it is so that you don’t need to know more data storage methods to learn about if/elif/else. You could use a 2d list or an ordered dictionary to store the results and then sort them after.

shipping_costs = []

if weight <= 2.0:

  shipping_costs.append([cost_ground, weight * 1.50 + 20])

Once shipping_costs has all the values, you could sort it using the cost as the key and pull the first or last depending on how you sort.

1 Like

Haven’t come across that stuff yet. Thanks for the reply, looks interesting!

Played around with what I’ve been taught so far, and incidentally this works lol - but it’s very messy:

a = 2

b = 2

c = 4

if a < b and a < c:

  print("A is the cheapest")

elif b < a and b < c:

  print("B is the cheapest")

elif c < a and c < b:

  print("C is the cheapest")

elif a == b and a < c:

  print("A and B are the cheapest")

elif a == c and a < b:

  print("A and C are the cheapest")

elif b == c and b < a:

  print("B and C are the cheapest")

else:

  print("They are all the same price!")
1 Like

Here’s a bit of fun for you, the first line makes a function out of the shipping calculator and I had it return a list of weight and the 3 shipping costs. Then I called it for a large range to look for matching shipping costs. This checks increments of 0.00001 from 0 to 14.99999

def shipping_function(weight):    
    
    if weight <= 2.0:

      cost_ground = weight * 1.50 + 20

    elif weight <= 6.0:

      cost_ground = weight * 3.0 + 20

    elif weight <= 10.0:

      cost_ground = weight * 4.0 + 20

    else:

      cost_ground = weight * 4.75 + 20

    # Ground Premium Shipping

    cost_ground_premium = 125

    # Drone Shipping

    if weight <= 2.0:

      cost_drone = weight * 4.50

    elif weight <= 6.0:

      cost_drone = weight * 9.0

    elif weight <=10:

      cost_drone = weight * 12.0

    else:

      cost_drone = weight * 14.25
    
    return [weight, cost_ground, cost_ground_premium, cost_drone]

matching_shipping_costs = []

for i in range(1500000):

    list_costs = shipping_function(i/100000)

    #print(list_costs)

    if list_costs[1] == list_costs[2] or list_costs[1] == list_costs[3] or list_costs[3] == list_costs[2]:

        matching_shipping_costs.append(list_costs)

print(f"Weights where shipping costs match: \n{matching_shipping_costs}")
1 Like

That’s beautiful. I can sort of read the code and understand it (at least I think I can).

Also I printed matching_shipping_costs, and it doesn’t seem there are any values where they equal one another!?

Edit: Also added a 0 to 1500000 so it went up to just before 150, and still nothing. I guess such a weight value doesn’t exist (or maybe it does if we go to like 0.0000000000000000000000000000000001 etc. etc., who knows).

1 Like

If you round the the cost calculations, there are some results:
This one rounds to the penny.

def shipping_function(weight):    
    
    if weight <= 2.0:

      cost_ground = weight * 1.50 + 20

    elif weight <= 6.0:

      cost_ground = weight * 3.0 + 20

    elif weight <= 10.0:

      cost_ground = weight * 4.0 + 20

    else:

      cost_ground = weight * 4.75 + 20

    # Ground Premium Shipping

    cost_ground_premium = 125

    # Drone Shipping

    if weight <= 2.0:

      cost_drone = weight * 4.50

    elif weight <= 6.0:

      cost_drone = weight * 9.0

    elif weight <=10:

      cost_drone = weight * 12.0

    else:

      cost_drone = weight * 14.25
    
    return [weight, round(cost_ground, 2), cost_ground_premium, round(cost_drone, 2)]

matching_shipping_costs = []

for i in range(15000):

    list_costs = shipping_function(i/1000)

    #print(list_costs)

    if list_costs[1] == list_costs[2] or list_costs[1] == list_costs[3] or list_costs[3] == list_costs[2]:

        matching_shipping_costs.append(list_costs)

print(f"Weights where shipping costs match: \n{matching_shipping_costs}")
1 Like

Oh awesome stuff. Yeah there’s loads of them when rounding to the penny! There’s a bunch with 3 (like 3.333) where cost_ground and cost_drone are equal, and then a bunch at 22 (like 22.105) where cost_ground and cost_premium are equal.

Forgot about round! (: Cool that all this was done in not that many lines of code at all.

This method defaults to ground shipping.

cheapest_method
def cheapest_method(weight):
  premium = 125
  g = ground_shipping(weight)
  d = drone_shipping(weight)
  if premium < g and premium < d:
    a, b = "Premium Ground", premium
  elif d < g:
    a, b = "Drone", d
  else:
    a, b = "Ground", g
  return f"The cheapest shipping method for a {weight}\
 pound package is {a}, at a cost of ${b:.2f}."

print (cheapest_method(41.5))
The cheapest shipping method for a 41.5 pound package is Premium Ground, at a cost of $125.00.
2 Likes

That’s cool, but when rounding to the penny (as someone can’t pay 124.9999998 for example), it doesn’t share when two options are equally cheap (just shows whichever is slightly smaller like how 124.99997 is smaller than 124.99998 etc.)

For example, if weight were 3.333 in this:

premium = 125

def ground_shipping(weight):

  

  if weight <= 2.0:

    cost_ground = weight * 1.50 + 20

  elif weight <= 6.0:

    cost_ground = weight * 3.0 + 20

  

  elif weight <= 10.0:

    cost_ground = weight * 4.0 + 2

  

  else:

    cost_ground = weight * 4.75 + 20

  return cost_ground

def drone_shipping(weight):

  if weight <= 2.0:

    cost_drone = weight * 4.50

  

  elif weight <= 6.0:

    cost_drone = weight * 9.0

  

  elif weight <=10:

    cost_drone = weight * 12.0

  

  else:

    cost_drone = weight * 14.25

  return cost_drone

def cheapest_method(weight):

  g = ground_shipping(weight)

  d = drone_shipping(weight)

  if premium < g and premium < d:

    a, b = "Premium Ground", premium

  elif d < g:

    a, b = "Drone Shipping", d

  else:

    a, b = "Ground Shipping", g

  return "The cheapest shipping method for a " + str(weight) + " pound package is " + a + " at a cost of " + str(round(b, 2))

weight = 3.333

print(cheapest_method(weight))

all_costs = [ground_shipping(weight), premium, drone_shipping(weight)]

round_to_penny = [round(cost, 2) for cost in all_costs]

print("")

print("The costs for Ground Shipping, Premium Shipping, and Drone Shipping respectively: " + str(round_to_penny))

Then despite the fact that Ground Shipping and Drone Shipping both have the price of 30.0 when rounded up to the nearest penny, the output will only show that Drone shipping is the cheapest option (which isn’t necessarily true as it is the same price as Ground Shipping if the weight is 3.333).

But that is a really nice function if we don’t care about rounding up. Still, I wonder if there is some bizarre weight number where two options have the same value no matter how many decimal places we go to. I guess that is extremely unlikely though.

Anyway thanks for the reply. It forced me to code a bit - good practice - and I had to google some things (like how to round up in a list - I had forgotten how to do that and it’s only been a few days since I learnt it on the python 3 course !)

1 Like