Using functions to compare the rates of shipping for books in Python

83 Views Asked by At

I am supposed to grade this assignment for a professor in an introductory computer science class, but I think I am either misinterpreting the assignment or it is kind of a poorly designed problem. Here are the three parts:

  1. Suppose that the cover price of a book is 24.95 dollars, however bookstores get a 40% discount. Shipping costs 3 dollars for the first copy and 75 cents for each additional copy. Write a function wholesale(n) that returns the total wholesale cost for an order of n books.
  2. Write a second wholesale function for a different book that costs 22.95 dollars, has the same discount, but that ships for 3 dollars for the first copy and 85 cents for each additional copy. Call this function wholesale2.
  3. Functions are actually objects themselves, and they have a type. As a result you can pass functions to other functions. Write a function check_cost(p, p2, n) that takes functions p and p2 and an integer n, and returns a Boolean value True if p(n) > p2(n); and False otherwise. Apply it to your wholesale functions by calling: check_cost(wholesale, wholesale2, n) and use different values for n until you find where the order of the costs changes.

In theory this is a pretty basic concept, however the two functions that I have written crossover at zero (and in this context we should only need to consider positive integers), and I feel like this defeats the point of the assignment especially in the context, where one should be cheaper for some number of books, but if you buy in bulk ultimately the other should be cheaper - at least that is what I was expecting.

Here is my chunk of code:

def wholesale(n):
    book_cost = 0.6 * 24.95 * n # the price of the book with a forty percent discount times the number of books
    shipping_cost = 3 + .75*(n-1) # this way shipping is exactly $3 for one book
    total_cost = book_cost + shipping_cost
    return total_cost

def wholesale2(n):
    book_cost = 0.6 * 22.95 * n # the price of the book with a forty percent discount times the number of books
    shipping_cost = 3 + .85*(n-1) # this way shipping is exactly $3 for one book
    total_cost = book_cost + shipping_cost
    return total_cost

def check_cost(p, p2, n):
    if (p > p2):
        return True
    else:
        return False

for n in range(-5, 100):
    print(check_cost(wholesale(n), wholesale2(n), n))

The final statement is just what I was using to determine the crossover, after I realized that it is not at a positive integer point, which again I feel defeats the point of the problem. Have I misinterpreted the question and incorrectly written the two functions? Or is it a poorly designed problem? Additionally, the check_cost function seems poorly designed by the nature he wants, as I feel as if there is no reason to pass the parameter n if we just need to compare the values of the two functions at n.

Please let me know if I am simply overlooking something. I plan to talk to the professor who wrote this assignment, but I wanted to make sure I wasn't missing something obvious first.

2

There are 2 best solutions below

2
Lajos Arpad On

You say that

the two functions that I have written crossover at zero

and my understanding is that you contemplate on the case when n is 0. If so, then your functions as they are written are correctly assessing that book_cost is 0, but incorrectly assessing that shipping_cost is 3. It is not 3, because we only have a shipping cost starting from the first book. Therefore, in your functions it makes sense to check whether n <= 0 and if so, return 0.

Then you say:

The final statement is just what I was using to determine the crossover, after I realized that it is not at a positive integer point, which again I feel defeats the point of the problem. Have I misinterpreted the question and incorrectly written the two functions? Or is it a poorly designed problem?

I think it is deliberate in order to make you think. Because the first is being greater than the second at n = 1 and at each increment of n the difference increases.

So you are supposed to search for the crossover for positive n until you realize that it will not happen (unless you get into a number overflow for an n high-enough). Therefore you either conclude that there is no crossover, or that the crossover is below, depending on what you define as the domain of n. Again, for non-positives your function should return sensible values.

The task does not say anything about the cases when n <= 0, it only speaks about the first book and subsequent books, so it is up to you to handle these edge cases.

Finally, you say:

Additionally, the check_cost function seems poorly designed by the nature he wants, as I feel as if there is no reason to pass the parameter n if we just need to compare the values of the two functions at n.

Here you clearly misunderstood the point. The point was to pass the functions to check_cost and n, but you pass the return value of these functions and n instead. The idea is that if you implement wholesale3, wholesale4, etc., then you should be able to pass them to check_cost.

The idea is to use wholesale and wholesale2 as callbacks, that is, functions that are passed (and not their return values) to check_cost and then those functions are called inside check_cost and their results are compared. This will allow check_cost to compare the result of any two functions for n, including, but not limited to your two wholesale functions.

1
protoncracker On

The purpose of check_cost is to compare the outputs of two functions (p and p2) when passed the same argument n. In the way you've implemented check_cost, you're not actually calling the funcions p and p2 inside check_cost. Instead, you're comparing the function objects themselves, which is not the intended behavior:

def check_cost(p, p2, n):
    return p(n) > p2(n)

And then, when you loop through the values of n to find the crossover point, you're correctly passing the functions wholesale and wholesale2 to check_cost, but the loop starts from -5, which doesn't make sense with the context of the problem that deals with positive integers representing the number of books. What it should be like is:

for n in range(1, 100):
    print(n, check_cost(wholesale, wholesale2, n))

The problem itself is an effective way to practice with functions and arithmetic in Python. Your confusion stemmed from the implementation of check_cost and the misuse of the functions within it.

Stack's here to answer questions, but asking this in stack is not a great way of learning how to do it yourself I guess.

Hope it helps.